예제 #1
0
def get_admin_user(_app_settings):
    admin = User.find_by_username("admin")
    if admin is None:
        admin = User("admin")
        admin.password = _app_settings['LIFEMONITOR_ADMIN_PASSWORD']
        admin.id = 1
        lm_db.db.session.add(admin)
        lm_db.db.session.commit()
    return admin
예제 #2
0
def get_admin_user():
    admin = User.find_by_username("admin")
    if admin is None:
        admin = User("admin")
        admin.password = "******"
        admin.id = 1
        lm_db.db.session.add(admin)
        lm_db.db.session.commit()
    return admin
예제 #3
0
def db_init():
    """
    Initialize the DB
    """
    from lifemonitor.db import create_db, db
    logger.debug("Initializing DB...")
    create_db(settings=current_app.config)
    db.create_all()
    logger.info("DB initialized")
    # create a default admin user if not exists
    admin = User.find_by_username('admin')
    if not admin:
        admin = User('admin')
        admin.password = current_app.config["LIFEMONITOR_ADMIN_PASSWORD"]
        db.session.add(admin)
        db.session.commit()
예제 #4
0
    def _find_and_check_workflow_version(cls, user: User, uuid, version=None):
        w = None
        if not version:
            _w = models.Workflow.get_user_workflow(user, uuid)
            if _w:
                w = _w.latest_version
        else:
            w = models.WorkflowVersion.get_user_workflow_version(user, uuid, version)
        if not w:
            w = cls._find_and_check_shared_workflow_version(user, uuid, version=version)

        if w is None:
            raise lm_exceptions.EntityNotFoundException(models.WorkflowVersion, f"{uuid}_{version}")
        # Check whether the user can access the workflow.
        # As a general rule, we grant user access to the workflow
        #   1. if the user belongs to the owners group
        #   2. or the user belongs to the viewers group
        # if user not in w.owners and user not in w.viewers:
        if not user.has_permission(w):
            # if the user is not the submitter
            # and the workflow is associated with a registry
            # then we try to check whether the user is allowed to view the workflow
            if w.workflow_registry is None or w.workflow not in w.workflow_registry.get_user_workflows(user):
                raise lm_exceptions.NotAuthorizedException(f"User {user.username} is not allowed to access workflow")
        return w
예제 #5
0
 def add_workflow_registry(type, name,
                           client_id, client_secret, client_auth_method="client_secret_post",
                           api_base_url=None, redirect_uris=None) -> models.WorkflowRegistry:
     try:
         # At the moment client_credentials of registries
         # are associated with the admin account
         user = User.find_by_username("admin")
         if not user:
             raise lm_exceptions.EntityNotFoundException(User, entity_id="admin")
         server_credentials = providers.new_instance(provider_type=type,
                                                     name=name,
                                                     client_id=client_id,
                                                     client_secret=client_secret,
                                                     api_base_url=api_base_url)
         client_credentials = \
             server.create_client(user, name, server_credentials.api_base_url,
                                  ['client_credentials', 'authorization_code', 'refresh_token'],
                                  ["code", "token"],
                                  "read write",
                                  redirect_uris.split(',')
                                  if isinstance(redirect_uris, str)
                                  else redirect_uris,
                                  client_auth_method, commit=False)
         registry = models.WorkflowRegistry.new_instance(type, client_credentials, server_credentials)
         registry.save()
         logger.debug(f"WorkflowRegistry '{name}' (type: {type})' created: {registry}")
         return registry
     except providers.OAuth2ProviderNotSupportedException as e:
         raise lm_exceptions.WorkflowRegistryNotSupportedException(exception=e)
예제 #6
0
def api_key_create(username, scope="read", length=40):
    """
    Create an API Key for a given user (identified by username)
    """
    logger.debug("Finding User '%s'...", username)
    user = User.find_by_username(username)
    if not user:
        print("User not found", file=sys.stderr)
        sys.exit(99)
    logger.debug("User found: %r", user)
    api_key = generate_new_api_key(user, scope, length)
    print("%r" % api_key)
    logger.debug("ApiKey created")
예제 #7
0
def api_key_list(username):
    """
    Create an API Key for a given user (identified by username)
    """
    logger.debug("Finding User '%s'...", username)
    user = User.find_by_username(username)
    if not user:
        print("User not found", file=sys.stderr)
        sys.exit(99)
    logger.debug("User found: %r", user)
    logger.info('-' * 82)
    logger.info("User '%s' ApiKeys", user.username)
    logger.info('-' * 82)
    for key in user.api_keys:
        print(key)
예제 #8
0
def api_key_clean(username):
    """
    Create an API Key for a given user (identified by username)
    """
    logger.debug("Finding User '%s'...", username)
    user = User.find_by_username(username)
    if not user:
        print("User not found", file=sys.stderr)
        sys.exit(99)
    logger.debug("User found: %r", user)
    count = 0
    for key in user.api_keys:
        key.delete()
        print("ApiKey '%s' deleted!" % key.key)
        count += 1
    print("%d ApiKeys deleted!" % count, file=sys.stderr)
    logger.debug("ApiKeys of User '%s' deleted!", user.username)
예제 #9
0
def token_invalidate(username):
    """
    Invalidate all tokens related with a given user
    """
    logger.debug("Finding User '%s'...", username)
    user = User.find_by_username(username)
    if not user:
        print("User not found", file=sys.stderr)
        sys.exit(99)
    logger.debug("User found: %r", user)
    count = 0
    for identity in user.oauth_identity.values():
        identity.token = invalidate_token(identity.token)
        identity.save()
        print("Token invalidated: %r !" % identity.token)
        count += 1
    print("%d Token invalidated!" % count, file=sys.stderr)
    logger.debug("Token of User '%s' invalidated!", user.username)
예제 #10
0
def create_client_credentials(client_name, client_uri, client_auth_method,
                              scope, username):
    """
    Create a OAuth2 client with 'client_credentials' grant
    """
    user = User.find_by_username(username)
    logger.debug("USERNAME: %r", username)
    if not user:
        print("User not found", file=sys.stderr)
        sys.exit(99)
    logger.debug("User found: %r", user)
    client = server.create_client(user, client_name, client_uri,
                                  'client_credentials', ["token"], scope, "",
                                  client_auth_method)
    print("CLIENT ID: %s" % client.client_id)
    print("CLIENT SECRET: %s" % client.client_secret)
    print("ACCESS TOKEN URL: <LIFE_MONITOR_BASE_URL>/oauth/token")
    logger.debug("Client created")
예제 #11
0
def create_client_oauth_code(client_name, client_uri, client_redirect_uri,
                             client_auth_method, scope, username):
    """
    Create a OAuth2 client with 'authorization_code' grant
    """
    user = User.find_by_username(username)
    logger.debug("USERNAME: %r", username)
    if not user:
        print("User not found", file=sys.stderr)
        sys.exit(99)
    logger.debug("User found: %r", user)
    client = server.create_client(user, client_name, client_uri,
                                  ['authorization_code', 'token', 'id_token'],
                                  ["code", "token"], scope,
                                  client_redirect_uri, client_auth_method)
    print("CLIENT ID: %s" % client.client_id)
    print("CLIENT SECRET: %s" % client.client_secret)
    print("AUTHORIZATION URL: <LIFE_MONITOR_BASE_URL>/oauth/authorize")
    print("ACCESS TOKEN URL: <LIFE_MONITOR_BASE_URL>/oauth/token")
    logger.debug("Client created")
예제 #12
0
    def register_workflow(roc_link, workflow_submitter: User, workflow_version,
                          workflow_uuid=None, workflow_identifier=None,
                          workflow_registry: Optional[models.WorkflowRegistry] = None,
                          authorization=None, name=None):

        # find or create a user workflow
        if workflow_registry:
            w = workflow_registry.get_workflow(workflow_uuid or workflow_identifier)
        else:
            w = models.Workflow.get_user_workflow(workflow_submitter, workflow_uuid)
        if not w:
            w = models.Workflow(uuid=workflow_uuid, identifier=workflow_identifier, name=name)
            w.permissions.append(Permission(user=workflow_submitter, roles=[RoleType.owner]))
            if workflow_registry:
                for auth in workflow_submitter.get_authorization(workflow_registry):
                    auth.resources.append(w)

        if str(workflow_version) in w.versions:
            raise lm_exceptions.WorkflowVersionConflictException(workflow_uuid, workflow_version)
        if not roc_link:
            if not workflow_registry:
                raise ValueError("Missing ROC link")
            else:
                roc_link = workflow_registry.build_ro_link(workflow_submitter, w.external_id)

        wv = w.add_version(workflow_version, roc_link, workflow_submitter,
                           name=name, hosting_service=workflow_registry)
        wv.permissions.append(Permission(user=workflow_submitter, roles=[RoleType.owner]))
        if authorization:
            auth = ExternalServiceAuthorizationHeader(workflow_submitter, header=authorization)
            auth.resources.append(wv)
        if name is None:
            w.name = wv.dataset_name
            wv.name = wv.dataset_name
        if wv.test_metadata:
            logger.debug("Test metadata found in the crate")
            # FIXME: the test metadata can describe more than one suite
            wv.add_test_suite(workflow_submitter, wv.test_metadata)
        w.save()
        return wv
예제 #13
0
    def handle_authorize(self, provider: FlaskRemoteApp, token, user_info: OAuthUserProfile):
        logger.debug("Remote: %r", provider.name)
        logger.debug("Acquired token: %r", token)
        logger.debug("Acquired user_info: %r", user_info)
        # avoid autoflush in this session
        with db.session.no_autoflush:
            try:
                p = OAuth2IdentityProvider.find(provider.name)
                logger.debug("Provider found: %r", p)
            except exceptions.EntityNotFoundException:
                try:
                    logger.debug(f"Provider '{provider.name}' not found!")
                    p = OAuth2IdentityProvider(provider.name, **provider.OAUTH_APP_CONFIG)
                    p.save()
                    logger.info(f"Provider '{provider.name}' registered")
                except Exception as e:
                    return exceptions.report_problem_from_exception(e)

            try:
                identity = p.find_identity_by_provider_user_id(user_info.sub)
                logger.debug("Found OAuth identity <%r,%r>: %r",
                             provider.name, user_info.sub, identity)
                # update identity with the last token and userinfo
                identity.user_info = user_info.to_dict()
                identity.token = token
                logger.debug("Update identity token: %r -> %r", identity.token, token)
            except OAuthIdentityNotFoundException:
                logger.debug("Not found OAuth identity <%r,%r>", provider.name, user_info.sub)
                with db.session.no_autoflush:
                    identity = OAuthIdentity(
                        provider=p,
                        user_info=user_info.to_dict(),
                        provider_user_id=user_info.sub,
                        token=token,
                    )
            # Now, figure out what to do with this token. There are 2x2 options:
            # user login state and token link state.
            if current_user.is_anonymous:
                # If the user is not logged in and the token is linked,
                # log the identity user
                if identity.user:
                    identity.save()
                    login_user(identity.user)
                else:
                    # If the user is not logged in and the token is unlinked,
                    # create a new local user account and log that account in.
                    # This means that one person can make multiple accounts, but it's
                    # OK because they can merge those accounts later.
                    user = User()
                    identity.user = user
                    # Check whether to review user details
                    review_details = session.get("confirm_user_details", None)
                    # Initialize username.
                    # if the user will be automatically registered (without review)
                    # we append a random string to the his identity username
                    identity.user.username = \
                        utils.generate_username(
                            user_info,
                            salt_length=4 if not review_details else 0)
                    if not review_details:
                        identity.save()
                        login_user(user)
                        flash("OAuth identity linked to the current user account.")
                    else:
                        # save the user identity on the current session
                        save_current_user_identity(identity)
                        # and redirect the user
                        # to finalize the registration
                        return redirect(url_for('auth.register_identity'))
            else:
                if identity.user:
                    # If the user is logged in and the token is linked, check if these
                    # accounts are the same!
                    if current_user != identity.user:
                        # Account collision! Ask user if they want to merge accounts.
                        return redirect(url_for(self.merge_view,
                                                provider=identity.provider,
                                                username=identity.user.username))
                # If the user is logged in and the token is unlinked or linked yet,
                # link the token to the current user
                identity.user = current_user
                identity.save()
                flash(f"Your account has successfully been linked to the identity {identity}.")

            # Determine the right next hop
            next_url = NextRouteRegistry.pop()
            flash(f"Logged with your \"{provider.name.capitalize()}\" identity.", category="success")
            return redirect(next_url, code=307) if next_url \
                else RequestHelper.response() or redirect('/', code=302)
예제 #14
0
    def register_workflow(
            cls,
            roc_link,
            workflow_submitter: User,
            workflow_version,
            workflow_uuid=None,
            workflow_identifier=None,
            workflow_registry: Optional[models.WorkflowRegistry] = None,
            authorization=None,
            name=None):

        # find or create a user workflow
        if workflow_registry:
            w = workflow_registry.get_workflow(workflow_uuid
                                               or workflow_identifier)
        else:
            w = models.Workflow.get_user_workflow(workflow_submitter,
                                                  workflow_uuid)
        if not w:
            w = models.Workflow(uuid=workflow_uuid,
                                identifier=workflow_identifier,
                                name=name)
            if workflow_submitter:
                w.permissions.append(
                    Permission(user=workflow_submitter,
                               roles=[RoleType.owner]))
                if workflow_registry:
                    for auth in workflow_submitter.get_authorization(
                            workflow_registry):
                        auth.resources.append(w)

        if str(workflow_version) in w.versions:
            raise lm_exceptions.WorkflowVersionConflictException(
                workflow_uuid, workflow_version)
        if not roc_link:
            if not workflow_registry:
                raise ValueError("Missing ROC link")
            else:
                roc_link = workflow_registry.build_ro_link(
                    workflow_submitter, w.external_id)

        wv = w.add_version(workflow_version,
                           roc_link,
                           workflow_submitter,
                           name=name,
                           hosting_service=workflow_registry)

        if workflow_submitter:
            wv.permissions.append(
                Permission(user=workflow_submitter, roles=[RoleType.owner]))
        if authorization:
            auth = ExternalServiceAuthorizationHeader(workflow_submitter,
                                                      header=authorization)
            auth.resources.append(wv)
        if name is None:
            w.name = wv.dataset_name
            wv.name = wv.dataset_name

        # parse roc_metadata and register suites and instances
        try:
            for _, raw_suite in wv.roc_suites.items():
                cls._init_test_suite_from_json(wv, workflow_submitter,
                                               raw_suite)
        except KeyError as e:
            raise lm_exceptions.SpecificationNotValidException(
                f"Missing property: {e}")
        w.save()
        return wv