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, provider_name): provider = (db.session.query(OpenIDProvider).filter( OpenIDProvider.name == provider_name).first()) if not provider: raise NotFound( f"Requested provider name '{provider_name}' not found") schema = OpenIDAuthorizeRequestSchema() obj = loads_schema(request.get_data(as_text=True), schema) redirect_uri = f"{app_config.mwdb.base_url}/oauth/callback" userinfo = provider.fetch_id_token(obj["code"], obj["state"], obj["nonce"], redirect_uri) # register user with information from provider if db.session.query(exists().where( and_( OpenIDUserIdentity.provider_id == provider.id, OpenIDUserIdentity.sub_id == userinfo["sub"], ))).scalar(): raise Conflict("User is already bound with selected provider.") login_claims = ["preferred_username", "nickname", "name"] for claim in login_claims: username = userinfo.get(claim) if not username: continue try: UserLoginSchemaBase().load({"login": username}) except ValidationError: continue already_exists = db.session.query( exists().where(Group.name == username)).scalar() if not already_exists: break # If no candidates in claims: try fallback login else: # If no candidates in claims: try fallback login sub_md5 = hashlib.md5( userinfo["sub"].encode("utf-8")).hexdigest()[:8] username = f"{provider_name}-{sub_md5}" if "email" in userinfo.keys(): user_email = userinfo["email"] else: user_email = f'{userinfo["sub"]}@mwdb.local' user = User.create( username, user_email, "Registered via OpenID Connect protocol", ) identity = OpenIDUserIdentity(sub_id=userinfo["sub"], provider_id=provider.id, user_id=user.id) db.session.add(identity) user.logged_on = datetime.datetime.now() db.session.commit() auth_token = user.generate_session_token() user_private_group = next( (g for g in user.groups if g.name == user.login), None) hooks.on_created_user(user) if user_private_group: hooks.on_created_group(user_private_group) logger.info( "User logged in via OpenID Provider", extra={ "login": user.login, "provider": provider_name }, ) schema = AuthSuccessResponseSchema() return schema.dump({ "login": user.login, "token": auth_token, "capabilities": user.capabilities, "groups": user.group_names, })
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})