def token_grant(admin_access_token, id_, email): """Grant a token to the selected user.""" try: admin = User.query.filter_by(id_=ADMIN_USER_ID).one_or_none() if admin_access_token != admin.access_token: raise ValueError("Admin access token invalid.") user = _get_user_by_criteria(id_, email) error_msg = None if not user: error_msg = f"User {id_ or email} does not exist." elif user.access_token: error_msg = ( f"User {user.id_} ({user.email}) has already an active access token." ) if error_msg: click.secho(f"ERROR: {error_msg}", fg="red") sys.exit(1) if user.access_token_status in [UserTokenStatus.revoked.name, None]: click.confirm( f"User {user.id_} ({user.email}) access token status" f" is {user.access_token_status}, do you want to" " proceed?", abort=True, ) user_granted_token = secrets.token_urlsafe(16) user.access_token = user_granted_token Session.commit() log_msg = (f"Token for user {user.id_} ({user.email}) granted.\n" f"\nToken: {user_granted_token}") click.secho(log_msg, fg="green") admin.log_action(AuditLogAction.grant_token, {"reana_admin": log_msg}) # send notification to user by email email_subject = "REANA access token granted" email_body = JinjaEnv.render_template( "emails/token_granted.txt", user_full_name=user.full_name, reana_hostname=REANA_HOSTNAME, ui_config=REANAConfig.load("ui"), sender_email=ADMIN_EMAIL, ) send_email(user.email, email_subject, email_body) except click.exceptions.Abort: click.echo("Grant token aborted.") except REANAEmailNotificationError as e: click.secho( "Something went wrong while sending email:\n{}".format(e), fg="red", err=True, ) except Exception as e: click.secho( "Something went wrong while granting token:\n{}".format(e), fg="red", err=True, )
def set_quota_limit(ctx, admin_access_token, emails, resource_name, limit): """Set quota limits to the given users per resource.""" try: for email in emails: error_msg = None user = _get_user_by_criteria(None, email) resource = Resource.query.filter_by( name=resource_name).one_or_none() if not user: error_msg = f"ERROR: Provided user {email} does not exist." elif not resource: error_msg = ( "ERROR: Provided resource name does not exist. Available " f"resources are {[resource.name for resource in Resource.query]}." ) if error_msg: click.secho( error_msg, fg="red", err=True, ) sys.exit(1) user_resource = UserResource.query.filter_by( user=user, resource=resource).one_or_none() if user_resource: user_resource.quota_limit = limit Session.add(user_resource) else: # Create user resource in case there isn't one. Useful for old users. user.resources.append( UserResource( user_id=user.id_, resource_id=resource.id_, quota_limit=limit, quota_used=0, )) Session.commit() click.secho( f"Quota limit {limit} for '{resource.name}' successfully set to users {emails}.", fg="green", ) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo( click.style("Quota could not be set: \n{}".format(str(e)), fg="red"), err=True, )
def token_revoke(admin_access_token, id_, email): """Revoke selected user's token.""" try: admin = User.query.filter_by(id_=ADMIN_USER_ID).one_or_none() if admin_access_token != admin.access_token: raise ValueError("Admin access token invalid.") user = _get_user_by_criteria(id_, email) error_msg = None if not user: error_msg = f"User {id_ or email} does not exist." elif not user.access_token: error_msg = (f"User {user.id_} ({user.email}) does not have an" " active access token.") if error_msg: click.secho(f"ERROR: {error_msg}", fg="red") sys.exit(1) revoked_token = user.access_token user.active_token.status = UserTokenStatus.revoked Session.commit() log_msg = (f"User token {revoked_token} ({user.email}) was" " successfully revoked.") click.secho(log_msg, fg="green") admin.log_action(AuditLogAction.revoke_token, {"reana_admin": log_msg}) # send notification to user by email email_subject = "REANA access token revoked" email_body = JinjaEnv.render_template( "emails/token_revoked.txt", user_full_name=user.full_name, reana_hostname=REANA_HOSTNAME, ui_config=REANAConfig.load("ui"), sender_email=ADMIN_EMAIL, ) send_email(user.email, email_subject, email_body) except REANAEmailNotificationError as e: click.secho( "Something went wrong while sending email:\n{}".format(e), fg="red", err=True, ) except Exception as e: click.secho( "Something went wrong while revoking token:\n{}".format(e), fg="red", err=True, )
def token_grant(admin_access_token, id_, email): """Grant a token to the selected user.""" try: admin = User.query.filter_by(id_=ADMIN_USER_ID).one_or_none() if admin_access_token != admin.access_token: raise ValueError("Admin access token invalid.") user = _get_user_by_criteria(id_, email) error_msg = None if not user: error_msg = f"User {id_ or email} does not exist." elif user.access_token: error_msg = (f"User {user.id_} ({user.email}) has already an" " active access token.") if error_msg: click.secho(f"ERROR: {error_msg}", fg="red") sys.exit(1) if user.access_token_status in [UserTokenStatus.revoked.name, None]: click.confirm( f"User {user.id_} ({user.email}) access token status" f" is {user.access_token_status}, do you want to" " proceed?", abort=True, ) user_granted_token = secrets.token_urlsafe(16) user.access_token = user_granted_token Session.commit() log_msg = (f"Token for user {user.id_} ({user.email}) granted.\n" f"\nToken: {user_granted_token}") click.secho(log_msg, fg="green") admin.log_action(AuditLogAction.grant_token, {"reana_admin": log_msg}) # send notification to user by email email_subject = "REANA access token granted" email_body = ( f"Dear {user.full_name},\n\nYour REANA access token has" f" been granted, please find it on https://{REANA_URL}/profile" "\n\nThe REANA support team") send_email(user.email, email_subject, email_body) except click.exceptions.Abort as e: click.echo("Grant token aborted.") except Exception as e: click.secho( "Something went wrong while granting token:\n{}".format(e), fg="red", err=True, )
def token_revoke(admin_access_token, id_, email): """Revoke selected user's token.""" try: admin = User.query.filter_by(id_=ADMIN_USER_ID).one_or_none() if admin_access_token != admin.access_token: raise ValueError("Admin access token invalid.") user = _get_user_by_criteria(id_, email) error_msg = None if not user: error_msg = f"User {id_ or email} does not exist." elif not user.access_token: error_msg = (f"User {user.id_} ({user.email}) does not have an" " active access token.") if error_msg: click.secho(f"ERROR: {error_msg}", fg="red") sys.exit(1) revoked_token = user.access_token user.active_token.status = UserTokenStatus.revoked Session.commit() log_msg = (f"User token {revoked_token} ({user.email}) was" " successfully revoked.") click.secho(log_msg, fg="green") admin.log_action(AuditLogAction.revoke_token, {"reana_admin": log_msg}) # send notification to user by email email_subject = "REANA access token revoked" email_body = (f"Dear {user.full_name},\n\nYour REANA access token has" " been revoked.\n\nThe REANA support team") send_email(user.email, email_subject, email_body) except Exception as e: click.secho( "Something went wrong while revoking token:\n{}".format(e), fg="red", err=True, )
def set_quota_limit(ctx, emails, resource_type, resource_name, limit): """Set quota limits to the given users per resource.""" try: for email in emails: error_msg = None resource = None user = _get_user_by_criteria(None, email) if resource_name: resource = Resource.query.filter_by( name=resource_name).one_or_none() elif resource_type in ResourceType._member_names_: resources = Resource.query.filter_by(type_=resource_type).all() if resources and len(resources) > 1: click.secho( f"ERROR: There are more than one `{resource_type}` resource. " "Please provide resource name with `--resource-name` option to specify the exact resource.", fg="red", err=True, ) sys.exit(1) else: resource = resources[0] if not user: error_msg = f"ERROR: Provided user {email} does not exist." elif not resource: resources = [ f"{resource.type_.name} ({resource.name})" for resource in Resource.query ] error_msg = ( f"ERROR: Provided resource `{resource_name or resource_type}` does not exist. " if resource_name or resource_type else "ERROR: Please provide a resource. ") error_msg += f"Available resources are: {', '.join(resources)}." if error_msg: click.secho( error_msg, fg="red", err=True, ) sys.exit(1) user_resource = UserResource.query.filter_by( user=user, resource=resource).one_or_none() if user_resource: user_resource.quota_limit = limit Session.add(user_resource) else: # Create user resource in case there isn't one. Useful for old users. user.resources.append( UserResource( user_id=user.id_, resource_id=resource.id_, quota_limit=limit, quota_used=0, )) Session.commit() click.secho( f"Quota limit {limit} for '{resource.type_.name} ({resource.name})' successfully set to users {emails}.", fg="green", ) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo( click.style("Quota could not be set: \n{}".format(str(e)), fg="red"), err=True, )