コード例 #1
0
ファイル: share.py プロジェクト: jmatthewarnold/dhis2-pk
def set_delimiter(dhis_version, object_filter):
    """
    Operator and rootJunction alias validation for the DHIS2 API (see DHIS2 developer docs)
    :param dhis_version: DHIS 2 version as an integer (e.g. 32):
    :param object_filter: Metadata object filter
    :return: tuple of aliases for OR / AND
    """
    if not object_filter:
        return None, None
    if '^' in object_filter:
        if dhis_version >= 28:
            raise PKClientException(
                "ArgumentError: Operator '^' was replaced with '$' in 2.28 onwards. Nothing shared."
            )
    if '||' in object_filter:
        if dhis_version < 25:
            raise PKClientException(
                "ArgumentError: rootJunction 'OR' / '||' is only supported 2.25 onwards. Nothing shared."
            )
        if '&&' in object_filter:
            raise PKClientException(
                "ArgumentError: Not allowed to combine delimiters '&&' and '||'. Nothing shared"
            )
        return '||', 'OR'
    return '&&', 'AND'
コード例 #2
0
ファイル: share.py プロジェクト: jmatthewarnold/dhis2-pk
 def create_obj(self, response):
     """
     Create ShareableObjects from the response
     :param response: server response
     :return yielded ShareableObjects
     """
     for elem in response:
         try:
             public_access = Permission.from_symbol(elem['publicAccess'])
         except ValueError as e:
             raise PKClientException(e)
         except KeyError:
             raise PKClientException(
                 "ServerError: Public access is not set "
                 "for {} {} '{}'".format(self.name, elem['id'],
                                         elem['name']))
         else:
             yield ShareableObject(obj_type=self.name,
                                   uid=elem['id'],
                                   name=elem['name'],
                                   code=elem.get('code'),
                                   public_access=public_access,
                                   usergroup_accesses={
                                       UserGroupAccess.from_dict(d)
                                       for d in elem['userGroupAccesses']
                                   })
コード例 #3
0
ファイル: share.py プロジェクト: ardhimanshu/dhis2-pk
def set_delimiter(version, argument):
    """
    Operator and rootJunction Alias validation
    :param version: DHIS2 version
    :param argument: Argument as received from parser
    :return: tuple(delimiter, rootJunction)
    """
    if not argument:
        return None, None
    if '^' in argument:
        if version >= 28:
            raise PKClientException(
                "ArgumentError: Operator '^' was replaced with '$' in 2.28 onwards. Nothing shared."
            )
    if '||' in argument:
        if version < 25:
            raise PKClientException(
                "ArgumentError: rootJunction 'OR' / '||' is only supported 2.25 onwards. Nothing shared."
            )
        if '&&' in argument:
            raise PKClientException(
                "ArgumentError: Not allowed to combine delimiters '&&' and '||'. Nothing shared"
            )
        return '||', 'OR'
    return '&&', 'AND'
コード例 #4
0
ファイル: share.py プロジェクト: ardhimanshu/dhis2-pk
def validate_data_access(public_access, collection, usergroups, dhis_version):
    if dhis_version < NEW_SYNTAX:
        if public_access.data or any(
            [group.permission.data for group in usergroups.accesses]):
            raise PKClientException(
                "ArgumentError: You cannot set DATA access on DHIS2 versions below 2.29 "
                "- check your arguments (-a) and (-g)")
    else:
        if collection.data_sharing_enabled:
            log_msg = "ArgumentError: Missing {} permission for DATA access for '{}' (Argument {})"
            if not public_access.data:
                raise PKClientException(
                    log_msg.format('Public Access', collection.name, '-a'))
            if not all(
                [group.permission.data for group in usergroups.accesses]):
                raise PKClientException(
                    log_msg.format('User Groups', collection.name, '-g'))
        else:
            log_msg = "ArgumentError: Not possible to set {} permission for DATA access for '{}' (Argument {})"
            if public_access.data:
                raise PKClientException(
                    log_msg.format('Public Access', collection.name, '-a'))
            if any([group.permission.data for group in usergroups.accesses]):
                raise PKClientException(
                    log_msg.format('User Group', collection.name, '-g'))
コード例 #5
0
ファイル: share.py プロジェクト: ardhimanshu/dhis2-pk
def validate_args(args, dhis_version):
    if len(args.public_access) not in (1, 2):
        raise PKClientException(
            "ArgumentError: Must use -a METADATA [DATA] - max. 2 arguments")
    if args.groups:
        for group in args.groups:
            try:
                metadata_permission = group[1]
            except IndexError:
                raise PKClientException(
                    "ArgumentError: Missing User Group permission for METADATA access"
                )
            if metadata_permission not in access.keys():
                raise PKClientException(
                    'ArgumentError: User Group permission for METADATA access not valid: "{}"'
                    .format(metadata_permission))
            if dhis_version >= NEW_SYNTAX:
                try:
                    data_permission = group[2]
                except IndexError:
                    pass
                else:
                    if data_permission not in access.keys():
                        raise PKClientException(
                            'ArgumentError: User Group permission for DATA access not valid: "{}"'
                            .format(data_permission))
コード例 #6
0
ファイル: share.py プロジェクト: jmatthewarnold/dhis2-pk
def validate_data_access(public_access, collection, usergroups, dhis_version):
    """
    Validate DATA access against public access, the collection and user groups. Raises Exception if invalid.
    :param public_access: Permission instance
    :param collection: ShareableObjectCollection instance
    :param usergroups: UserGroupsCollection instance
    :param dhis_version: DHIS 2 version as an integer (e.g. 32)
    :return: None
    """
    if dhis_version < NEW_SYNTAX:
        if public_access and public_access != PUBLIC_ACCESS_INHERITED and public_access.data\
                or any([group.permission.data for group in usergroups.accesses]):
            raise PKClientException(
                "ArgumentError: You cannot set DATA access on DHIS2 versions below 2.29 "
                "- check your arguments (-a) and (-g)")
    elif public_access != PUBLIC_ACCESS_INHERITED:
        if collection.data_sharing_enabled:
            log_msg = "ArgumentError: Missing {} permission for DATA access for '{}' (argument {})"
            if not public_access.data:
                raise PKClientException(
                    log_msg.format('Public Access', collection.name, '-a'))
            if not all(
                [group.permission.data for group in usergroups.accesses]):
                raise PKClientException(
                    log_msg.format('User Groups', collection.name, '-g'))
        else:
            log_msg = "ArgumentError: Not possible to set {} permission for DATA access for '{}' (argument {})"
            if public_access.data:
                raise PKClientException(
                    log_msg.format('Public Access', collection.name, '-a'))
            if any([group.permission.data for group in usergroups.accesses]):
                raise PKClientException(
                    log_msg.format('User Group', collection.name, '-g'))
コード例 #7
0
ファイル: attributes.py プロジェクト: ardhimanshu/dhis2-pk
def get_attribute_name(api, uid):
    try:
        return api.get('attributes/{}'.format(uid)).json()['name']
    except APIException as exc:
        if exc.code == 404:
            raise PKClientException(
                "Attribute {} could not be found".format(uid))
        else:
            raise PKClientException("Error: {}".format(exc))
コード例 #8
0
ファイル: attributes.py プロジェクト: ardhimanshu/dhis2-pk
def validate_csv(data):
    if not data[0].get('uid', None) or not data[0].get('attributeValue', None):
        raise PKClientException(
            "CSV not valid: CSV must have 'uid' and 'attributeValue' as headers"
        )

    object_uids = [obj['uid'] for obj in data]
    for uid in object_uids:
        if not valid_uid(uid):
            raise PKClientException(
                "Object '{}' is not a valid UID in the CSV".format(uid))
    if len(object_uids) != len(set(object_uids)):
        raise PKClientException("Duplicate Objects (rows) found in the CSV.")
    return True
コード例 #9
0
ファイル: share.py プロジェクト: ardhimanshu/dhis2-pk
 def get_name(self, obj_type):
     shareable = self.schema('shareable')
     for name, plural in iteritems(shareable):
         if obj_type.lower() in (name.lower(), plural.lower()):
             return name, plural
     raise PKClientException(
         "No DHIS2 object type for '{}'".format(obj_type))
コード例 #10
0
ファイル: attributes.py プロジェクト: ardhimanshu/dhis2-pk
def attribute_is_on_model(api, attribute, typ):
    attr_get = {'fields': 'id,name,{}Attribute'.format(typ[:-1])}
    attr = api.get('attributes/{}'.format(attribute.uid),
                   params=attr_get).json()
    if attr['{}Attribute'.format(typ[:-1])] is False:
        raise PKClientException(
            "Attribute {} ({}) is not assigned to type {}".format(
                attribute.name, attribute.uid, typ[:-1]))
コード例 #11
0
ファイル: indicators.py プロジェクト: jmatthewarnold/dhis2-pk
def parse_args():
    description = "{}Readable indicator definition to CSV.{}".format(
        Style.BRIGHT, Style.RESET_ALL)
    usage = "\n{}Example:{} dhis2-pk-indicator-definitions -s play.dhis2.org/demo -u admin -p district -t indicators".format(
        Style.BRIGHT, Style.RESET_ALL)

    types = {'programIndicators', 'indicators'}
    parser = argparse.ArgumentParser(usage=usage, description=description)
    parser._action_groups.pop()

    required = parser.add_argument_group('required arguments')
    required.add_argument('-t',
                          dest='indicator_type',
                          action='store',
                          metavar='INDICATOR_TYPE',
                          help="{}".format(" or ".join(types)),
                          choices=types,
                          required=True)

    optional = parser.add_argument_group('optional arguments')
    optional.add_argument('-s',
                          dest='server',
                          action='store',
                          help="DHIS2 server URL")
    optional.add_argument(
        '-f',
        dest='indicator_filter',
        action='store',
        help=
        "Indicator filter, e.g. -f 'name:like:HIV' - see dhis2-pk-share --help"
    )
    optional.add_argument('-u',
                          dest='username',
                          action='store',
                          help="DHIS2 username")
    optional.add_argument('-p',
                          dest='password',
                          action='store',
                          help="DHIS2 password")
    optional.add_argument('-v',
                          dest='api_version',
                          action='store',
                          type=int,
                          help='DHIS2 API version e.g. -v=28')
    args = parser.parse_args()
    if not args.password:
        if not args.username:
            raise PKClientException(
                "ArgumentError: Must provide a username via argument -u")
        password = getpass.getpass(
            prompt="Password for {} @ {}: ".format(args.username, args.server))
    else:
        password = args.password
    return args, password
コード例 #12
0
ファイル: share.py プロジェクト: jmatthewarnold/dhis2-pk
 def get_name(self, obj_type):
     """
     Get an object collection's name and it's plural name
     :param obj_type: type of object, e.g. dataelement
     :return: tuple of name and its plural name, e.g. dataElement, dataElements
     """
     shareable = self.schema('shareable')
     for name, plural in iteritems(shareable):
         if obj_type.lower() in (name.lower(), plural.lower()):
             return name, plural
     raise PKClientException(
         "No DHIS2 object type for '{}'".format(obj_type))
コード例 #13
0
ファイル: share.py プロジェクト: jmatthewarnold/dhis2-pk
def validate_args(args, dhis_version):
    """
    Validate arguments. Raises Exception if invalid
    :param args: the argparse arguments
    :param dhis_version: DHIS 2 version as an integer (e.g. 32)
    :return: None
    """
    if args.extend:
        if not args.groups and not args.public_access:
            raise PKClientException(
                "ArgumentError: Must supply user groups when extending sharing - check your argument (-g)"
            )
    else:
        if not args.public_access or len(args.public_access) not in (1, 2):
            raise PKClientException(
                "ArgumentError: Must use -a METADATA [DATA] - max. 2 arguments"
            )

    if args.groups:
        for group in args.groups:
            try:
                metadata_permission = group[1]
            except IndexError:
                raise PKClientException(
                    "ArgumentError: Missing User Group permission for METADATA access"
                )
            if metadata_permission not in access.keys():
                raise PKClientException(
                    'ArgumentError: User Group permission for METADATA access not valid: "{}"'
                    .format(metadata_permission))
            if dhis_version >= NEW_SYNTAX:
                try:
                    data_permission = group[2]
                except IndexError:
                    pass
                else:
                    if data_permission not in access.keys():
                        raise PKClientException(
                            'ArgumentError: User Group permission for DATA access not valid: "{}"'
                            .format(data_permission))
コード例 #14
0
ファイル: share.py プロジェクト: jmatthewarnold/dhis2-pk
    def get_usergroup_uids(self, filter_list, root_junction='AND'):
        """
        Get UserGroup UIDs
        :param filter_list: List of filters, e.g. ['name:like:ABC', 'code:eq:XYZ']
        :param root_junction: AND or OR
        :return: List of UserGroup UIDs
        """
        params = {'fields': 'id,name', 'paging': False, 'filter': filter_list}

        if root_junction == 'OR':
            params['rootJunction'] = root_junction

        endpoint = 'userGroups'
        response = self.api.get(endpoint, params=params).json()
        if len(response['userGroups']) > 0:
            return {ug['id']: ug['name'] for ug in response['userGroups']}
        else:
            raise PKClientException(
                "No userGroup found with {}".format(filter_list))
コード例 #15
0
def parse_args():
    description = "{}Post CSS stylesheet to a server.{}".format(
        Style.BRIGHT, Style.RESET_ALL)
    usage = "\n{}Example:{} dhis2-pk-post-css -s=play.dhis2.org/dev -u=admin -p=district -c=file.css".format(
        Style.BRIGHT, Style.RESET_ALL)
    parser = argparse.ArgumentParser(usage=usage, description=description)

    parser._action_groups.pop()
    required = parser.add_argument_group('required arguments')
    required.add_argument('-c',
                          dest='css',
                          action='store',
                          required=True,
                          help="Path to CSS file")

    optional = parser.add_argument_group('optional arguments')
    optional.add_argument('-s',
                          dest='server',
                          action='store',
                          help="DHIS2 server URL")
    optional.add_argument('-u',
                          dest='username',
                          action='store',
                          help='DHIS2 username')
    optional.add_argument('-p',
                          dest='password',
                          action='store',
                          help='DHIS2 password')
    args = parser.parse_args()

    if not args.password:
        if not args.username:
            raise PKClientException(
                "ArgumentError: Must provide a username via argument -u")
        password = getpass.getpass(
            prompt="Password for {} @ {}: ".format(args.username, args.server))
    else:
        password = args.password
    return args, password
コード例 #16
0
ファイル: integrity.py プロジェクト: jmatthewarnold/dhis2-pk
def parse_args():
    description = "{}Analyze data integrity.{}".format(Style.BRIGHT,
                                                       Style.RESET_ALL)
    usage = "\n{}Example:{} dhis2-pk-data-integrity -s play.dhis2.org/demo -u admin -p district".format(
        Style.BRIGHT, Style.RESET_ALL)

    parser = argparse.ArgumentParser(usage=usage, description=description)
    parser.add_argument('-s',
                        dest='server',
                        action='store',
                        help="DHIS2 server URL")
    parser.add_argument('-u',
                        dest='username',
                        action='store',
                        help="DHIS2 username")
    parser.add_argument('-p',
                        dest='password',
                        action='store',
                        help="DHIS2 password")
    parser.add_argument('-v',
                        dest='api_version',
                        action='store',
                        required=False,
                        type=int,
                        help='DHIS2 API version e.g. -v=28')
    args = parser.parse_args()

    if not args.password:
        if not args.username:
            raise PKClientException(
                "ArgumentError: Must provide a username via argument -u")
        password = getpass.getpass(
            prompt="Password for {} @ {}: ".format(args.username, args.server))
    else:
        password = args.password
    return args, password
コード例 #17
0
ファイル: attributes.py プロジェクト: ardhimanshu/dhis2-pk
def parse_args():
    description = "{}Set Attribute Values sourced from CSV file.{}".format(
        Style.BRIGHT, Style.RESET_ALL)

    usage = """
{}Example:{} dhis2-pk-attribute-setter -s play.dhis2.org/dev -u admin -p district -c file.csv -t organisationUnits -a pt5Ll9bb2oP

{}CSV file structure:{}
uid   | attributeValue
------|---------------
UID   | myValue
""".format(Style.BRIGHT, Style.RESET_ALL, Style.BRIGHT, Style.RESET_ALL)

    parser = argparse.ArgumentParser(
        usage=usage,
        description=description,
        formatter_class=argparse.RawTextHelpFormatter)
    parser._action_groups.pop()
    required = parser.add_argument_group('required arguments')
    required.add_argument(
        '-t',
        dest='object_type',
        action='store',
        required=True,
        help=
        "Object type to set attributeValues to: {organisationUnits, dataElements, ...}"
    )
    required.add_argument('-c',
                          dest='source_csv',
                          action='store',
                          required=True,
                          help="Path to CSV file with Attribute Values")
    required.add_argument('-a',
                          dest='attribute_uid',
                          action='store',
                          help='Attribute UID',
                          required=True)

    optional = parser.add_argument_group('optional arguments')
    optional.add_argument('-s',
                          dest='server',
                          action='store',
                          help="DHIS2 server URL")
    optional.add_argument('-u',
                          dest='username',
                          action='store',
                          help="DHIS2 username")
    optional.add_argument('-p',
                          dest='password',
                          action='store',
                          help="DHIS2 password")

    args = parser.parse_args()
    if args.object_type not in OBJ_TYPES:
        raise PKClientException(
            "argument -t must be a valid object_type - one of:\n{}".format(
                ', '.join(sorted(OBJ_TYPES))))
    if not valid_uid(args.attribute_uid):
        raise PKClientException("Attribute {} is not a valid UID".format(
            args.attribute_uid))
    return args
コード例 #18
0
def validate_file(filename):
    if not os.path.exists(filename):
        raise PKClientException("File does not exist: {}".format(filename))
    if not os.path.getsize(filename) > 0:
        raise PKClientException("File is empty: {}".format(filename))
コード例 #19
0
ファイル: share.py プロジェクト: jmatthewarnold/dhis2-pk
def parse_args():
    """Argument parsing"""
    description = "{}Share DHIS2 objects with userGroups via filters.{}".format(
        Style.BRIGHT, Style.RESET_ALL)
    usage = """
{}Example:{} dhis2-pk-share -s play.dhis2.org/dev -u admin -p district -f 'id:eq:P3jJH5Tu5VC' -t dataelement -a readonly -g 'name:like:Admin' readwrite -g 'name:like:Research' readwrite
""".format(Style.BRIGHT, Style.RESET_ALL)
    parser = argparse.ArgumentParser(
        usage=usage,
        description=description,
        formatter_class=argparse.RawTextHelpFormatter)

    parser._action_groups.pop()
    required = parser.add_argument_group('required arguments')

    required.add_argument(
        '-t',
        dest='object_type',
        action='store',
        required=True,
        help="DHIS2 object type to apply sharing, e.g. -t sqlView")

    optional = parser.add_argument_group('optional arguments')
    optional.add_argument('-a',
                          dest='public_access',
                          action='append',
                          required=False,
                          nargs='+',
                          metavar='PUBLICACCESS',
                          choices=access.keys(),
                          help=textwrap.dedent('''\
                            Public Access for all objects. 
                            Valid choices are: {{{}}}
                            For setting DATA access, add second argument, e.g. -a readwrite readonly
                          '''.format(', '.join(access.keys()))))
    optional.add_argument('-f',
                          dest='filter',
                          action='store',
                          required=False,
                          help=textwrap.dedent('''\
                                Filter on objects with DHIS2 field filter.
                                To add multiple filters:
                                - '&&' joins filters with AND
                                - '||' joins filters with OR
                                Example:  -f 'name:like:ABC||code:eq:X'
                                   '''))
    optional.add_argument('-g',
                          dest='groups',
                          action='append',
                          required=False,
                          metavar='USERGROUP',
                          nargs='+',
                          help=textwrap.dedent('''\
                            User Group to share objects with: FILTER METADATA [DATA]
                            - FILTER: Filter all User Groups. See -f for filtering mechanism
                            - METADATA: Metadata access for this User Group. {readwrite, none, readonly}
                            - DATA: Data access for this User Group. {readwrite, none, readonly}
                            Example:  -g 'id:eq:OeFJOqprom6' readwrite none
                            '''))
    optional.add_argument(
        '-o',
        dest='overwrite',
        action='store_true',
        required=False,
        default=False,
        help=
        "Overwrite sharing - updates 'lastUpdated' field of all shared objects"
    )
    optional.add_argument('-e',
                          dest='extend',
                          action='store_true',
                          required=False,
                          default=False,
                          help="Extend existing sharing settings")
    optional.add_argument(
        '-l',
        dest='logging_to_file',
        action='store',
        required=False,
        metavar='FILEPATH',
        help="Path to Log file (default level: INFO, pass -d for DEBUG)")
    optional.add_argument('-v',
                          dest='api_version',
                          action='store',
                          required=False,
                          type=int,
                          help='DHIS2 API version e.g. -v 28')
    optional.add_argument('-s',
                          dest='server',
                          action='store',
                          metavar='URL',
                          help="DHIS2 server URL")
    optional.add_argument('-u',
                          dest='username',
                          action='store',
                          help='DHIS2 username, e.g. -u admin')
    optional.add_argument('-p',
                          dest='password',
                          action='store',
                          help='DHIS2 password, e.g. -p district')
    optional.add_argument('-d',
                          dest='debug',
                          action='store_true',
                          default=False,
                          required=False,
                          help="Debug flag")
    args = parser.parse_args()

    if not args.password:
        if not args.username:
            raise PKClientException(
                "ArgumentError: Must provide a username via argument -u")
        password = getpass.getpass(
            prompt="Password for {} @ {}: ".format(args.username, args.server))
    else:
        password = args.password
    return args, password