Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
Archivo: s3rtb.py Proyecto: sahana/eden
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
Archivo: s3rtb.py Proyecto: sahana/eden
    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
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
    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