def post(self, login): """ --- summary: Accept a pending registration description: | Accepts pending user registration. Requires `manage_users` capability. security: - bearerAuth: [] tags: - user parameters: - in: path name: login schema: type: string description: Login of pending account responses: 200: description: When user is successfully accepted content: application/json: schema: UserSuccessResponseSchema 400: description: When invalid login is provided. 403: description: When user doesn't have `manage_users` capability. 500: description: When SMTP server is unavailable or not properly configured on the server. """ user_login_obj = load_schema({"login": login}, UserLoginSchemaBase()) user = db.session.query(User).filter(User.login == login, User.pending == true()).first() user.pending = False user.registered_on = datetime.datetime.now() user.registered_by = g.auth_user.id db.session.add(user) try: send_email_notification( "register", "New account registered in MWDB", user.email, base_url=app_config.mwdb.base_url, login=user.login, set_password_token=user.generate_set_password_token().decode( "utf-8")) except MailError: logger.exception("Can't send e-mail notification") raise InternalServerError( "SMTP server needed to fulfill this request is not configured or unavailable." ) db.session.commit() logger.info('User accepted', extra={'user': user.login}) schema = UserSuccessResponseSchema() return schema.dump({"login": user.login})
def post(self): """ --- summary: Get password change link for the current user description: | Requests password change link for currently authenticated user. Link expires after setting a new password or after 14 days. Link is sent to the e-mail address set in user's profile. Requires `manage_profile` capability. security: - bearerAuth: [] tags: - auth responses: 200: description: | When password change link was successfully sent to the user's e-mail content: application/json: schema: UserSuccessResponseSchema 403: description: | When user doesn't have required capability 500: description: | When SMTP server is unavailable or not properly configured on the server. """ login = g.auth_user.login email = g.auth_user.email try: send_email_notification( "recover", "Change password in MWDB", email, base_url=app_config.mwdb.base_url, login=login, set_password_token=g.auth_user.generate_set_password_token(), ) except MailError: logger.exception("Can't send e-mail notification") raise InternalServerError( "SMTP server needed to fulfill this request is" " not configured or unavailable.") schema = UserSuccessResponseSchema() logger.info("Requested password change token", extra={"user": login}) return schema.dump({"login": login})
def delete(self, login): """ --- summary: Delete user description: | Remove user from database. Requires `manage_users` capability. security: - bearerAuth: [] tags: - user parameters: - in: path name: login schema: type: string description: User login responses: 200: description: When user was removed successfully content: application/json: schema: UserSuccessResponseSchema 403: description: When user doesn't have `manage_users` capability. 404: description: When user doesn't exist. 503: description: | Request canceled due to database statement timeout. """ if g.auth_user.login == login: raise Forbidden("You can't remove yourself from the database.") user = db.session.query(User).filter(User.login == login).first() if user is None: raise NotFound("No such user") group = (db.session.query(Group).filter(Group.name == login)).first() db.session.delete(user) db.session.delete(group) db.session.commit() hooks.on_removed_user(user) hooks.on_removed_group(group) logger.info("User was deleted", extra={"user": login}) schema = UserSuccessResponseSchema() return schema.dump({"login": login})
def post(self): """ --- summary: Request a new user account description: Creates a new pending user account. tags: - auth requestBody: description: User basic information content: application/json: schema: AuthRegisterRequestSchema responses: 200: description: User login on successful registration. content: application/json: schema: UserSuccessResponseSchema 400: description: When request body is invalid. 403: description: When registration feature is disabled or reCAPTCHA token wasn't valid. 409: description: When user login or group name already exists. 500: description: When ReCAPTCHA verification service is unavailable. """ if not app_config.mwdb.enable_registration: raise Forbidden("User registration is not enabled.") schema = AuthRegisterRequestSchema() obj = loads_schema(request.get_data(as_text=True), schema) login = obj["login"] if db.session.query(exists().where(User.login == login)).scalar(): raise Conflict("Name already exists") if db.session.query(exists().where(Group.name == login)).scalar(): raise Conflict("Name already exists") verify_recaptcha(obj.get("recaptcha")) user = User.create(login, obj["email"], obj["additional_info"], pending=True) try: send_email_notification("pending", "Pending registration in MWDB", user.email, base_url=app_config.mwdb.base_url, login=user.login) except MailError: logger.exception("Can't send e-mail notification") logger.info('User registered', extra={'user': user.login}) schema = UserSuccessResponseSchema() return schema.dump({"login": user.login})
def post(self): """ --- summary: Set a new password for user description: Sets a new password for user using password change token. tags: - auth requestBody: description: | User set password token and new password. Password must be longer than 8 chars and shorter than 72 UTF-8 encoded bytes. content: application/json: schema: AuthSetPasswordRequestSchema responses: 200: description: User login on successful password set content: application/json: schema: UserSuccessResponseSchema 400: description: | When request body is invalid or provided password doesn't match the policy 403: description: When set password token is no longer valid 503: description: | Request canceled due to database statement timeout. """ schema = AuthSetPasswordRequestSchema() obj = loads_schema(request.get_data(as_text=True), schema) user = User.verify_set_password_token(obj["token"]) if user is None: raise Forbidden("Set password token expired") user.set_password(password=obj["password"]) db.session.commit() logger.info("Password changed", extra={"user": user.login}) schema = UserSuccessResponseSchema() return schema.dump({"login": user.login})
def post(self): """ --- summary: Recover user password description: | Sends e-mail with password recovery link for provided login and e-mail. Link expires after setting a new password or after 14 days. Link is sent to the e-mail address set in user's profile. requestBody: description: | User login and e-mail content: application/json: schema: AuthRecoverPasswordRequestSchema tags: - auth responses: 200: description: Get the password reset link by providing login and e-mail content: application/json: schema: UserSuccessResponseSchema 400: description: When request body is invalid 403: description: When login and e-mail address doesn't match or doesn't exist 500: description: When SMTP server is unavailable or not properly configured on the server. """ schema = AuthRecoverPasswordRequestSchema() obj = loads_schema(request.get_data(as_text=True), schema) try: user = User.query.filter( User.login == obj['login'], func.lower(User.email) == obj['email'].lower(), User.pending == false()).one() except NoResultFound: raise Forbidden('Invalid login or email address.') verify_recaptcha(obj.get("recaptcha")) try: send_email_notification( "recover", "Recover password in MWDB", user.email, base_url=app_config.mwdb.base_url, login=user.login, set_password_token=user.generate_set_password_token().decode( "utf-8")) except MailError: logger.exception("Can't send e-mail notification") raise InternalServerError( "SMTP server needed to fulfill this request is" " not configured or unavailable.") logger.info('User password recovered', extra={'user': user.login}) schema = UserSuccessResponseSchema() return schema.dump({"login": user.login})
def put(self, login): """ --- summary: Update existing user description: | Updates existing user account. Requires `manage_users` capability. security: - bearerAuth: [] tags: - user parameters: - in: path name: login schema: type: string description: User login requestBody: description: User information content: application/json: schema: UserUpdateRequestSchema responses: 200: description: When user was updated successfully content: application/json: schema: UserSuccessResponseSchema 400: description: When request body is invalid 403: description: | When user doesn't have `manage_users` capability or modified user is pending. 404: description: When user doesn't exist. """ schema = UserUpdateRequestSchema() obj = loads_schema(request.get_data(as_text=True), schema) user_login_obj = load_schema({"login": login}, UserLoginSchemaBase()) user = (db.session.query(User).filter( User.login == user_login_obj["login"]).first()) if user is None: raise NotFound("No such user") if user.pending: raise Forbidden("User is pending and need to be accepted first") email = obj["email"] if email is not None: user.email = email additional_info = obj["additional_info"] if additional_info is not None: user.additional_info = additional_info feed_quality = obj["feed_quality"] if feed_quality is not None: user.feed_quality = feed_quality disabled = obj["disabled"] if disabled is not None: user.disabled = disabled user.reset_sessions() db.session.commit() logger.info("User updated", extra=obj) schema = UserSuccessResponseSchema() return schema.dump({"login": user_login_obj["login"]})
def post(self, login): """ --- summary: Create a new user description: | Creates new user account Requires `manage_users` capability. security: - bearerAuth: [] tags: - user parameters: - in: path name: login schema: type: string description: New user login requestBody: description: User information content: application/json: schema: UserCreateRequestSchema responses: 200: description: When user was created successfully content: application/json: schema: UserSuccessResponseSchema 400: description: When request body is invalid 403: description: When user doesn't have `manage_users` capability. 409: description: When user or group with provided name already exists. 500: description: | When SMTP server is unavailable or not properly configured on the server. """ schema = UserCreateRequestSchema() obj = loads_schema(request.get_data(as_text=True), schema) user_login_obj = load_schema({"login": login}, UserLoginSchemaBase()) if db.session.query(exists().where( User.login == user_login_obj["login"])).scalar(): raise Conflict("User exists yet") if db.session.query(exists().where( Group.name == user_login_obj["login"])).scalar(): raise Conflict("Group exists yet") user = User.create( user_login_obj["login"], obj["email"], obj["additional_info"], pending=False, feed_quality=obj["feed_quality"], ) if obj["send_email"]: try: send_email_notification( "register", "New account registered in MWDB", user.email, base_url=app_config.mwdb.base_url, login=user.login, set_password_token=user.generate_set_password_token(). decode("utf-8"), ) except MailError: logger.exception("Can't send e-mail notification") raise InternalServerError( "SMTP server needed to fulfill this request is" " not configured or unavailable.") db.session.commit() logger.info("User created", extra={"user": user.login}) schema = UserSuccessResponseSchema() return schema.dump({"login": user.login})
def delete(self, login): """ --- summary: Reject a pending registration description: | Rejects pending user registration. Requires `manage_users` capability. security: - bearerAuth: [] tags: - user parameters: - in: path name: login schema: type: string description: Login of pending account responses: 200: description: When user is successfully rejected content: application/json: schema: UserSuccessResponseSchema 400: description: When invalid login is provided. 403: description: When user doesn't have `manage_users` capability. 404: description: When user doesn't exist or is already accepted/rejected. 500: description: | When SMTP server is unavailable or not properly configured on the server. """ user_login_obj = load_schema({"login": login}, UserLoginSchemaBase()) obj = load_schema(request.args, UserRejectRequestArgsSchema()) user = (db.session.query(User).filter( User.login == user_login_obj["login"], User.pending == true()).first()) if not user: raise NotFound("User doesn't exist or is already rejected") group = (db.session.query(Group).filter( Group.name == user_login_obj["login"]).first()) user.groups.remove(group) db.session.delete(group) db.session.delete(user) db.session.commit() if obj["send_email"]: try: send_email_notification( "rejection", "MWDB account request has been rejected", user.email, base_url=app_config.mwdb.base_url, login=user.login, set_password_token=user.generate_set_password_token(). decode("utf-8"), ) except MailError: logger.exception("Can't send e-mail notification") raise InternalServerError( "SMTP server needed to fulfill this request " "is not configured or unavailable.") logger.info( "User rejected with notification", extra={"user": user_login_obj["login"]}, ) else: logger.info( "User rejected without notification", extra={"user": user_login_obj["login"]}, ) schema = UserSuccessResponseSchema() return schema.dump({"login": user_login_obj["login"]})
def post(self): """ --- summary: Recover user password description: | Sends e-mail with password recovery link for provided login and e-mail. Link expires after setting a new password or after 14 days. Link is sent to the e-mail address set in user's profile. User must have `manage_profile` capability. requestBody: description: | User login and e-mail content: application/json: schema: AuthRecoverPasswordRequestSchema tags: - auth responses: 200: description: Get the password reset link by providing login and e-mail content: application/json: schema: UserSuccessResponseSchema 400: description: When request body is invalid 403: description: | When login and e-mail address doesn't match or doesn't exist 500: description: | When SMTP server is unavailable or not properly configured on the server. 503: description: | Request canceled due to database statement timeout. """ schema = AuthRecoverPasswordRequestSchema() obj = loads_schema(request.get_data(as_text=True), schema) try: user = User.query.filter( User.login == obj["login"], func.lower(User.email) == obj["email"].lower(), User.pending == false(), ).one() except NoResultFound: raise Forbidden("Invalid login or email address.") if not user.has_rights(Capabilities.manage_profile): raise Forbidden("You are not allowed to recover the password. " "Ask administrator for details.") verify_recaptcha(obj.get("recaptcha")) try: send_email_notification( "recover", "Recover password in MWDB", user.email, base_url=app_config.mwdb.base_url, login=user.login, set_password_token=user.generate_set_password_token(), ) except MailError: logger.exception("Can't send e-mail notification") raise InternalServerError( "SMTP server needed to fulfill this request is" " not configured or unavailable.") logger.info("User password recovered", extra={"user": user.login}) schema = UserSuccessResponseSchema() return schema.dump({"login": user.login})
def post(self, login): """ --- summary: Get password change link for specific user description: | Requests password change link for specific user. Link expires after setting a new password or after 14 days. Link is sent to the e-mail address set in user's profile. Requires `manage_users` capability. security: - bearerAuth: [] tags: - user parameters: - in: path name: login required: true schema: type: string description: Login of specific user responses: 200: description: | When password change link was successfully sent to the user's e-mail content: application/json: schema: UserSuccessResponseSchema 403: description: | When user doesn't have required capability 404: description: | When user doesn't exists. 500: description: | When SMTP server is unavailable or not properly configured on the server. 503: description: | Request canceled due to database statement timeout. """ user_login_obj = load_schema({"login": login}, UserLoginSchemaBase()) user = (db.session.query(User).filter( User.login == user_login_obj["login"]).first()) if not user: raise NotFound("User doesn't exist") try: send_email_notification( "recover", "Change password in MWDB", recipient_email=user.email, base_url=app_config.mwdb.base_url, login=user.login, set_password_token=user.generate_set_password_token(), ) except MailError: logger.exception("Can't send e-mail notification") raise InternalServerError( "SMTP server needed to fulfill this request is" " not configured or unavailable.") schema = UserSuccessResponseSchema() logger.info("Requested password change token", extra={"user": login}) return schema.dump({"login": login})