def evac_realm_entity(table, row): """ Assign a Realm Entity to records Cases all have a unique Realm Resources all have a unique Realm - other than: * Orgs * Staff Special Cases for Doctors (both a Case & a Resource!) """ from s3dal import original_tablename db = current.db s3db = current.s3db tablename = original_tablename(table) if tablename == "org_organisation": # Realm is own PE ID # => use Default Rules pass elif tablename in ("transport_airport", "transport_airplane", ): # No Realm return None elif tablename == "pr_person": # Staff? # Case? # Doctor? # Case & Doctor? pass elif tablename == "br_case": # Has a unique pr_realm with appropriate multiple inheritance pass elif tablename == "gis_route": # Inherits realm from the Case pass elif tablename == "br_activity": # Has a unique pr_realm with appropriate multiple inheritance pass elif tablename in ("event_incident_report", "hms_contact", "hms_hospital", "hms_pharmacy", "inv_inv_item", "org_facility", "security_zone", "transport_flight", "vehicle_vehicle", ): # Has a unique pr_realm with appropriate multiple inheritance pass realm_entity = 0 return realm_entity
def identities(self): """ A map over all identities of this node, i.e. the actual table name and ID, as well as all super entity names and IDs of the record (lazy property); this can be used to resolve any references to this record, including via super-links Returns: A map {(tablename, id): (itablename, iid, uid)}, where: - tablename is the table / supertable name - id is the record ID / super ID - itablename is the (instance) table name - iid is the (instance) record id - uid is the record UID """ table = self.table pkey = table._id.name # Super-records have no identities themselves if pkey != "id" and "instance_type" in table.fields: return {} identities = self._identities if identities is None: record = self.record tablename = original_tablename(table) record_id = record[pkey] # The base identity identity = ( tablename, record_id, record.uuid if "uuid" in table.fields else None, ) identities = self._identities = {(tablename, record_id): identity} # Add all known super-records for superkey in self.superkeys: super_id = self.record.get(superkey) if not super_id: continue tn = s3_get_foreign_key(table[superkey])[0] if tn: identities[(tn, super_id)] = identity return identities
def __init__( self, resource, archive=None, representation=None, ): """ Constructor @param resource: the S3Resource to delete records from @param archive: True|False to override global security.archive_not_delete setting @param representation: the request format (for audit, optional) """ self.resource = resource self.representation = representation # Get unaliased table tablename = self.tablename = original_tablename(resource.table) table = self.table = current.db[tablename] # Archive or hard-delete? if archive is None: if current.deployment_settings.get_security_archive_not_delete() and \ DELETED in table: archive = True else: archive = False self.archive = archive # Callbacks get_config = resource.get_config self.prepare = get_config("ondelete_cascade") self.ondelete = get_config("ondelete") # Initialize properties self._super_keys = None self._foreign_keys = None self._references = None self._restrictions = None self._done = False # Initialize instance variables self.errors = {} self.permission_error = False
def __init__(self, resource, archive=None, representation=None): """ Constructor @param resource: the S3Resource to delete records from @param archive: True|False to override global security.archive_not_delete setting @param representation: the request format (for audit, optional) """ self.resource = resource self.representation = representation # Get unaliased table tablename = self.tablename = original_tablename(resource.table) table = self.table = current.db[tablename] # Archive or hard-delete? if archive is None: if current.deployment_settings.get_security_archive_not_delete() and \ DELETED in table: archive = True else: archive = False self.archive = archive # Callbacks get_config = resource.get_config self.prepare = get_config("ondelete_cascade") self.ondelete = get_config("ondelete") # Initialize properties self._super_keys = None self._foreign_keys = None self._references = None self._restrictions = None self._done = False # Initialize instance variables self.errors = {} self.permission_error = False
def references(self): """ The references of this node (lazy property) Returns: A list of S3ResourceReferences """ references = self._references if references is None: self._references = references = [] table = self.table record = self.record xml = current.xml DELETED = xml.DELETED REPLACEDBY = xml.REPLACEDBY if DELETED in record and record[DELETED] and \ REPLACEDBY in record and record[REPLACEDBY]: fields = [REPLACEDBY] else: fields = self.rfields if not fields: return references for fn in fields: # Skip super-keys if fn in self.superkeys: continue # Skip unavailable/empty fields value = record.get(fn) if not value: continue if fn == REPLACEDBY: # Special handling since not a foreign key tn = original_tablename(table) key = table._id.name multiple = False else: # Inspect the DB field try: dbfield = getattr(table, fn) except AttributeError: continue tn, key, multiple = s3_get_foreign_key(dbfield) if not tn: continue # Add the reference reference = S3ResourceReference( table, fn, tn, key, value, multiple=multiple, ) references.append(reference) return references
def anonymize(cls, r, table, record_id): """ Handle POST (anonymize-request), i.e. anonymize the target record @param r: the S3Request @param table: the target Table @param record_id: the target record ID @returns: JSON message """ # Read+parse body JSON s = r.body s.seek(0) try: options = json.load(s) except JSONERRORS: options = None if not isinstance(options, dict): r.error(400, "Invalid request options") # Verify submitted action key against session (CSRF protection) widget_id = "%s-%s-anonymize" % (table, record_id) session_s3 = current.session.s3 keys = session_s3.anonymize if keys is None or \ widget_id not in keys or \ options.get("key") != keys[widget_id]: r.error(400, "Invalid action key (form reopened in another tab?)") # Get the available rules from settings rules = current.s3db.get_config(table, "anonymize") if isinstance(rules, (tuple, list)): names = set(rule.get("name") for rule in rules) names.discard(None) else: # Single rule rules["name"] = "default" names = (rules["name"], ) rules = [rules] # Get selected rules from options selected = options.get("apply") if not isinstance(selected, list): r.error(400, "Invalid request options") # Validate selected rules for name in selected: if name not in names: r.error(400, "Invalid rule: %s" % name) # Merge selected rules cleanup = {} cascade = [] for rule in rules: name = rule.get("name") if not name or name not in selected: continue field_rules = rule.get("fields") if field_rules: cleanup.update(field_rules) cascade_rules = rule.get("cascade") if cascade_rules: cascade.extend(cascade_rules) # Apply selected rules if cleanup or cascade: rules = { "fields": cleanup, "cascade": cascade, } # NB will raise (+roll back) if configuration is invalid cls.cascade(table, (record_id, ), rules) # Audit anonymize prefix, name = original_tablename(table).split("_", 1) current.audit( "anonymize", prefix, name, record=record_id, representation="html", ) output = current.xml.json_message(updated=record_id) else: output = current.xml.json_message(msg="No applicable rules found") return output
def anonymize(cls, r, table, record_ids): """ Handle POST (anonymize-request), i.e. anonymize the target record @param r: the S3Request @param table: the target Table @param record_ids: the target record IDs @returns: JSON message """ post_vars_get = r.post_vars.get # Verify submitted action key against session (CSRF protection) widget_id = "%s-anonymize" % table session_s3 = current.session.s3 keys = session_s3.anonymize if keys is None or \ widget_id not in keys or \ post_vars_get("action-key") != keys[widget_id]: r.error(400, "Invalid action key (form reopened in another tab?)") # Get the available rules from settings rules = current.s3db.get_config(table, "anonymize") if isinstance(rules, (tuple, list)): names = set(rule.get("name") for rule in rules) names.discard(None) else: # Single rule rules["name"] = "default" names = (rules["name"], ) rules = [rules] # Get selected rules from form selected = [] for rule in rules: rule_name = rule.get("name") if not rule_name: continue if post_vars_get(rule_name) == "on": selected.append(rule) # Merge selected rules cleanup = {} cascade = [] for rule in selected: field_rules = rule.get("fields") if field_rules: cleanup.update(field_rules) cascade_rules = rule.get("cascade") if cascade_rules: cascade.extend(cascade_rules) # Apply selected rules if cleanup or cascade: rules = { "fields": cleanup, "cascade": cascade, } for record_id in record_ids: # NB will raise (+roll back) if configuration is invalid cls.cascade(table, (record_id, ), rules) # Audit anonymize prefix, name = original_tablename(table).split("_", 1) current.audit( "anonymize", prefix, name, record=record_id, representation="html", ) output = current.xml.json_message(updated=record_ids) else: output = current.xml.json_message(msg="No applicable rules found") return output
def brcms_realm_entity(table, row): """ Assign a Realm Entity to records """ db = current.db s3db = current.s3db tablename = original_tablename(table) realm_entity = 0 if tablename == "pr_person": # Client records are owned by the organisation # the case is assigned to ctable = s3db.br_case query = (ctable.person_id == row.id) & \ (ctable.deleted == False) case = db(query).select( ctable.organisation_id, limitby=(0, 1), ).first() if case and case.organisation_id: realm_entity = s3db.pr_get_pe_id( "org_organisation", case.organisation_id, ) elif tablename in ( "pr_address", "pr_contact", "pr_contact_emergency", "pr_image", ): # Inherit from person via PE table = s3db.table(tablename) ptable = s3db.pr_person query = (table._id == row.id) & \ (ptable.pe_id == table.pe_id) person = db(query).select( ptable.realm_entity, limitby=(0, 1), ).first() if person: realm_entity = person.realm_entity elif tablename in ( "br_appointment", "br_case_activity", "br_case_language", "br_assistance_measure", "br_note", "pr_group_membership", "pr_person_details", "pr_person_tag", ): # Inherit from person via person_id table = s3db.table(tablename) ptable = s3db.pr_person query = (table._id == row.id) & \ (ptable.id == table.person_id) person = db(query).select( ptable.realm_entity, limitby=(0, 1), ).first() if person: realm_entity = person.realm_entity elif tablename == "br_case_activity_update": # Inherit from case activity table = s3db.table(tablename) atable = s3db.br_case_activity query = (table._id == row.id) & \ (atable.id == table.case_activity_id) activity = db(query).select( atable.realm_entity, limitby=(0, 1), ).first() if activity: realm_entity = activity.realm_entity elif tablename == "br_assistance_measure_theme": # Inherit from measure table = s3db.table(tablename) mtable = s3db.br_assistance_measure query = (table._id == row.id) & \ (mtable.id == table.measure_id) activity = db(query).select( mtable.realm_entity, limitby=(0, 1), ).first() if activity: realm_entity = activity.realm_entity elif tablename == "pr_group": # No realm-entity for case groups table = s3db.pr_group query = table._id == row.id group = db(query).select( table.group_type, limitby=(0, 1), ).first() if group and group.group_type == 7: realm_entity = None elif tablename == "project_task": # Inherit the realm entity from the assignee assignee_pe_id = row.pe_id instance_type = s3db.pr_instance_type(assignee_pe_id) if instance_type: table = s3db.table(instance_type) query = table.pe_id == assignee_pe_id assignee = db(query).select( table.realm_entity, limitby=(0, 1), ).first() if assignee and assignee.realm_entity: realm_entity = assignee.realm_entity # If there is no assignee, or the assignee has no # realm entity, fall back to the user organisation if realm_entity == 0: auth = current.auth user_org_id = auth.user.organisation_id if auth.user else None if user_org_id: realm_entity = s3db.pr_get_pe_id( "org_organisation", user_org_id, ) return realm_entity
def anonymize(cls, r, table, record_id): """ Handle POST (anonymize-request), i.e. anonymize the target record @param r: the S3Request @param table: the target Table @param record_id: the target record ID @returns: JSON message """ # Read+parse body JSON s = r.body s.seek(0) try: options = json.load(s) except JSONERRORS: options = None if not isinstance(options, dict): r.error(400, "Invalid request options") # Verify submitted action key against session (CSRF protection) widget_id = "%s-%s-anonymize" % (table, record_id) session_s3 = current.session.s3 keys = session_s3.anonymize if keys is None or \ widget_id not in keys or \ options.get("key") != keys[widget_id]: r.error(400, "Invalid action key (form reopened in another tab?)") # Get the available rules from settings rules = current.s3db.get_config(table, "anonymize") if isinstance(rules, (tuple, list)): names = set(rule.get("name") for rule in rules) names.discard(None) else: # Single rule rules["name"] = "default" names = (rules["name"],) rules = [rules] # Get selected rules from options selected = options.get("apply") if not isinstance(selected, list): r.error(400, "Invalid request options") # Validate selected rules for name in selected: if name not in names: r.error(400, "Invalid rule: %s" % name) # Merge selected rules cleanup = {} cascade = [] for rule in rules: name = rule.get("name") if not name or name not in selected: continue field_rules = rule.get("fields") if field_rules: cleanup.update(field_rules) cascade_rules = rule.get("cascade") if cascade_rules: cascade.extend(cascade_rules) # Apply selected rules if cleanup or cascade: rules = {"fields": cleanup, "cascade": cascade} # NB will raise (+roll back) if configuration is invalid cls.cascade(table, (record_id,), rules) # Audit anonymize prefix, name = original_tablename(table).split("_", 1) current.audit("anonymize", prefix, name, record = record_id, representation = "html", ) output = current.xml.json_message(updated=record_id) else: output = current.xml.json_message(msg="No applicable rules found") return output
def brcms_realm_entity(table, row): """ Assign a Realm Entity to records """ db = current.db s3db = current.s3db tablename = original_tablename(table) realm_entity = 0 if tablename == "pr_person": # Client records are owned by the organisation # the case is assigned to ctable = s3db.br_case query = (ctable.person_id == row.id) & \ (ctable.deleted == False) case = db(query).select(ctable.organisation_id, limitby = (0, 1), ).first() if case and case.organisation_id: realm_entity = s3db.pr_get_pe_id("org_organisation", case.organisation_id, ) elif tablename in ("pr_address", "pr_contact", "pr_contact_emergency", "pr_image", ): # Inherit from person via PE table = s3db.table(tablename) ptable = s3db.pr_person query = (table._id == row.id) & \ (ptable.pe_id == table.pe_id) person = db(query).select(ptable.realm_entity, limitby = (0, 1), ).first() if person: realm_entity = person.realm_entity elif tablename in ("br_appointment", "br_case_activity", "br_case_language", "br_assistance_measure", "br_note", "pr_group_membership", "pr_person_details", "pr_person_tag", ): # Inherit from person via person_id table = s3db.table(tablename) ptable = s3db.pr_person query = (table._id == row.id) & \ (ptable.id == table.person_id) person = db(query).select(ptable.realm_entity, limitby = (0, 1), ).first() if person: realm_entity = person.realm_entity elif tablename == "br_case_activity_update": # Inherit from case activity table = s3db.table(tablename) atable = s3db.br_case_activity query = (table._id == row.id) & \ (atable.id == table.case_activity_id) activity = db(query).select(atable.realm_entity, limitby = (0, 1), ).first() if activity: realm_entity = activity.realm_entity elif tablename == "br_assistance_measure_theme": # Inherit from measure table = s3db.table(tablename) mtable = s3db.br_assistance_measure query = (table._id == row.id) & \ (mtable.id == table.measure_id) activity = db(query).select(mtable.realm_entity, limitby = (0, 1), ).first() if activity: realm_entity = activity.realm_entity elif tablename == "pr_group": # No realm-entity for case groups table = s3db.pr_group query = table._id == row.id group = db(query).select(table.group_type, limitby = (0, 1), ).first() if group and group.group_type == 7: realm_entity = None elif tablename == "project_task": # Inherit the realm entity from the assignee assignee_pe_id = row.pe_id instance_type = s3db.pr_instance_type(assignee_pe_id) if instance_type: table = s3db.table(instance_type) query = table.pe_id == assignee_pe_id assignee = db(query).select(table.realm_entity, limitby = (0, 1), ).first() if assignee and assignee.realm_entity: realm_entity = assignee.realm_entity # If there is no assignee, or the assignee has no # realm entity, fall back to the user organisation if realm_entity == 0: auth = current.auth user_org_id = auth.user.organisation_id if auth.user else None if user_org_id: realm_entity = s3db.pr_get_pe_id("org_organisation", user_org_id, ) return realm_entity
def rlpptm_realm_entity(table, row): """ Assign a Realm Entity to records """ db = current.db s3db = current.s3db realm_entity = 0 # = use default tablename = original_tablename(table) #if tablename in ("org_group", # "org_organisation", # "org_facility", # "org_office", # ): # # These entities own themselves by default, and form # # a OU hierarchy (default ok) # realm_entity = 0 # #elif tablename == "pr_person": # # # Persons are owned by the org employing them (default ok) # realm_entity = 0 # if tablename == "disease_case_diagnostics": # Test results are owned by the user organisation user = current.auth.user organisation_id = user.organisation_id if user else None if not organisation_id: # Fall back to default organisation organisation_id = settings.get_org_default_organisation() if organisation_id: realm_entity = s3db.pr_get_pe_id( "org_organisation", organisation_id, ) #elif tablename == "fin_voucher_program": # # # Voucher programs are owned by the organisation managing # # them (default ok) # realm_entity = 0 # #elif tablename == "fin_voucher": # # # Vouchers are owned by the issuer PE (default ok) # realm_entity = 0 # #elif tablename == "fin_voucher_debit": # # # Debits are owned by the provider PE (default ok) # realm_entity = 0 # elif tablename == "fin_voucher_transaction": # Vouchers inherit the realm-entity from the program table = s3db.table(tablename) ptable = s3db.fin_voucher_program query = (table._id == row.id) & \ (ptable.id == table.program_id) program = db(query).select( ptable.realm_entity, limitby=(0, 1), ).first() if program: realm_entity = program.realm_entity return realm_entity