mirror of
https://github.com/clearml/clearml-server
synced 2025-05-06 13:04:45 +00:00
Improve handling of fixed users
This commit is contained in:
parent
92a4e56c1f
commit
5189adf4f1
@ -58,6 +58,9 @@
|
||||
# verify user tokens
|
||||
verify_user_tokens: false
|
||||
|
||||
# If set then users that were created from secure credentials or fixed user settings and are no longer in these settings will be deleted on startup
|
||||
delete_missing_autocreated_users: true
|
||||
|
||||
# max token expiration timeout in seconds (1 year)
|
||||
max_expiration_sec: 31536000
|
||||
|
||||
|
@ -4,6 +4,7 @@ from mongoengine import (
|
||||
EmbeddedDocumentListField,
|
||||
EmailField,
|
||||
DateTimeField,
|
||||
BooleanField,
|
||||
)
|
||||
|
||||
from apiserver.database import Database, strict
|
||||
@ -76,3 +77,6 @@ class User(DbModelMixin, AuthDocument):
|
||||
|
||||
email = EmailField(unique=True, sparse=True)
|
||||
""" Email uniquely identifying the user """
|
||||
|
||||
autocreated = BooleanField(default=False)
|
||||
""" Set to true if the user was auto created based on config settings"""
|
||||
|
@ -3,7 +3,7 @@ from typing import Sequence, Union
|
||||
|
||||
from apiserver.config_repo import config
|
||||
from apiserver.config.info import get_default_company
|
||||
from apiserver.database.model.auth import Role
|
||||
from apiserver.database.model.auth import Role, User as AuthUser
|
||||
from apiserver.service_repo.auth.fixed_user import FixedUser
|
||||
from .migration import _apply_migrations, check_mongo_empty, get_last_server_version
|
||||
from .pre_populate import PrePopulate
|
||||
@ -60,14 +60,18 @@ def init_mongo_data():
|
||||
|
||||
fixed_mode = FixedUser.enabled()
|
||||
|
||||
internal_user_emails = set()
|
||||
for user, credentials in config.get("secure.credentials", {}).items():
|
||||
email = f"{user}@example.com"
|
||||
user_data = {
|
||||
"name": user,
|
||||
"role": credentials.role,
|
||||
"email": f"{user}@example.com",
|
||||
"email": email,
|
||||
"key": credentials.user_key,
|
||||
"secret": credentials.user_secret,
|
||||
"autocreated": True,
|
||||
}
|
||||
internal_user_emails.add(email.lower())
|
||||
revoke = fixed_mode and credentials.get("revoke_in_fixed_mode", False)
|
||||
user_id = _ensure_auth_user(user_data, company_id, log=log, revoke=revoke)
|
||||
if credentials.role == Role.user:
|
||||
@ -82,8 +86,20 @@ def init_mongo_data():
|
||||
|
||||
for user in FixedUser.from_config():
|
||||
try:
|
||||
ensure_fixed_user(user, log=log)
|
||||
ensure_fixed_user(user, log=log, emails=internal_user_emails)
|
||||
except Exception as ex:
|
||||
log.error(f"Failed creating fixed user {user.name}: {ex}")
|
||||
|
||||
if internal_user_emails and config.get(
|
||||
f"apiserver.auth.delete_missing_autocreated_users", True
|
||||
):
|
||||
for user in AuthUser.objects(
|
||||
company=company_id, autocreated=True, email__nin=internal_user_emails
|
||||
):
|
||||
log.info(
|
||||
f"Removing user that is no longer in configuration: {user['id']}\t{user['email']}\t{user['name']}"
|
||||
)
|
||||
user.delete()
|
||||
|
||||
except Exception as ex:
|
||||
log.exception("Failed initializing mongodb")
|
||||
log.exception(f"Failed initializing mongodb: {str(ex)}")
|
||||
|
@ -26,6 +26,7 @@ def _ensure_auth_user(user_data: dict, company_id: str, log: Logger, revoke: boo
|
||||
credentials = [] if revoke else [creds]
|
||||
|
||||
user_id = user_data.get("id", f"__{user_data['name']}__")
|
||||
autocreated = user_data.get("autocreated", False)
|
||||
|
||||
log.info(f"Creating user: {user_data['name']}")
|
||||
|
||||
@ -37,6 +38,7 @@ def _ensure_auth_user(user_data: dict, company_id: str, log: Logger, revoke: boo
|
||||
email=user_data["email"],
|
||||
created=datetime.utcnow(),
|
||||
credentials=credentials,
|
||||
autocreated=autocreated,
|
||||
)
|
||||
|
||||
user.save()
|
||||
@ -59,7 +61,7 @@ def _ensure_backend_user(user_id: str, company_id: str, user_name: str):
|
||||
return user_id
|
||||
|
||||
|
||||
def ensure_fixed_user(user: FixedUser, log: Logger):
|
||||
def ensure_fixed_user(user: FixedUser, log: Logger, emails: set):
|
||||
db_user = User.objects(company=user.company, id=user.user_id).first()
|
||||
if db_user:
|
||||
# noinspection PyBroadException
|
||||
@ -73,9 +75,12 @@ def ensure_fixed_user(user: FixedUser, log: Logger):
|
||||
|
||||
data = attr.asdict(user)
|
||||
data["id"] = user.user_id
|
||||
data["email"] = f"{user.user_id}@example.com"
|
||||
email = f"{user.user_id}@example.com"
|
||||
data["email"] = email
|
||||
data["role"] = Role.guest if user.is_guest else Role.user
|
||||
data["autocreated"] = True
|
||||
|
||||
_ensure_auth_user(user_data=data, company_id=user.company, log=log)
|
||||
emails.add(email)
|
||||
|
||||
return _ensure_backend_user(user.user_id, user.company, user.name)
|
||||
|
@ -16,7 +16,7 @@ from apiserver.bll.project import ProjectBLL
|
||||
from apiserver.bll.user import UserBLL
|
||||
from apiserver.config_repo import config
|
||||
from apiserver.database.errors import translate_errors_context
|
||||
from apiserver.database.model.auth import Role
|
||||
from apiserver.database.model.auth import Role, User as AuthUser
|
||||
from apiserver.database.model.company import Company
|
||||
from apiserver.database.model.user import User
|
||||
from apiserver.database.utils import parse_from_call
|
||||
@ -158,9 +158,17 @@ def update_user(user_id, company_id, data: dict) -> Tuple[int, dict]:
|
||||
update_fields = {
|
||||
k: v for k, v in create_fields.items() if k in User.user_set_allowed()
|
||||
}
|
||||
auth_user_update_fields = ("name",)
|
||||
partial_update_dict = parse_from_call(data, update_fields, User.get_fields())
|
||||
with translate_errors_context("updating user"):
|
||||
return User.safe_update(company_id, user_id, partial_update_dict)
|
||||
ret = User.safe_update(company_id, user_id, partial_update_dict)
|
||||
auth_update = {
|
||||
k: v for k, v in partial_update_dict.items() if k in auth_user_update_fields
|
||||
}
|
||||
if auth_update:
|
||||
AuthUser.objects(id=user_id).update(**auth_update)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@endpoint("users.update", response_data_model=UpdateResponse)
|
||||
|
Loading…
Reference in New Issue
Block a user