Exemple #1
0
    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)}")
Exemple #2
0
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)
Exemple #3
0
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,
    )
Exemple #4
0
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")
Exemple #5
0
class EditUserReq(Base):
    user = StringField(required=True)
    role = EnumField(Role.get_company_roles())