def delete_user(identity: Identity, user_id: str, company_id: str = None, call: APICall = None): """ Delete an existing user from both the auth database and the backend database :param identity: Calling user identity :param user_id: ID of user to delete :param company_id: Company of user to delete :param call: API call that triggered this call. If not None, backend user deletion will be performed using a new call in the same transaction. """ if user_id == identity.user: raise errors.bad_request.FieldsValueError("cannot delete yourself", user=user_id) if not company_id: company_id = identity.company if (identity.role not in Role.get_system_roles() and company_id != identity.company): raise errors.bad_request.FieldsNotAllowedForRole( "must be empty or your own company", role=identity.role, field="company") with translate_errors_context(): query = dict(id=user_id, company=company_id) res = User.objects(**query).delete() if not res: raise errors.bad_request.InvalidUserId(**query) try: UserBLL.delete(user_id) except Exception as ex: log.error(f"Exception calling users.delete: {str(ex)}")
def create_user(call: APICall, _, request: CreateUserRequest): """ Create a user from. INTERNAL. """ if call.identity.role not in Role.get_system_roles( ) and request.company != call.identity.company: raise errors.bad_request.InvalidId( "cannot create user in another company") user_id = AuthBLL.create_user(request=request, call=call) call.result.data_model = CreateUserResponse(id=user_id)
def get_token_for_user(call: APICall, _: str, request: GetTokenForUserRequest): """ Generates a token based on a requested user and company. INTERNAL. """ if call.identity.role not in Role.get_system_roles(): if call.identity.role != Role.admin and call.identity.user != request.user: raise errors.bad_request.InvalidUserId( "cannot generate token for another user") if call.identity.company != request.company: raise errors.bad_request.InvalidId( "cannot generate token in another company") call.result.data_model = AuthBLL.get_token_for_user( user_id=request.user, company_id=request.company, expiration_sec=request.expiration_sec, )
def validate_impersonation(endpoint, call): """ Validate impersonation headers and set impersonated identity and authorization data accordingly. :returns True if impersonating, False otherwise """ try: act_as = call.act_as impersonate_as = call.impersonate_as if not impersonate_as and not act_as: return elif impersonate_as and act_as: raise errors.bad_request.InvalidHeaders( "only one allowed", headers=tuple(call.impersonation_headers.keys())) identity = call.auth.identity # verify this user is allowed to impersonate at all if identity.role not in Role.get_system_roles() | {Role.admin}: raise errors.bad_request.ImpersonationError( "impersonation not allowed", role=identity.role) # get the impersonated user's info user_id = act_as or impersonate_as if identity.role in [Role.root]: # only root is allowed to impersonate users in other companies query = dict(id=user_id) else: query = dict(id=user_id, company=identity.company) user = User.objects(**query).first() if not user: raise errors.bad_request.ImpersonationError( "unknown user", **query) company = Company.objects(id=user.company).only("name").first() if not company: query.update(company=user.company) raise errors.bad_request.ImpersonationError( "unknown company for user", **query) # create impersonation payload if act_as: # act as a user, using your own role and permissions call.impersonation = Payload( auth_type=None, identity=Identity( user=user.id, company=user.company, role=identity.role, user_name=f"{identity.user_name} (acting as {user.name})", company_name=company.name, ), ) elif impersonate_as: # impersonate as a user, using his own identity and permissions (required additional validation to verify # impersonated user is allowed to access the endpoint) service, _, action = endpoint.name.partition(".") call.impersonation = authorize_impersonation( user=user, identity=Identity( user=user.id, company=user.company, role=user.role, user_name= f"{user.name} (impersonated by {identity.user_name})", company_name=company.name, ), service=service, action=action, call=call, ) else: return False return True except APIError: raise except Exception as ex: log.exception(f"Validating impersonation: {str(ex)}") raise errors.server_error.InternalError("validating impersonation")
class EditUserReq(Base): user = StringField(required=True) role = EnumField(Role.get_company_roles())