async def authenticate(request, *args, **kwargs): """Set up JWT auth.""" user_service = UserService(request[REQUEST_DB_SESSION_KEY]) rjs = request.json # enterprise SSO single-use-token login if rjs and rjs.get("single_use_token") is not None: user = user_service.single_use_token_login(rjs["single_use_token"], return_api_token=True) if user: return user else: raise exceptions.AuthenticationFailed( "Wrong authentication token.") if not rjs: raise exceptions.AuthenticationFailed("Missing username or password.") # standard auth with username and password in request username = rjs.get("username", None) password = rjs.get("password", None) if username and password: return user_service.login(username, password, return_api_token=True) raise exceptions.AuthenticationFailed("Missing username or password.")
def create_community_user(session: orm.Session, app: Optional[sanic.Sanic] = None) -> None: from rasax.community.services.role_service import RoleService from rasax.community.services.settings_service import SettingsService role_service = RoleService(session) role_service.init_roles(project_id=constants.COMMUNITY_PROJECT_NAME) settings_service = SettingsService(session) password = settings_service.get_community_user_password() is_password_generated = False # only re-assign password in local mode or if it doesn't exist if config.LOCAL_MODE or not password: password = os.environ.get(constants.ENV_RASA_X_PASSWORD) if not password: password = random_password() is_password_generated = True settings_service.save_community_user_password(password) user_service = UserService(session) user_service.insert_or_update_user(constants.COMMUNITY_USERNAME, password, constants.COMMUNITY_TEAM_NAME) if app: run_operation_in_single_sanic_worker( app, AppStartedCallable(password, is_password_generated))
def update_role_users( self, role: Text, username_to_exclude: Text, users_to_update: List[Text], user_service: UserService, ) -> List[Dict[Text, Any]]: """Update all users associated with this role. Exclude user `username_to_exclude` from this operation. Returns a list of users associated with `role`. """ # delete this role from all users for user in self.fetch_role_users(role): username = user["username"] # exclude `username_to_exclude` if username == username_to_exclude: continue user_service.delete_user_role(username, role) # add role to all users_to_update for username in users_to_update: # exclude `username_to_exclude` if username == username_to_exclude: continue existing_user = user_service.fetch_user(username) if existing_user: user_service.add_role_to_user(username, role) return self.fetch_role_users(role)
async def retrieve_user( request: Request, payload: Dict, allow_api_token: bool, extract_user_from_jwt: bool, *args: Any, **kwargs: Any, ) -> Optional[Dict]: if extract_user_from_jwt and payload and has_role(payload.get("user"), GUEST): return payload["user"] user_service = UserService(request[REQUEST_DB_SESSION_KEY]) if allow_api_token: api_token = rasa_x_utils.default_arg(request, "api_token") if api_token: return user_service.api_token_auth(api_token) if payload: username = payload.get("username", None) if username is not None: return user_service.fetch_user(username) else: # user is first-time enterprise user and has username None # in this case we'll fetch the profile using name_id name_id = payload.get("user", {}).get("name_id", None) return user_service.fetch_user(name_id) return None
async def delete_user(request: Request, username: Text, user: Dict) -> HTTPResponse: user_service = UserService(request[REQUEST_DB_SESSION_KEY]) try: deleted = user_service.delete_user( username, requesting_user=user["username"]) return response.json(deleted) except UserException as e: return rasa_x_utils.error(404, "UserDeletionError", e)
async def change_password(request: Request) -> HTTPResponse: rjs = request.json user_service = UserService(request[REQUEST_DB_SESSION_KEY]) try: user = user_service.change_password(rjs) if user is None: return rasa_x_utils.error(404, "UserNotFound", "user not found") return response.json(user) except MismatchedPasswordsException: return rasa_x_utils.error(403, "WrongPassword", "wrong password")
async def create_user(request: Request) -> HTTPResponse: rjs = request.json user_service = UserService(request[REQUEST_DB_SESSION_KEY]) team = rjs.get("team") or config.team_name user_service.create_user( username=rjs["username"], raw_password=rjs["password"], team=team, roles=rjs["roles"], ) return response.json(rjs, 201)
def _create_system_user(session: Session) -> None: user_service = UserService(session) if user_service.fetch_user(rasa_x_config.SYSTEM_USER): logger.debug( f"Found existing system system user '{rasa_x_config.SYSTEM_USER}'." ) return user_service.create_user( rasa_x_config.SYSTEM_USER, None, rasa_x_config.team_name, ADMIN ) logger.debug(f"Created new system user '{rasa_x_config.SYSTEM_USER}'.")
async def create_project(request: Request, project_id: Text, user: Dict) -> HTTPResponse: settings_service = SettingsService(request[REQUEST_DB_SESSION_KEY]) try: project = settings_service.init_project(user["team"], project_id) except ProjectException as e: return rasa_x_utils.error(404, "ProjectCreationError", details=e) user_service = UserService(request[REQUEST_DB_SESSION_KEY]) user_service.assign_project_to_user(user, project_id) return response.json(project)
async def list_users(request: Request) -> HTTPResponse: user_service = UserService(request[REQUEST_DB_SESSION_KEY]) username_query = utils.default_arg(request, "username", None) role_query = utils.default_arg(request, "role", None) users = user_service.fetch_all_users(config.team_name, username_query, role_query) if not users: return rasa_x_utils.error(404, "NoUsersFound", "No users found") profiles = [user_service.fetch_user(u["username"]) for u in users] return response.json(profiles, headers={"X-Total-Count": len(profiles)})
def _update_role_name(self, new_name: Text, old_name: Text, user_service: UserService) -> None: """Update the name of a role and move its users.""" # a rename should preserve old description and its `is_default` status existing_role = self.get_role(old_name) self.save_role(new_name, existing_role.description, existing_role.is_default) # move users with old role name to new role name users = self.fetch_role_users(old_name) for user in users: user_service.replace_user_roles(user["username"], [new_name]) if old_name in self.roles: self.delete_role(old_name)
def initialise_services(_session): return ( UserService(_session), SettingsService(_session), DomainService(_session), RoleService(_session), )
async def update_username(request: Request, user: Dict) -> HTTPResponse: rjs = request.json try: user_service = UserService(request[REQUEST_DB_SESSION_KEY]) user_profile = user_service.update_saml_username( user["name_id"], rjs["username"]) except UserException as e: return rasa_x_utils.error( 404, "UserException", "Could not assign username {} to name_id {}" "".format(rjs["username"], user["name_id"]), details=e, ) return response.json(user_profile)
def get_user_permissions( self, username: Text, user_service: UserService, project_id: Text = config.project_name, ) -> List[Text]: """Retrieve list of API permissions associated with `username`.""" user = user_service.fetch_user(username) return self._permissions_for(user, project_id)
def run_analytics_caching() -> None: import rasax.community.database.utils as database_utils with database_utils.session_scope() as session: # Use new session for all sql operations analytics_service = AnalyticsService(session) now = time.time() user_service = UserService(session) platform_users = user_service.fetch_all_users(config.team_name) platform_user_ids = [u["username"] for u in platform_users] for k, v in CACHED_ANALYTICS_CONFIG.items(): window = rasa_x_utils.duration_to_seconds(v["window"]) start = now - rasa_x_utils.duration_to_seconds(v["range"]) for include_platform_users in [False, True]: result = analytics_service.calculate_analytics( start, now, window, platform_user_ids) analytics_service._persist_analytics( k, result, include_platform_users)
def _user_service(request: Request) -> UserService: return UserService(request[REQUEST_DB_SESSION_KEY])
async def profile(request: Request, user: Dict) -> HTTPResponse: user_service = UserService(request[REQUEST_DB_SESSION_KEY]) return response.json( user_service.fetch_user(user["username"], return_api_token=True))
async def decorated_function(request, *args, **kwargs): user_service = UserService(request[REQUEST_DB_SESSION_KEY]) if initialized_on and isinstance(initialized_on, Blueprint): instance = initialized_on else: instance = request.app with instant_config(instance, request=request, **kw): if request.method == "OPTIONS": return await sanic_jwt_utils.call(f, request, *args, **kwargs) is_authenticated = False user_scopes = None reasons = None status = None if allow_rasa_x_token: rasa_x_token = default_arg(request, "token", None) if rasa_x_token == config.rasa_x_token: return await await_and_return_response(args, kwargs, request) if allow_api_token: # if decorator allows api_tokens for authentication # skip the usual JWT authentication api_token = default_arg(request, "api_token") if api_token: user = user_service.api_token_auth(api_token) is_authenticated = True status = 200 permissions = user["permissions"] user_scopes = normalise_permissions(permissions) if not is_authenticated: try: ( is_authenticated, status, reasons, ) = instance.auth._check_authentication( request, request_args=args, request_kwargs=kwargs ) except AttributeError: raise exceptions.SanicJWTException( "Authentication instance not found. Perhaps you " "used @scoped without passing in a blueprint? " "Try @scoped(..., initialized_on=blueprint)", status_code=500, ) except exceptions.SanicJWTException as e: status = e.status_code reasons = e.args[0] if is_authenticated: is_authorized, reasons, status = await authorise_user( args, kwargs, instance, reasons, request, status, user_scopes ) else: is_authorized = False if is_authorized: # the user is authorized. # run the handler method and return the response # NOTE: it's possible to use return await.utils(f, ...) in # here, but inside the @protected decorator it wont work, # so this is left as is for now return await await_and_return_response(args, kwargs, request) else: raise exceptions.Unauthorized(reasons, status_code=status)