Align Sahana Spotter template with the current default template
This commit is contained in:
parent
6f52ea0f1a
commit
967ccc0d44
@ -1,91 +1,91 @@
|
||||
uid,role,description,controller,function,table,entity,uacl,oacl,hidden,system,protected,Notes
|
||||
ANONYMOUS,Anonymous,Unauthenticated users,,,org_organisation,,READ,READ,,,,Required for self-registration
|
||||
ANONYMOUS,Anonymous,,org,sites_for_org,,,READ,READ,,,,Required for self-registration
|
||||
ANONYMOUS,Anonymous,,gis,,,,READ,READ,,,,
|
||||
ANONYMOUS,Anonymous,,vulnerability,,,,READ,READ,,,,
|
||||
ANONYMOUS,Anonymous,,water,,,,READ,READ,,,,
|
||||
ANONYMOUS,Anonymous,,delphi,,,,READ,READ,,,,
|
||||
AUTHENTICATED,Authenticated,Authenticated - all logged-in users,gis,,,,READ,READ,,,,
|
||||
AUTHENTICATED,Authenticated,,vulnerability,,,,READ,READ,,,,
|
||||
AUTHENTICATED,Authenticated,,water,,,,READ,READ,,,,
|
||||
AUTHENTICATED,Authenticated,,delphi,,,,READ,READ,,,,
|
||||
AUTHENTICATED,Authenticated,,impact,,,,READ,READ,,,,
|
||||
AUTHENTICATED,Authenticated,,doc,,,,READ,READ,,,,
|
||||
EDITOR,Editor,Editor - can access & make changes to any unprotected data,pr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,vulnerability,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,survey,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,security,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,fire,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,deploy,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,water,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,budget,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,cap,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,vol,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,delphi,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,org,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,scenario,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,vehicle,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,member,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,cr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,gis,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,asset,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,patient,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,transport,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,po,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,impact,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,dvr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,event,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,msg,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,supply,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,project,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,doc,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,hrm,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,appadmin,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,hms,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,req,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,mpr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,sync,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,inv,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,stats,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,edu,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,dvi,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
EDITOR,Editor,,cms,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,,,,
|
||||
uid,role,description,controller,function,table,entity,uacl,oacl,Notes
|
||||
ANONYMOUS,Anonymous,Unauthenticated users,,,org_organisation,,READ,READ,Required for self-registration
|
||||
ANONYMOUS,Anonymous,,org,sites_for_org,,,READ,READ,Required for self-registration
|
||||
ANONYMOUS,Anonymous,,gis,,,,READ,READ,
|
||||
ANONYMOUS,Anonymous,,vulnerability,,,,READ,READ,
|
||||
ANONYMOUS,Anonymous,,water,,,,READ,READ,
|
||||
ANONYMOUS,Anonymous,,delphi,,,,READ,READ,
|
||||
AUTHENTICATED,Authenticated,Authenticated - all logged-in users,gis,,,,READ,READ,
|
||||
AUTHENTICATED,Authenticated,,vulnerability,,,,READ,READ,
|
||||
AUTHENTICATED,Authenticated,,water,,,,READ,READ,
|
||||
AUTHENTICATED,Authenticated,,delphi,,,,READ,READ,
|
||||
AUTHENTICATED,Authenticated,,impact,,,,READ,READ,
|
||||
AUTHENTICATED,Authenticated,,doc,,,,READ,READ,
|
||||
EDITOR,Editor,Editor - can access & make changes to any unprotected data,pr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,vulnerability,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,survey,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,security,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,fire,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,deploy,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,water,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,budget,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,cap,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,vol,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,delphi,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,org,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,scenario,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,vehicle,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,member,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,cr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,gis,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,asset,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,patient,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,transport,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,po,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,impact,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,dvr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,event,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,msg,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,supply,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,project,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,doc,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,hrm,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,appadmin,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,hms,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,req,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,mpr,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,sync,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,inv,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,stats,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,edu,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,dvi,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
EDITOR,Editor,,cms,,,,ALL,CREATE|READ|UPDATE|REVIEW|APPROVE,
|
||||
MAP_ADMIN,Map Admin,"Complementary role: FULL access mode only to the maps and their configurations
|
||||
When to assign: Staff Directors.",gis,,,,ALL,ALL,,,,
|
||||
ORG_ADMIN,Organization Admin,,org,,,,ALL,ALL,,,,
|
||||
ORG_GROUP_ADMIN,Organziation Group Admin,,,,,,,,,,,
|
||||
When to assign: Staff Directors.",gis,,,,ALL,ALL,
|
||||
ORG_ADMIN,Organization Admin,,org,,,,ALL,ALL,
|
||||
ORG_GROUP_ADMIN,Organzation Group Admin,,,,,,,,
|
||||
medical_admin,Medical Details Admin,"Complementary role: FULL access but only to medical data of registered evacuees. It must be assigned with other roles to grant access to the other types of data.
|
||||
When to assign: Medical Staff.",patient,,,,ALL,ALL,,,,
|
||||
medical_admin,Medical Details Admin,,hms,,,,ALL,ALL,,,,
|
||||
medical_admin,Medical Details Admin,,dvi,,,,ALL,ALL,,,,
|
||||
notification_sender,Notification Sender,,msg,,,,ALL,ALL,,,,
|
||||
When to assign: Medical Staff.",patient,,,,ALL,ALL,
|
||||
medical_admin,Medical Details Admin,,hms,,,,ALL,ALL,
|
||||
medical_admin,Medical Details Admin,,dvi,,,,ALL,ALL,
|
||||
notification_sender,Notification Sender,,msg,,,,ALL,ALL,
|
||||
org_reader,Organization Reader,"Complementary role: Access in ""READ only"" mode to Organization data and its branches
|
||||
When to assign: Staff Directors",org,,,,READ,READ,,,,
|
||||
When to assign: Staff Directors",org,,,,READ,READ,
|
||||
private_user_editor,Private User Editor,"FULL access to modules Evacuees and Shelter.
|
||||
When to assign: private user member of a shelter / Organization and committed to provide assistance to some evacuees",cr,,,,ALL,ALL,,,,
|
||||
private_user_editor,Private User Editor,,dvr,,,,ALL,ALL,,,,
|
||||
When to assign: private user member of a shelter / Organization and committed to provide assistance to some evacuees",cr,,,,ALL,ALL,
|
||||
private_user_editor,Private User Editor,,dvr,,,,ALL,ALL,
|
||||
private_user_reader,Private User Reader,"Access in ""READ only"" mode to modules Evacuees and Shelter.
|
||||
When to assign: private user member of a Shelter / Organization and committed to provide assistance to some evacuees.",cr,,,,READ,READ,,,,
|
||||
private_user_reader,Private User Reader,,dvr,,,,READ,READ,,,,
|
||||
When to assign: private user member of a Shelter / Organization and committed to provide assistance to some evacuees.",cr,,,,READ,READ,
|
||||
private_user_reader,Private User Reader,,dvr,,,,READ,READ,
|
||||
public_auth_editor,Public Authority Editor,"FULL access to modules Evacuees and Shelter.
|
||||
When to assign: supervisor user member of local government office with the rights to register data.",cr,,,,ALL,ALL,,,,
|
||||
public_auth_editor,Public Authority Editor,,dvr,,,,ALL,ALL,,,,
|
||||
public_auth_editor,Public Authority Editor,,mpr,,,,READ,READ,,,,
|
||||
When to assign: supervisor user member of local government office with the rights to register data.",cr,,,,ALL,ALL,
|
||||
public_auth_editor,Public Authority Editor,,dvr,,,,ALL,ALL,
|
||||
public_auth_editor,Public Authority Editor,,mpr,,,,READ,READ,
|
||||
public_auth_reader,Public Authority Reader,"Access in ""READ only"" mode to modules Evacuees and Shelter.
|
||||
When to assign: supervisor user member of a local government office.",dvr,,,,READ,READ,,,,
|
||||
When to assign: supervisor user member of a local government office.",dvr,,,,READ,READ,
|
||||
staff_admin,Staff Admin,"FULL access to modules Staff, Volunteer, Evacuees and Shelter.
|
||||
When to assign: Staff assigned to manage one or more shelters.",vol,,,,ALL,ALL,,,,
|
||||
staff_admin,Staff Admin,,cr,,,,ALL,ALL,,,,
|
||||
staff_admin,Staff Admin,,dvr,,,,ALL,ALL,,,,
|
||||
staff_admin,Staff Admin,,hrm,,,,ALL,ALL,,,,
|
||||
When to assign: Staff assigned to manage one or more shelters.",vol,,,,ALL,ALL,
|
||||
staff_admin,Staff Admin,,cr,,,,ALL,ALL,
|
||||
staff_admin,Staff Admin,,dvr,,,,ALL,ALL,
|
||||
staff_admin,Staff Admin,,hrm,,,,ALL,ALL,
|
||||
staff_reader,Staff Reader,"Access in ""READ only"" mode to modules Staff, Volunteer, Evacuees and Shelter.
|
||||
When to assign: Staff assigned to manage one or more shelters.",vol,,,,READ,READ,,,,
|
||||
staff_reader,Staff Reader,,cr,,,,READ,READ,,,,
|
||||
staff_reader,Staff Reader,,dvr,,,,READ,READ,,,,
|
||||
staff_reader,Staff Reader,,hrm,,,,READ,READ,,,,
|
||||
When to assign: Staff assigned to manage one or more shelters.",vol,,,,READ,READ,
|
||||
staff_reader,Staff Reader,,cr,,,,READ,READ,
|
||||
staff_reader,Staff Reader,,dvr,,,,READ,READ,
|
||||
staff_reader,Staff Reader,,hrm,,,,READ,READ,
|
||||
vol_editor,Volunteer Editor,"FULL access to modules Evacuees and Shelter.
|
||||
When to assign: volunteer (trusted person) volunteer who provides assistance to some evacuees inside a well-defined group of shelters.",cr,,,,ALL,ALL,,,,
|
||||
vol_editor,Volunteer Editor,,dvr,,,,ALL,ALL,,,,
|
||||
When to assign: volunteer (trusted person) volunteer who provides assistance to some evacuees inside a well-defined group of shelters.",cr,,,,ALL,ALL,
|
||||
vol_editor,Volunteer Editor,,dvr,,,,ALL,ALL,
|
||||
vol_reader,Volunteer Reader,"Access in ""READ only"" mode to modules Evacuees and Shelter.
|
||||
When to assign: volunteer who provides assistance to some evacuees inside a well- defined group of shelters.",cr,,,,READ,READ,,,,
|
||||
vol_reader,Volunteer Reader,,dvr,,,,READ,READ,,,,
|
||||
When to assign: volunteer who provides assistance to some evacuees inside a well- defined group of shelters.",cr,,,,READ,READ,
|
||||
vol_reader,Volunteer Reader,,dvr,,,,READ,READ,
|
||||
|
|
@ -27,6 +27,7 @@ def config(settings):
|
||||
#settings.base.theme = "default"
|
||||
|
||||
# Enable Guided Tours
|
||||
# - defaults to module enabled or not
|
||||
#settings.base.guided_tour = True
|
||||
|
||||
# Authentication settings
|
||||
@ -128,6 +129,7 @@ def config(settings):
|
||||
# Uncomment this to enable the creation of new locations if a user logs in from an unknown location. Warning: This may lead to many useless location entries
|
||||
#settings.auth.create_unknown_locations = True
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# L10n settings
|
||||
# Languages used in the deployment (used for Language Toolbar, GIS Locations, etc)
|
||||
# http://www.loc.gov/standards/iso639-2/php/code_list.php
|
||||
@ -347,8 +349,8 @@ def config(settings):
|
||||
# 6: Apply Controller, Function, Table ACLs and Entity Realm
|
||||
# 7: Apply Controller, Function, Table ACLs and Entity Realm + Hierarchy
|
||||
# 8: Apply Controller, Function, Table ACLs, Entity Realm + Hierarchy and Delegations
|
||||
#
|
||||
settings.security.policy = 7 # Organisation-ACLs
|
||||
|
||||
settings.security.policy = 7 # Organization ACLs
|
||||
|
||||
# Ownership-rule for records without owner:
|
||||
# True = not owned by any user (strict ownership, default)
|
||||
@ -787,7 +789,7 @@ def config(settings):
|
||||
# Make Services Hierarchical
|
||||
settings.org.services_hierarchical = True
|
||||
# Set the length of the auto-generated org/site code the default is 10
|
||||
#settings.org.site_code_len = 10
|
||||
#settings.org.site_code_len = 3
|
||||
# Set the label for Sites
|
||||
settings.org.site_label = "Facility"
|
||||
# Uncomment to show the date when a Site (Facilities-only for now) was last contacted
|
||||
@ -936,7 +938,7 @@ def config(settings):
|
||||
settings.inv.recv_shortname = "ARDR"
|
||||
# Types common to both Send and Receive
|
||||
settings.inv.shipment_types = {
|
||||
0: T(""),
|
||||
0: "", # current.messages["NONE"] but current.messages is defined only after 000_config.py is executed
|
||||
1: T("Other Warehouse"),
|
||||
2: T("Donation"),
|
||||
3: T("Foreign Donation"),
|
||||
@ -952,7 +954,7 @@ def config(settings):
|
||||
# 34: T("Purchase"),
|
||||
# }
|
||||
#settings.inv.item_status = {
|
||||
# 0: current.messages["NONE"],
|
||||
# 0: "", # current.messages["NONE"] but current.messages is defined only after 000_config.py is executed
|
||||
# 1: T("Dump"),
|
||||
# 2: T("Sale"),
|
||||
# 3: T("Reject"),
|
||||
@ -1168,9 +1170,8 @@ def config(settings):
|
||||
settings.modules = OrderedDict([
|
||||
# Core modules which shouldn't be disabled
|
||||
("default", Storage(
|
||||
name_nice = T("Home"),
|
||||
name_nice = T("Default"),
|
||||
restricted = False, # Use ACLs to control access to this module
|
||||
access = None, # All Users (inc Anonymous) can see this module in the default menu & access the controller
|
||||
module_type = None # This item is not shown in the menu
|
||||
)),
|
||||
("admin", Storage(
|
||||
@ -1211,7 +1212,7 @@ def config(settings):
|
||||
module_type = None,
|
||||
)),
|
||||
("translate", Storage(
|
||||
name_nice = T("Translation Functionality"),
|
||||
name_nice = T("Translation"),
|
||||
#description = "Selective translation of strings based on module.",
|
||||
module_type = None,
|
||||
)),
|
||||
@ -1281,9 +1282,8 @@ def config(settings):
|
||||
#("proc", Storage(
|
||||
# name_nice = T("Procurement"),
|
||||
# #description = "Ordering & Purchasing of Goods & Services",
|
||||
# restricted = True,
|
||||
# module_type = 10
|
||||
# )),
|
||||
#)),
|
||||
("asset", Storage(
|
||||
name_nice = T("Assets"),
|
||||
#description = "Recording and Assigning Assets",
|
||||
@ -1309,47 +1309,11 @@ def config(settings):
|
||||
restricted = True,
|
||||
module_type = 2
|
||||
)),
|
||||
#("survey", Storage(
|
||||
# name_nice = T("Surveys"),
|
||||
# #description = "Create, enter, and manage surveys.",
|
||||
# restricted = True,
|
||||
# module_type = 5,
|
||||
#)),
|
||||
("dc", Storage(
|
||||
name_nice = T("Assessments"),
|
||||
#description = "Data collection tool",
|
||||
("stats", Storage(
|
||||
name_nice = T("Statistics"),
|
||||
#description = "Manages statistics",
|
||||
restricted = True,
|
||||
module_type = 5
|
||||
)),
|
||||
("cr", Storage(
|
||||
name_nice = T("Shelters"),
|
||||
#description = "Tracks the location, capacity and breakdown of victims in Shelters",
|
||||
restricted = True,
|
||||
module_type = 9
|
||||
)),
|
||||
("hms", Storage(
|
||||
name_nice = T("Hospitals"),
|
||||
#description = "Helps to monitor status of hospitals",
|
||||
restricted = True,
|
||||
module_type = 9
|
||||
)),
|
||||
#("disease", Storage(
|
||||
# name_nice = T("Disease Tracking"),
|
||||
# #description = "Helps to track cases and trace contacts in disease outbreaks",
|
||||
# restricted = True,
|
||||
# module_type = 10
|
||||
#)),
|
||||
#("br", Storage(
|
||||
# name_nice = T("Beneficiary Registry"),
|
||||
# #description = "Beneficiary Registry and Case Management",
|
||||
# restricted = True,
|
||||
# module_type = 10,
|
||||
#)),
|
||||
("dvr", Storage(
|
||||
name_nice = T("Disaster Victim Registry"),
|
||||
#description = "Allow affected individuals & households to register to receive compensation and distributions",
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
module_type = None,
|
||||
)),
|
||||
("event", Storage(
|
||||
name_nice = T("Events"),
|
||||
@ -1357,16 +1321,29 @@ def config(settings):
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
("transport", Storage(
|
||||
name_nice = T("Transport"),
|
||||
("br", Storage(
|
||||
name_nice = T("Beneficiary Registry"),
|
||||
#description = "Allow affected individuals & households to register to receive compensation and distributions",
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
("stats", Storage(
|
||||
name_nice = T("Statistics"),
|
||||
#description = "Manages statistics",
|
||||
("cr", Storage(
|
||||
name_nice = T("Shelters"),
|
||||
#description = "Tracks the location, capacity and breakdown of victims in Shelters",
|
||||
restricted = True,
|
||||
module_type = None,
|
||||
module_type = 9
|
||||
)),
|
||||
("dc", Storage(
|
||||
name_nice = T("Assessments"),
|
||||
#description = "Data collection tool",
|
||||
restricted = True,
|
||||
module_type = 5
|
||||
)),
|
||||
("hms", Storage(
|
||||
name_nice = T("Hospitals"),
|
||||
#description = "Helps to monitor status of hospitals",
|
||||
restricted = True,
|
||||
module_type = 9
|
||||
)),
|
||||
("member", Storage(
|
||||
name_nice = T("Members"),
|
||||
@ -1386,45 +1363,28 @@ def config(settings):
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
# Deprecated: Replaced by event
|
||||
#("irs", Storage(
|
||||
# name_nice = T("Incidents"),
|
||||
# #description = "Incident Reporting System",
|
||||
# restricted = True,
|
||||
#("disease", Storage(
|
||||
# name_nice = T("Disease Tracking"),
|
||||
# #description = "Helps to track cases and trace contacts in disease outbreaks",
|
||||
# module_type = 10
|
||||
#)),
|
||||
("dvi", Storage(
|
||||
name_nice = T("Disaster Victim Identification"),
|
||||
#description = "Disaster Victim Identification",
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
#access = "|DVI|", # Only users with the DVI role can see this module in the default menu & access the controller
|
||||
)),
|
||||
("edu", Storage(
|
||||
name_nice = T("Schools"),
|
||||
#description = "Helps to monitor status of schools",
|
||||
restricted = True,
|
||||
module_type = 10
|
||||
)),
|
||||
("mpr", Storage(
|
||||
name_nice = T("Missing Person Registry"),
|
||||
#description = "Helps to report and search for missing persons",
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
# https://github.com/sahana/eden/issues/1562
|
||||
#("vulnerability", Storage(
|
||||
# name_nice = T("Vulnerability"),
|
||||
# #description = "Manages vulnerability indicators",
|
||||
# restricted = True,
|
||||
# module_type = 10,
|
||||
#)),
|
||||
("fire", Storage(
|
||||
name_nice = T("Fire Stations"),
|
||||
#description = "Fire Station Management",
|
||||
restricted = True,
|
||||
module_type = 1,
|
||||
)),
|
||||
("transport", Storage(
|
||||
name_nice = T("Transport"),
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
("water", Storage(
|
||||
name_nice = T("Water"),
|
||||
#description = "Flood Gauges show water levels in various parts of the country",
|
||||
@ -1449,6 +1409,36 @@ def config(settings):
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
# Vulnerability temporarily disabled - https://github.com/sahana/eden/issues/1562
|
||||
#("vulnerability", Storage(
|
||||
# name_nice = T("Vulnerability"),
|
||||
# #description = "Manages vulnerability indicators",
|
||||
# module_type = 10,
|
||||
# )),
|
||||
("work", Storage(
|
||||
name_nice = T("Jobs"),
|
||||
#description = "Simple Volunteer Jobs Management",
|
||||
restricted = False,
|
||||
module_type = None,
|
||||
)),
|
||||
# Deprecated: Replaced by BR
|
||||
#("dvr", Storage(
|
||||
# name_nice = T("Beneficiary Registry"),
|
||||
# #description = "Disaster Victim Registry",
|
||||
# module_type = 10
|
||||
#)),
|
||||
# Deprecated: Replaced by event
|
||||
#("irs", Storage(
|
||||
# name_nice = T("Incidents"),
|
||||
# #description = "Incident Reporting System",
|
||||
# module_type = 10
|
||||
#)),
|
||||
# Deprecated: Replaced by DC
|
||||
#("survey", Storage(
|
||||
# name_nice = T("Surveys"),
|
||||
# #description = "Create, enter, and manage surveys.",
|
||||
# module_type = 5,
|
||||
#)),
|
||||
# These are specialist modules
|
||||
("cap", Storage(
|
||||
name_nice = T("CAP"),
|
||||
@ -1456,11 +1446,23 @@ def config(settings):
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
("dvi", Storage(
|
||||
name_nice = T("Disaster Victim Identification"),
|
||||
#description = "Disaster Victim Identification",
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
#access = "|DVI|", # Only users with the DVI role can see this module in the default menu & access the controller
|
||||
)),
|
||||
("mpr", Storage(
|
||||
name_nice = T("Missing Person Registry"),
|
||||
#description = "Helps to report and search for missing persons",
|
||||
restricted = True,
|
||||
module_type = 10,
|
||||
)),
|
||||
# Requires RPy2 & PostgreSQL
|
||||
#("climate", Storage(
|
||||
# name_nice = T("Climate"),
|
||||
# #description = "Climate data portal",
|
||||
# restricted = True,
|
||||
# module_type = 10,
|
||||
#)),
|
||||
("delphi", Storage(
|
||||
@ -1473,7 +1475,6 @@ def config(settings):
|
||||
#("building", Storage(
|
||||
# name_nice = T("Building Assessments"),
|
||||
# #description = "Building Safety Assessments",
|
||||
# restricted = True,
|
||||
# module_type = 10,
|
||||
#)),
|
||||
# Deprecated by Surveys module
|
||||
@ -1481,13 +1482,11 @@ def config(settings):
|
||||
#("assess", Storage(
|
||||
# name_nice = T("Assessments"),
|
||||
# #description = "Rapid Assessments & Flexible Impact Assessments",
|
||||
# restricted = True,
|
||||
# module_type = 10,
|
||||
#)),
|
||||
#("impact", Storage(
|
||||
# name_nice = T("Impacts"),
|
||||
# #description = "Used by Assess",
|
||||
# restricted = True,
|
||||
# module_type = None,
|
||||
#)),
|
||||
#("ocr", Storage(
|
||||
@ -1496,12 +1495,6 @@ def config(settings):
|
||||
# restricted = False,
|
||||
# module_type = None,
|
||||
#)),
|
||||
("work", Storage(
|
||||
name_nice = T("Jobs"),
|
||||
#description = "Simple Volunteer Jobs Management",
|
||||
restricted = False,
|
||||
module_type = None,
|
||||
)),
|
||||
])
|
||||
|
||||
# END =========================================================================
|
||||
|
@ -13,6 +13,8 @@ plugins/jquery.tagit.css
|
||||
ui/core.css
|
||||
ui/autocomplete.css
|
||||
ui/button.css
|
||||
#ui/checkboxradio.css
|
||||
#ui/controlgroup.css
|
||||
ui/datepicker.css
|
||||
ui/dialog.css
|
||||
# Needed for Delphi
|
||||
@ -29,6 +31,7 @@ ui/tabs.css
|
||||
ui/fgtimepicker.css
|
||||
ui/multiselect.css
|
||||
ui/timepicker-addon.css
|
||||
#calendars/ui.calendars.picker.css
|
||||
#calendars/ui-smoothness.calendars.picker.css
|
||||
../themes/foundation/jquery-ui.theme.css
|
||||
gis/style.css
|
||||
|
@ -10,8 +10,8 @@ Epidemic,,
|
||||
Explosion,,
|
||||
Extreme Winter Conditions,,
|
||||
Fire,,
|
||||
Flash Floods,,
|
||||
Floods,,
|
||||
Flash Flood,,
|
||||
Flood,,
|
||||
Food Security,,
|
||||
Heat Wave,,
|
||||
Land Slide,,
|
||||
|
|
@ -26,7 +26,7 @@ SITE_DEFAULT,,"State / Province","County / District","City / Town / Village","Vi
|
||||
,CO,Department,Municipality,Corregimiento,
|
||||
,CR,Province,Canton,District,
|
||||
,CU,Province,Municipality,
|
||||
,DE,"Federal State","Rural District / District","Town / Municipality",Village,
|
||||
,DE,"Federal State","Rural District / District","Town / Municipality",Locality,
|
||||
,DO,Province,Municipality,,,,
|
||||
,EC,Province,Canton,Parish,,,
|
||||
,FI,Regional State Administrative Agency,Region,Sub-region,Municipality,,
|
||||
@ -44,12 +44,14 @@ SITE_DEFAULT,,"State / Province","County / District","City / Town / Village","Vi
|
||||
,IN,State,District,Sub-District,,,
|
||||
,IQ,Province,District,,,,
|
||||
,IT,Region,Province,Commune,,,
|
||||
,JO,Governorate,District,Subdistrict,,,
|
||||
,KE,County,Constituency,Location,SubLocation,
|
||||
,KG,"Oblast / State City","District (Rayon) / Oblast City","Town / Village Group",Village,,
|
||||
,KH,Province,District,Commune,Village,
|
||||
,KI,Island Council,,,,
|
||||
,KZ,Province,District,,,,
|
||||
,LA,Province,District,Village,,,
|
||||
,LB,Governorate,District,,,,
|
||||
,LK,Province,District,Divisional Secretariat,Grama Niladhari,,
|
||||
,LR,County,District,Clan,,,
|
||||
,LT,County,Municipality,Eldership,,,
|
||||
@ -70,6 +72,8 @@ SITE_DEFAULT,,"State / Province","County / District","City / Town / Village","Vi
|
||||
,PG,Province,District,LLG,Village,,
|
||||
,PH,Region,Province,"City / Municipality",Barangay,,
|
||||
,PK,Province,District,Tehsil,Union Council,Village,
|
||||
,PL,Province,County,Municipality,,,
|
||||
,PR,Municipality,Barrio,,,,
|
||||
,PY,Department,District,"City / Town / Village",,,
|
||||
,RS,District,"Municipality / City",,,,
|
||||
,SB,Province,Ward,,
|
||||
@ -77,18 +81,18 @@ SITE_DEFAULT,,"State / Province","County / District","City / Town / Village","Vi
|
||||
,SG,Region,,,
|
||||
,SL,Province,District,Chiefdom,,,
|
||||
,SV,Department,Municipality,
|
||||
,SY,Governorate,District,Subdistrict
|
||||
,TD,Region,Department,Sub-Prefecture,Canton,
|
||||
,TH,Province,District,Sub-District,,,
|
||||
,TJ,Province,District,Jamoat,Village,,
|
||||
,TL,District,SubDistrict,Suco,Aldeia,,
|
||||
,TM,Province,District,,,,
|
||||
,TO,Island Group,District,,,,
|
||||
,TR,City,Town,District,,,
|
||||
,TR,Province,District / Town,Neighborhood / Village,,,
|
||||
,TV,Island Council,,,,
|
||||
,PR,Municipality,Barrio,,,,
|
||||
,US,State,County,City,Neighborhood,,False
|
||||
,UZ,Province,District,,,,
|
||||
,VU,Province,Area Council,,
|
||||
,VN,Province,District,Commune,,,
|
||||
,VU,Province,Area Council,,
|
||||
,XK,District,Municipality,,,,
|
||||
,YE,Governorate,District,Sub-District,Village,,
|
||||
|
Can't render this file because it has a wrong number of fields in line 6.
|
@ -12,4 +12,4 @@ Population Density 2010 (Alternate server),GPWv3,http://sedac.ciesin.columbia.ed
|
||||
Population Density 2000 (Persons per km2),GRUMPv1,http://beta.sedac.ciesin.columbia.edu:8080/geoserver/wms?,grump-v1:grump-v1-population-density_2000 ,Population,WGS84,True,False,False,True,0.8,image/png,False,,,
|
||||
Precipitation forecast,,http://geo.weatheroffice.gc.ca/geomet/?,GDPS.ETA_PR,Weather,,True,False,False,True,0.4,image/png,False,http://geo.weatheroffice.gc.ca/geomet/?LANG=E%26SERVICE=WMS%26VERSION=1.1.1%26REQUEST=GetLegendGraphic%26STYLE=PRECIPMM%26LAYER=GDPS.ETA_PR%26format=image/png,PRECIPMM,
|
||||
Cloud forecast,,http://geo.weatheroffice.gc.ca/geomet/?,GDPS.ETA_NT,Weather,,True,False,False,True,0.4,image/png,False,http://geo.weatheroffice.gc.ca/geomet/?LANG=E%26SERVICE=WMS%26VERSION=1.1.1%26REQUEST=GetLegendGraphic%26STYLE=CLOUD%26LAYER=GDPS.ETA_NT%26format=image/png,CLOUD,
|
||||
Sea Level: Rise of 2m,Data from https://www.cresis.ku.edu/data/sea-level-rise-maps,http://lacrmt.sahanafoundation.org:8080/geoserver/wms?,lacrmt:inund2,Hazards,,True,False,False,True,0.4,image/png,False,,,
|
||||
Sea Level: Rise of 2m,Data from https://www.cresis.ku.edu/data/sea-level-rise-maps,http://lacrmt.sahanafoundation.org:8080/geoserver/wms?,lacrmt:inund2,Hazards,,False,False,False,True,0.4,image/png,False,,,
|
||||
|
|
@ -5,7 +5,7 @@
|
||||
|
||||
Template-specific Monitoring Tasks are defined here.
|
||||
|
||||
@copyright: 2014-2019 (c) Sahana Software Foundation
|
||||
@copyright: 2014-2020 (c) Sahana Software Foundation
|
||||
@license: MIT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
@ -33,11 +33,26 @@
|
||||
__all__ = ("S3Monitor",)
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from gluon import current
|
||||
#from gluon.tools import fetch
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
REQUESTS = None
|
||||
else:
|
||||
REQUESTS = True
|
||||
|
||||
INSTANCE_TYPES = {"prod": 1,
|
||||
"setup": 2,
|
||||
"test": 3,
|
||||
"demo": 4,
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
class S3Monitor(object):
|
||||
@ -45,11 +60,366 @@ class S3Monitor(object):
|
||||
Monitoring Check Scripts
|
||||
"""
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def diskspace(task_id, run_id):
|
||||
"""
|
||||
Test the free diskspace
|
||||
"""
|
||||
|
||||
db = current.db
|
||||
s3db = current.s3db
|
||||
|
||||
# Read the Task Options
|
||||
ttable = s3db.setup_monitor_task
|
||||
task = db(ttable.id == task_id).select(ttable.options,
|
||||
ttable.server_id,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
options = task.options or {}
|
||||
options_get = options.get
|
||||
|
||||
partition = options_get("partition", "/") # Root Partition by default
|
||||
space_min = options_get("space_min", 1000000000) # 1 Gb
|
||||
|
||||
stable = s3db.setup_server
|
||||
server = db(stable.id == task.server_id).select(stable.host_ip,
|
||||
stable.remote_user,
|
||||
stable.private_key,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
|
||||
if server.host_ip == "127.0.0.1":
|
||||
result = os.statvfs(partition)
|
||||
space = result.f_bavail * result.f_frsize
|
||||
percent = float(result.f_bavail) / float(result.f_blocks) * 100
|
||||
if space < space_min:
|
||||
return {"result": "Warning: %s free (%d%%)" % \
|
||||
(_bytes_to_size_string(space), percent),
|
||||
"status": 2,
|
||||
}
|
||||
|
||||
return {"result": "OK. %s free (%d%%)" % \
|
||||
(_bytes_to_size_string(space), percent),
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
ssh = _ssh(server)
|
||||
if isinstance(ssh, dict):
|
||||
# We failed to login
|
||||
return ssh
|
||||
|
||||
command = "import os;result=os.statvfs('%s');print(result.f_bavail);print(result.f_frsize);print(result.f_blocks)" % partition
|
||||
stdin, stdout, stderr = ssh.exec_command('python -c "%s"' % command)
|
||||
outlines = stdout.readlines()
|
||||
ssh.close()
|
||||
|
||||
f_bavail = int(outlines[0])
|
||||
f_frsize = int(outlines[1])
|
||||
f_blocks = int(outlines[2])
|
||||
|
||||
space = f_bavail * f_frsize
|
||||
percent = float(f_bavail) / float(f_blocks) * 100
|
||||
if space < space_min:
|
||||
return {"result": "Warning: %s free (%d%%)" % \
|
||||
(_bytes_to_size_string(space), percent),
|
||||
"status": 2,
|
||||
}
|
||||
|
||||
return {"result": "OK. %s free (%d%%)" % \
|
||||
(_bytes_to_size_string(space), percent),
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def eden(task_id, run_id):
|
||||
"""
|
||||
Test that we can retrieve the public_url, which checks:
|
||||
- DNS must resolve to correct IP
|
||||
- Server must be up
|
||||
- Firewall cannot be blocking
|
||||
- Web server is running
|
||||
- UWSGI is running
|
||||
- Database is running
|
||||
- Eden can connect to Database
|
||||
"""
|
||||
|
||||
if REQUESTS is None:
|
||||
return {"result": "Critical: Requests library not installed",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
db = current.db
|
||||
s3db = current.s3db
|
||||
|
||||
# Read the Task Options
|
||||
ttable = s3db.setup_monitor_task
|
||||
task = db(ttable.id == task_id).select(ttable.options,
|
||||
ttable.deployment_id,
|
||||
ttable.server_id,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
options = task.options or {}
|
||||
options_get = options.get
|
||||
|
||||
appname = options_get("appname", "eden")
|
||||
public_url = options_get("public_url")
|
||||
timeout = options_get("timeout", 60) # 60s (default is no timeout!)
|
||||
|
||||
if not public_url:
|
||||
deployment_id = task.deployment_id
|
||||
if deployment_id:
|
||||
# Read from the instance
|
||||
itable = s3db.setup_instance
|
||||
query = (itable.deployment_id == deployment_id) & \
|
||||
(itable.type == 1)
|
||||
instance = db(query).select(itable.url,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
if instance:
|
||||
public_url = instance.url
|
||||
if not public_url:
|
||||
# Use the server name
|
||||
stable = s3db.setup_server
|
||||
server = db(stable.id == task.server_id).select(stable.name,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
public_url = "https://%s" % server.name
|
||||
|
||||
url = "%(public_url)s/%(appname)s/default/public_url" % {"appname": appname,
|
||||
"public_url": public_url,
|
||||
}
|
||||
|
||||
try:
|
||||
r = requests.get(url, timeout = timeout) # verify=True
|
||||
except requests.exceptions.SSLError:
|
||||
# e.g. Expired Certificate
|
||||
import traceback
|
||||
tb_parts = sys.exc_info()
|
||||
tb_text = "".join(traceback.format_exception(tb_parts[0],
|
||||
tb_parts[1],
|
||||
tb_parts[2]))
|
||||
return {"result": "Critical: SSL Error\n\n%s" % tb_text,
|
||||
"status": 3,
|
||||
}
|
||||
except requests.exceptions.Timeout:
|
||||
import traceback
|
||||
tb_parts = sys.exc_info()
|
||||
tb_text = "".join(traceback.format_exception(tb_parts[0],
|
||||
tb_parts[1],
|
||||
tb_parts[2]))
|
||||
return {"result": "Critical: Timeout Error\n\n%s" % tb_text,
|
||||
"status": 3,
|
||||
}
|
||||
except requests.exceptions.TooManyRedirects:
|
||||
import traceback
|
||||
tb_parts = sys.exc_info()
|
||||
tb_text = "".join(traceback.format_exception(tb_parts[0],
|
||||
tb_parts[1],
|
||||
tb_parts[2]))
|
||||
return {"result": "Critical: TooManyRedirects Error\n\n%s" % tb_text,
|
||||
"status": 3,
|
||||
}
|
||||
except requests.exceptions.ConnectionError:
|
||||
# e.g. DNS Error
|
||||
import traceback
|
||||
tb_parts = sys.exc_info()
|
||||
tb_text = "".join(traceback.format_exception(tb_parts[0],
|
||||
tb_parts[1],
|
||||
tb_parts[2]))
|
||||
return {"result": "Critical: Connection Error\n\n%s" % tb_text,
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
if r.status_code != 200:
|
||||
return {"result": "Critical: HTTP Error. Status = %s" % r.status_code,
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
if r.text != public_url:
|
||||
return {"result": "Critical: Page returned '%s' instead of '%s'" % \
|
||||
(r.text, public_url),
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
latency = int(r.elapsed.microseconds / 1000)
|
||||
latency_max = options_get("latency_max", 2000) # 2 seconds
|
||||
if latency > latency_max:
|
||||
return {"result": "Warning: Latency of %s exceeded threshold of %s." % \
|
||||
(latency, latency_max),
|
||||
"status": 2,
|
||||
}
|
||||
|
||||
return {"result": "OK. Latency: %s" % latency,
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def email_round_trip(task_id, run_id):
|
||||
"""
|
||||
Check that a Mailbox is being Polled & Parsed OK and can send replies
|
||||
"""
|
||||
|
||||
# Read the Task Options
|
||||
ttable = current.s3db.setup_monitor_task
|
||||
task = current.db(ttable.id == task_id).select(ttable.options,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
options = task.options or {}
|
||||
options_get = options.get
|
||||
|
||||
to = options_get("to", None)
|
||||
if not to:
|
||||
return {"result": "Critical: No recipient address specified",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
subject = options_get("subject", "")
|
||||
message = options_get("message", "")
|
||||
reply_to = options_get("reply_to")
|
||||
if not reply_to:
|
||||
# Use the outbound email address
|
||||
reply_to = current.deployment_settings.get_mail_sender()
|
||||
if not reply_to:
|
||||
return {"result": "Critical: No reply_to specified",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
# Append the run_id for the remote parser to identify as a monitoring message & return to us to be able to match the run
|
||||
message = "%s\n%s" % (message, ":run_id:%s:" % run_id)
|
||||
|
||||
# Append the reply_to address for the remote parser
|
||||
message = "%s\n%s" % (message, ":reply_to:%s:" % reply_to)
|
||||
|
||||
# Send the Email
|
||||
result = current.msg.send_email(to,
|
||||
subject,
|
||||
message,
|
||||
reply_to = reply_to)
|
||||
|
||||
if result:
|
||||
# Schedule a task to see if the reply has arrived
|
||||
wait = options_get("wait", 60) # Default = 60 minutes
|
||||
start_time = datetime.datetime.utcnow() + \
|
||||
datetime.timedelta(minutes = wait)
|
||||
current.s3task.schedule_task("setup_monitor_check_email_reply",
|
||||
args = [run_id],
|
||||
start_time = start_time,
|
||||
timeout = 300, # seconds
|
||||
repeats = 1 # one-time
|
||||
)
|
||||
return {"result": "OK so far: Waiting for Reply",
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
return {"result": "Critical: Unable to send Email",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def http(task_id, run_id):
|
||||
"""
|
||||
Test that HTTP is accessible
|
||||
"""
|
||||
|
||||
if REQUESTS is None:
|
||||
return {"result": "Critical: Requests library not installed",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def https(task_id, run_id):
|
||||
"""
|
||||
Test that HTTP is accessible
|
||||
"""
|
||||
|
||||
if REQUESTS is None:
|
||||
return {"result": "Critical: Requests library not installed",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def load_average(task_id, run_id):
|
||||
"""
|
||||
Test the Load Average
|
||||
"""
|
||||
|
||||
db = current.db
|
||||
s3db = current.s3db
|
||||
|
||||
# Read the Task Options
|
||||
ttable = s3db.setup_monitor_task
|
||||
task = db(ttable.id == task_id).select(ttable.options,
|
||||
ttable.server_id,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
options = task.options or {}
|
||||
options_get = options.get
|
||||
|
||||
which = options_get("which", 2) # 15 min average
|
||||
load_max = options_get("load_max", 2)
|
||||
|
||||
stable = s3db.setup_server
|
||||
server = db(stable.id == task.server_id).select(stable.host_ip,
|
||||
stable.remote_user,
|
||||
stable.private_key,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
|
||||
if server.host_ip == "127.0.0.1":
|
||||
loadavg = os.getloadavg()
|
||||
if loadavg[which] > load_max:
|
||||
return {"result": "Warning: load average: %0.2f, %0.2f, %0.2f" % \
|
||||
(loadavg[0], loadavg[1], loadavg[2]),
|
||||
"status": 2,
|
||||
}
|
||||
|
||||
return {"result": "OK. load average: %0.2f, %0.2f, %0.2f" % \
|
||||
(loadavg[0], loadavg[1], loadavg[2]),
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
ssh = _ssh(server)
|
||||
if isinstance(ssh, dict):
|
||||
# We failed to login
|
||||
return ssh
|
||||
|
||||
command = "import os;loadavg=os.getloadavg();print(loadavg[0]);print(loadavg[1]);print(loadavg[2])"
|
||||
stdin, stdout, stderr = ssh.exec_command('python -c "%s"' % command)
|
||||
outlines = stdout.readlines()
|
||||
ssh.close()
|
||||
|
||||
loadavg = {0: float(outlines[0]),
|
||||
1: float(outlines[1]),
|
||||
2: float(outlines[2]),
|
||||
}
|
||||
|
||||
if loadavg[which] > load_max:
|
||||
return {"result": "Warning: load average: %0.2f, %0.2f, %0.2f" % \
|
||||
(loadavg[0], loadavg[1], loadavg[2]),
|
||||
"status": 2,
|
||||
}
|
||||
|
||||
return {"result": "OK. load average: %0.2f, %0.2f, %0.2f" % \
|
||||
(loadavg[0], loadavg[1], loadavg[2]),
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def ping(task_id, run_id):
|
||||
"""
|
||||
Ping a server
|
||||
ICMP Ping a server
|
||||
- NB AWS instances don't respond to ICMP Ping by default, but this can be enabled in the Firewall
|
||||
"""
|
||||
|
||||
s3db = current.s3db
|
||||
@ -66,83 +436,323 @@ class S3Monitor(object):
|
||||
host_ip = row.host_ip
|
||||
|
||||
try:
|
||||
output = subprocess.check_output("ping -{} 1 {}".format("n" if platform.system().lower == "windows" else "c", host_ip), shell=True)
|
||||
except Exception as e:
|
||||
# Critical: Ping failed
|
||||
return 3
|
||||
# @ToDo: Replace with socket?
|
||||
# - we want to see the latency
|
||||
if platform.system().lower == "windows":
|
||||
_format = "n"
|
||||
else:
|
||||
# OK
|
||||
return 1
|
||||
_format = "c"
|
||||
output = subprocess.check_output("ping -{} 1 {}".format(_format,
|
||||
host_ip),
|
||||
shell = True)
|
||||
except Exception:
|
||||
import traceback
|
||||
tb_parts = sys.exc_info()
|
||||
tb_text = "".join(traceback.format_exception(tb_parts[0],
|
||||
tb_parts[1],
|
||||
tb_parts[2]))
|
||||
return {"result": "Critical: Ping failed\n\n%s" % tb_text,
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#@staticmethod
|
||||
#def http(task_id, run_id):
|
||||
# """
|
||||
# Test that HTTP is accessible
|
||||
# """
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
#@staticmethod
|
||||
#def https(task_id, run_id):
|
||||
# """
|
||||
# Test that HTTPS is accessible
|
||||
# @ToDo: Check that SSL certificate hasn't expired
|
||||
# """
|
||||
return {"result": "OK",
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def email_round_trip(task_id, run_id):
|
||||
def scheduler(task_id, run_id):
|
||||
"""
|
||||
Check that a Mailbox is being Polled & Parsed OK and can send replies
|
||||
Test whether the scheduler is running
|
||||
"""
|
||||
|
||||
db = current.db
|
||||
s3db = current.s3db
|
||||
|
||||
# Read the Task Options
|
||||
otable = current.s3db.setup_monitor_task_option
|
||||
query = (otable.task_id == task_id) & \
|
||||
(otable.deleted == False)
|
||||
rows = current.db(query).select(otable.tag,
|
||||
otable.value,
|
||||
)
|
||||
options = dict((row.tag, row.value) for row in rows)
|
||||
ttable = s3db.setup_monitor_task
|
||||
task = db(ttable.id == task_id).select(ttable.options,
|
||||
ttable.server_id,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
options = task.options or {}
|
||||
options_get = options.get
|
||||
|
||||
to = options.get("to", None)
|
||||
if not to:
|
||||
return False
|
||||
stable = s3db.setup_server
|
||||
server = db(stable.id == task.server_id).select(stable.host_ip,
|
||||
stable.remote_user,
|
||||
stable.private_key,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
|
||||
subject = options.get("subject", "")
|
||||
message = options.get("message", "")
|
||||
reply_to = options.get("reply_to")
|
||||
if not reply_to:
|
||||
# Use the outbound email address
|
||||
reply_to = current.deployment_settings.get_mail_sender()
|
||||
if not reply_to:
|
||||
return False
|
||||
earliest = current.request.utcnow - datetime.timedelta(seconds = 900) # 15 minutes
|
||||
|
||||
# Append the run_id for the remote parser to identify as a monitoring message & return to us to be able to match the run
|
||||
message = "%s\n%s" % (message, ":run_id:%s:" % run_id)
|
||||
if server.host_ip == "127.0.0.1":
|
||||
# This shouldn't make much sense as a check, since this won't run if the scheduler has died
|
||||
# - however in practise, it can actually provide useful warning!
|
||||
|
||||
# Append the reply_to address for the remote parser
|
||||
message = "%s\n%s" % (message, ":reply_to:%s:" % reply_to)
|
||||
wtable = s3db.scheduler_worker
|
||||
worker = db(wtable.status == "ACTIVE").select(wtable.last_heartbeat,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
|
||||
# Send the Email
|
||||
result = current.msg.send_email(to,
|
||||
subject,
|
||||
message,
|
||||
reply_to=reply_to)
|
||||
error = None
|
||||
if worker is None:
|
||||
error = "Warning: Scheduler not ACTIVE"
|
||||
|
||||
if result:
|
||||
# Schedule a task to see if the reply has arrived after 1 hour
|
||||
start_time = datetime.datetime.utcnow() + datetime.timedelta(hours=1)
|
||||
current.s3task.schedule_task("setup_monitor_check_email_reply",
|
||||
args = [run_id],
|
||||
start_time = start_time,
|
||||
timeout = 300, # seconds
|
||||
repeats = 1 # one-time
|
||||
)
|
||||
# Warning: No reply received yet
|
||||
return 2
|
||||
elif worker.last_heartbeat < earliest:
|
||||
error = "Warning: Scheduler stalled since %s" % worker.last_heartbeat.strftime("%H:%M %a %d %b")
|
||||
|
||||
if error:
|
||||
appname = options_get("appname", "eden")
|
||||
instance = options_get("instance", "prod")
|
||||
|
||||
# Restart uwsgi
|
||||
error += "\n\nAttempting to restart:\n"
|
||||
# Note this needs to actually run after last task as it kills us ;)
|
||||
# NB Need to ensure the web2py user has permission to run sudo
|
||||
command = 'echo "sudo service uwsgi-%s restart" | at now + 1 minutes' % instance
|
||||
output = subprocess.check_output(command,
|
||||
stderr = subprocess.STDOUT,
|
||||
shell = True)
|
||||
error += output.decode("utf-8")
|
||||
# Restart Monitoring Scripts
|
||||
command = 'echo "cd /home/%s;python web2py.py --no-banner -S %s -M -R applications/%s/static/scripts/tools/restart_monitor_tasks.py" | at now + 5 minutes' % \
|
||||
(instance, appname, appname)
|
||||
output = subprocess.check_output(command,
|
||||
stderr = subprocess.STDOUT,
|
||||
shell = True)
|
||||
error += output.decode("utf-8")
|
||||
return {"result": error,
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
return {"result": "OK",
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
|
||||
ssh = _ssh(server)
|
||||
if isinstance(ssh, dict):
|
||||
# We failed to login
|
||||
return ssh
|
||||
|
||||
appname = options_get("appname", "eden")
|
||||
instance = options_get("instance", "prod")
|
||||
|
||||
command = "cd /home/%s;python web2py.py --no-banner -S %s -M -R applications/%s/static/scripts/tools/check_scheduler.py -A '%s'" % \
|
||||
(instance, appname, appname, earliest)
|
||||
stdin, stdout, stderr = ssh.exec_command(command)
|
||||
outlines = stdout.readlines()
|
||||
|
||||
if outlines:
|
||||
error = outlines[0]
|
||||
# Restart uwsgi
|
||||
error += "\n\nAttempting to restart:\n"
|
||||
command = "sudo service uwsgi-%s restart" % instance
|
||||
stdin, stdout, stderr = ssh.exec_command(command)
|
||||
outlines = stdout.readlines()
|
||||
if outlines:
|
||||
error += "\n".join(outlines)
|
||||
else:
|
||||
# Critical: Unable to send Email
|
||||
return 3
|
||||
# Doesn't usually give any output
|
||||
error += "OK"
|
||||
ssh.close()
|
||||
return {"result": error,
|
||||
"status": 3,
|
||||
}
|
||||
ssh.close()
|
||||
|
||||
return {"result": "OK",
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def tcp(task_id, run_id):
|
||||
"""
|
||||
Test that a TCP port is accessible
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def tickets(task_id, run_id):
|
||||
"""
|
||||
Test whether there are new tickets today
|
||||
- designed to be run daily (period 86400s)
|
||||
"""
|
||||
|
||||
db = current.db
|
||||
s3db = current.s3db
|
||||
|
||||
# Read the Task Options
|
||||
ttable = s3db.setup_monitor_task
|
||||
task = db(ttable.id == task_id).select(ttable.options,
|
||||
#ttable.period,
|
||||
ttable.server_id,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
options = task.options or {}
|
||||
options_get = options.get
|
||||
|
||||
stable = s3db.setup_server
|
||||
server = db(stable.id == task.server_id).select(stable.host_ip,
|
||||
stable.remote_user,
|
||||
stable.private_key,
|
||||
stable.deployment_id,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
|
||||
request = current.request
|
||||
today = request.utcnow.date().isoformat()
|
||||
|
||||
if server.host_ip == "127.0.0.1":
|
||||
appname = request.application
|
||||
public_url = current.deployment_settings.get_base_public_url()
|
||||
tickets = os.listdir("applications/%s/errors" % appname)
|
||||
new = []
|
||||
for ticket in tickets:
|
||||
#if os.stat(ticket).st_mtime < now - task.period:
|
||||
if today in ticket:
|
||||
url = "%s/%s/admin/ticket/%s/%s" % (public_url,
|
||||
appname,
|
||||
appname,
|
||||
ticket,
|
||||
)
|
||||
new.append(url)
|
||||
|
||||
if new:
|
||||
return {"result": "Warning: New tickets:\n\n%s" % "\n".join(new),
|
||||
"status": 2,
|
||||
}
|
||||
|
||||
return {"result": "OK",
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
ssh = _ssh(server)
|
||||
if isinstance(ssh, dict):
|
||||
# We failed to login
|
||||
return ssh
|
||||
|
||||
appname = options_get("appname", "eden")
|
||||
instance = options_get("instance", "prod")
|
||||
|
||||
command = "import os;ts=os.listdir('/home/%s/applications/%s/errors');for t in ts:print(t) if '%s' in t" % \
|
||||
(instance, appname, today)
|
||||
stdin, stdout, stderr = ssh.exec_command('python -c "%s"' % command)
|
||||
outlines = stdout.readlines()
|
||||
ssh.close()
|
||||
|
||||
if outlines:
|
||||
itable = s3db.setup_instance
|
||||
query = (itable.deployment_id == server.deployment_id) & \
|
||||
(itable.type == INSTANCE_TYPES[instance])
|
||||
instance = db(query).select(itable.url,
|
||||
limitby = (0, 1)
|
||||
).first()
|
||||
public_url = instance.url
|
||||
new = []
|
||||
for ticket in outlines:
|
||||
url = "%s/%s/admin/ticket/%s/%s" % (public_url,
|
||||
appname,
|
||||
appname,
|
||||
ticket,
|
||||
)
|
||||
new.append(url)
|
||||
return {"result": "Warning: New tickets:\n\n%s" % "\n".join(new),
|
||||
"status": 2,
|
||||
}
|
||||
|
||||
return {"result": "OK",
|
||||
"status": 1,
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
def _bytes_to_size_string(b):
|
||||
#def _bytes_to_size_string(b: int) -> str:
|
||||
"""
|
||||
Convert a number in bytes to a sensible unit.
|
||||
|
||||
From https://github.com/jamesoff/simplemonitor/blob/develop/simplemonitor/Monitors/host.py#L35
|
||||
"""
|
||||
|
||||
kb = 1024
|
||||
mb = kb * 1024
|
||||
gb = mb * 1024
|
||||
tb = gb * 1024
|
||||
|
||||
if b > tb:
|
||||
return "%0.2fTiB" % (b / float(tb))
|
||||
elif b > gb:
|
||||
return "%0.2fGiB" % (b / float(gb))
|
||||
elif b > mb:
|
||||
return "%0.2fMiB" % (b / float(mb))
|
||||
elif b > kb:
|
||||
return "%0.2fKiB" % (b / float(kb))
|
||||
else:
|
||||
return str(b)
|
||||
|
||||
# =============================================================================
|
||||
def _ssh(server):
|
||||
"""
|
||||
SSH into a Server
|
||||
"""
|
||||
|
||||
remote_user = server.remote_user
|
||||
private_key = server.private_key
|
||||
if not private_key or not remote_user:
|
||||
if remote_user:
|
||||
return {"result": "Critical. Missing Private Key",
|
||||
"status": 3,
|
||||
}
|
||||
elif private_key:
|
||||
return {"result": "Critical. Missing Remote User",
|
||||
"status": 3,
|
||||
}
|
||||
else:
|
||||
return {"result": "Critical. Missing Remote User & Private Key",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
# SSH in & run check
|
||||
try:
|
||||
import paramiko
|
||||
except ImportError:
|
||||
return {"result": "Critical. Paramiko required.",
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
keyfile = open(os.path.join(current.request.folder, "uploads", private_key), "r")
|
||||
mykey = paramiko.RSAKey.from_private_key(keyfile)
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
ssh.connect(hostname = server.host_ip,
|
||||
username = remote_user,
|
||||
pkey = mykey)
|
||||
except paramiko.ssh_exception.AuthenticationException:
|
||||
import traceback
|
||||
tb_parts = sys.exc_info()
|
||||
tb_text = "".join(traceback.format_exception(tb_parts[0],
|
||||
tb_parts[1],
|
||||
tb_parts[2]))
|
||||
return {"result": "Critical. Authentication Error\n\n%s" % tb_text,
|
||||
"status": 3,
|
||||
}
|
||||
except paramiko.ssh_exception.SSHException:
|
||||
import traceback
|
||||
tb_parts = sys.exc_info()
|
||||
tb_text = "".join(traceback.format_exception(tb_parts[0],
|
||||
tb_parts[1],
|
||||
tb_parts[2]))
|
||||
return {"result": "Critical. SSH Error\n\n%s" % tb_text,
|
||||
"status": 3,
|
||||
}
|
||||
|
||||
return ssh
|
||||
|
||||
# END =========================================================================
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Template-specific Message Parsers are defined here.
|
||||
|
||||
@copyright: 2012-2019 (c) Sahana Software Foundation
|
||||
@copyright: 2012-2020 (c) Sahana Software Foundation
|
||||
@license: MIT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
@ -55,6 +55,53 @@ class S3Parser(object):
|
||||
Message Parsing Template
|
||||
"""
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def parse_email(message):
|
||||
"""
|
||||
Parse Responses
|
||||
- parse responses to mails from the Monitor service
|
||||
"""
|
||||
|
||||
reply = None
|
||||
|
||||
db = current.db
|
||||
s3db = current.s3db
|
||||
|
||||
# Need to use Raw currently as not showing in Body
|
||||
message_id = message.message_id
|
||||
table = s3db.msg_email
|
||||
record = db(table.message_id == message_id).select(table.raw,
|
||||
limitby=(0, 1)
|
||||
).first()
|
||||
if not record:
|
||||
return reply
|
||||
|
||||
message_body = record.raw
|
||||
if not message_body:
|
||||
return reply
|
||||
|
||||
# What type of message is this?
|
||||
if ":run_id:" in message_body:
|
||||
# Response to Monitor Check
|
||||
|
||||
# Parse Mail
|
||||
try:
|
||||
run_id = S3Parser._parse_value(message_body, "run_id")
|
||||
run_id = int(run_id)
|
||||
except:
|
||||
return reply
|
||||
|
||||
# Update the Run entry to show that we have received the reply OK
|
||||
rtable = s3db.monitor_run
|
||||
db(rtable.id == run_id).update(result = "Reply Received",
|
||||
status = 1)
|
||||
return reply
|
||||
|
||||
else:
|
||||
# Don't know what this is: ignore
|
||||
return reply
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def parse_twitter(message):
|
||||
@ -250,37 +297,6 @@ class S3Parser(object):
|
||||
# No reply here
|
||||
return None
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def _parse_keywords(message_body):
|
||||
"""
|
||||
Parse Keywords
|
||||
- helper function for search_resource, etc
|
||||
"""
|
||||
|
||||
# Equivalent keywords in one list
|
||||
primary_keywords = ["get", "give", "show"]
|
||||
contact_keywords = ["email", "mobile", "facility", "clinical",
|
||||
"security", "phone", "status", "hospital",
|
||||
"person", "organisation"]
|
||||
|
||||
pkeywords = primary_keywords + contact_keywords
|
||||
keywords = message_body.split(" ")
|
||||
pquery = []
|
||||
name = ""
|
||||
for word in keywords:
|
||||
match = None
|
||||
for key in pkeywords:
|
||||
if soundex(key) == soundex(word):
|
||||
match = key
|
||||
break
|
||||
if match:
|
||||
pquery.append(match)
|
||||
else:
|
||||
name = word
|
||||
|
||||
return pquery, name
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
def search_resource(self, message):
|
||||
"""
|
||||
@ -310,7 +326,7 @@ class S3Parser(object):
|
||||
"""
|
||||
Search for People
|
||||
- can be called direct
|
||||
- can be called from search_by_keyword
|
||||
- can be called from search_resource
|
||||
"""
|
||||
|
||||
message_body = message.body
|
||||
@ -385,7 +401,7 @@ class S3Parser(object):
|
||||
"""
|
||||
Search for Hospitals
|
||||
- can be called direct
|
||||
- can be called from search_by_keyword
|
||||
- can be called from search_resource
|
||||
"""
|
||||
|
||||
message_body = message.body
|
||||
@ -458,7 +474,7 @@ class S3Parser(object):
|
||||
"""
|
||||
Search for Organisations
|
||||
- can be called direct
|
||||
- can be called from search_by_keyword
|
||||
- can be called from search_resource
|
||||
"""
|
||||
|
||||
message_body = message.body
|
||||
@ -600,6 +616,49 @@ class S3Parser(object):
|
||||
reply = "Incident Report Logged!"
|
||||
return reply
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def _parse_keywords(message_body):
|
||||
"""
|
||||
Parse Keywords
|
||||
- helper function for search_resource, etc
|
||||
"""
|
||||
|
||||
# Equivalent keywords in one list
|
||||
primary_keywords = ["get", "give", "show"]
|
||||
contact_keywords = ["email", "mobile", "facility", "clinical",
|
||||
"security", "phone", "status", "hospital",
|
||||
"person", "organisation"]
|
||||
|
||||
pkeywords = primary_keywords + contact_keywords
|
||||
keywords = message_body.split(" ")
|
||||
pquery = []
|
||||
name = ""
|
||||
for word in keywords:
|
||||
match = None
|
||||
for key in pkeywords:
|
||||
if soundex(key) == soundex(word):
|
||||
match = key
|
||||
break
|
||||
if match:
|
||||
pquery.append(match)
|
||||
else:
|
||||
name = word
|
||||
|
||||
return pquery, name
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def _parse_value(text, fieldname):
|
||||
"""
|
||||
Parse a value from a piece of text
|
||||
"""
|
||||
|
||||
parts = text.split(":%s:" % fieldname, 1)
|
||||
parts = parts[1].split(":", 1)
|
||||
result = parts[0]
|
||||
return result
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def _respond_drequest(message, report_id, response, text):
|
||||
@ -613,8 +672,8 @@ class S3Parser(object):
|
||||
rtable = current.s3db.irs_ireport_human_resource
|
||||
query = (rtable.ireport_id == report_id) & \
|
||||
(rtable.human_resource_id == hr_id)
|
||||
current.db(query).update(reply=text,
|
||||
response=response)
|
||||
current.db(query).update(reply = text,
|
||||
response = response)
|
||||
reply = "Response Logged in the Report (Id: %d )" % report_id
|
||||
else:
|
||||
reply = None
|
||||
|
@ -0,0 +1,2 @@
|
||||
Name,Comments
|
||||
Received,
|
|
@ -14,13 +14,16 @@
|
||||
# zzz_1st_run
|
||||
# s3import::S3BulkImporter
|
||||
# =============================================================================
|
||||
# Authentication
|
||||
# Roles
|
||||
*,import_role,auth_roles.csv
|
||||
auth,user,masterUsers.csv,user.xsl
|
||||
# GIS
|
||||
# Markers
|
||||
gis,marker,gis_marker.csv,marker.xsl
|
||||
# Config
|
||||
gis,config,gis_config.csv,config.xsl
|
||||
gis,hierarchy,gis_hierarchy.csv,hierarchy.xsl
|
||||
# Layers
|
||||
gis,layer_feature,gis_layer_feature.csv,layer_feature.xsl
|
||||
gis,layer_config,gis_layer_openstreetmap.csv,layer_openstreetmap.xsl
|
||||
gis,layer_config,gis_layer_openweathermap.csv,layer_openweathermap.xsl
|
||||
@ -31,16 +34,15 @@ gis,layer_config,gis_layer_tms.csv,layer_tms.xsl
|
||||
gis,layer_geojson,gis_layer_geojson.csv,layer_geojson.xsl
|
||||
gis,layer_georss,gis_layer_georss.csv,layer_georss.xsl
|
||||
gis,layer_config,gis_layer_coordinate.csv,layer_coordinate.xsl
|
||||
# CMS
|
||||
# -----------------------------------------------------------------------------
|
||||
cms,post,cms_post.csv,post.xsl
|
||||
# Organisations
|
||||
# -----------------------------------------------------------------------------
|
||||
org,sector,org_sector.csv,sector.xsl
|
||||
org,organisation_type,organisation_type.csv,organisation_type.xsl
|
||||
org,office_type,office_type.csv,office_type.xsl
|
||||
# Supplies
|
||||
supply,catalog_item,DefaultItems.csv,catalog_item.xsl
|
||||
supply,catalog_item,StandardItems.csv,catalog_item.xsl
|
||||
# Human Resource Management
|
||||
supply,person_item_status,supply_person_item_status.csv,person_item_status.xsl
|
||||
hrm,skill,DefaultSkillList.csv,skill.xsl
|
||||
hrm,skill,DrivingSkillList.csv,skill.xsl
|
||||
hrm,skill,DrivingSkillList_EU.csv,skill.xsl
|
||||
@ -48,20 +50,15 @@ hrm,skill,LanguageSkillList.csv,skill.xsl
|
||||
hrm,competency_rating,DefaultSkillCompetency.csv,competency_rating.xsl
|
||||
hrm,competency_rating,LanguageCompetency.csv,competency_rating.xsl
|
||||
hrm,certificate,certificate.csv,certificate.xsl
|
||||
# Events
|
||||
event,event_type,event_type.csv,event_type.xsl
|
||||
event,incident_type,incident_type.csv,incident_type.xsl
|
||||
# Projects
|
||||
project,status,project_status.csv,status.xsl
|
||||
project,activity_type,project_activity_type.csv,activity_type.xsl
|
||||
project,hazard,project_hazard.csv,hazard.xsl
|
||||
project,theme,project_theme.csv,theme.xsl
|
||||
project,beneficiary_type,project_beneficiary_type.csv,beneficiary_type.xsl
|
||||
# Shelters
|
||||
cr,shelter_type,shelter_type.csv,shelter_type.xsl
|
||||
# Disaster Victim Registry
|
||||
dvr,case_status,dvr_case_status.csv,case_status.xsl
|
||||
# Members
|
||||
# Spotter
|
||||
cr,shelter_type,cr_shelter_type.csv,shelter_type.xsl
|
||||
event,event_type,event_type.csv,event_type.xsl
|
||||
event,incident_type,incident_type.csv,incident_type.xsl
|
||||
member,membership_type,membership_type.csv,membership_type.xsl
|
||||
# Jobs
|
||||
work,job_type,work_job_type.csv,job_type.xsl
|
||||
# =============================================================================
|
||||
|
Loading…
Reference in New Issue
Block a user