From cbe78cc58eef477b7d5ffabf30400c1c195ebf49 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Mon, 6 Jun 2022 19:33:26 +0200 Subject: [PATCH] feat(db): removed user's appearance feat(db): removed generated_password feat(api): merged account&client feat(api): cleaned account response feat(api): removed user's appearance feat(api): removed generated_password feat(api): limits endpoint feat(api): notifications/count endpoint --- api/chalicelib/core/license.py | 15 +---- api/chalicelib/core/notifications.py | 18 ++++++ api/chalicelib/core/signup.py | 4 +- api/chalicelib/core/users.py | 55 +++++----------- api/routers/core.py | 12 ++-- api/routers/core_dynamic.py | 42 ++++++------ api/schemas.py | 5 -- ee/api/chalicelib/core/license.py | 16 +---- ee/api/chalicelib/core/notifications.py | 21 ++++++ ee/api/chalicelib/core/signup.py | 4 +- ee/api/chalicelib/core/users.py | 56 ++++------------ ee/api/routers/core_dynamic.py | 43 ++++++------- .../{1.6.1/1.6.1.sql => 1.7.0/1.7.0.sql} | 33 +++++++--- .../db/init_dbs/postgresql/init_schema.sql | 64 +------------------ .../{1.6.1/1.6.1.sql => 1.7.0/1.7.0.sql} | 8 ++- .../db/init_dbs/postgresql/init_schema.sql | 64 +------------------ 16 files changed, 153 insertions(+), 307 deletions(-) rename ee/scripts/helm/db/init_dbs/postgresql/{1.6.1/1.6.1.sql => 1.7.0/1.7.0.sql} (88%) rename scripts/helm/db/init_dbs/postgresql/{1.6.1/1.6.1.sql => 1.7.0/1.7.0.sql} (97%) diff --git a/api/chalicelib/core/license.py b/api/chalicelib/core/license.py index ab704778a..4a562ea7b 100644 --- a/api/chalicelib/core/license.py +++ b/api/chalicelib/core/license.py @@ -3,19 +3,10 @@ from chalicelib.utils import pg_client def get_status(tenant_id=None): with pg_client.PostgresClient() as cur: - cur.execute("SELECT * FROM public.tenants;") + # cur.execute("SELECT * FROM public.tenants;") + cur.execute("SELECT edition FROM public.tenants;") r = cur.fetchone() return { "hasActivePlan": True, - "current": { - "edition": r.get("edition", "").upper(), - "versionNumber": r.get("version_number", ""), - "license": "", - "expirationDate": -1 - }, - "count": { - "teamMember": r.get("t_users"), - "projects": r.get("t_projects"), - "capturedSessions": r.get("t_sessions") - } + "edition": r.get("edition", "").upper() } diff --git a/api/chalicelib/core/notifications.py b/api/chalicelib/core/notifications.py index 0d9b5be20..ce3c4d61a 100644 --- a/api/chalicelib/core/notifications.py +++ b/api/chalicelib/core/notifications.py @@ -25,6 +25,24 @@ def get_all(tenant_id, user_id): return rows +def get_all_count(tenant_id, user_id): + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify("""\ + SELECT COUNT(notifications.*) AS count + FROM public.notifications + LEFT JOIN (SELECT notification_id + FROM public.user_viewed_notifications + WHERE user_viewed_notifications.user_id = %(user_id)s) AS user_viewed_notifications USING (notification_id) + WHERE (notifications.user_id IS NULL OR notifications.user_id =%(user_id)s) AND user_viewed_notifications.notification_id IS NULL + ORDER BY created_at DESC + LIMIT 100;""", + {"user_id": user_id}) + ) + row = cur.fetchone() + return row + + def view_notification(user_id, notification_ids=[], tenant_id=None, startTimestamp=None, endTimestamp=None): if (notification_ids is None or len(notification_ids) == 0) and endTimestamp is None: return False diff --git a/api/chalicelib/core/signup.py b/api/chalicelib/core/signup.py index ab23eef68..4d320e0be 100644 --- a/api/chalicelib/core/signup.py +++ b/api/chalicelib/core/signup.py @@ -77,8 +77,8 @@ def create_step1(data: schemas.UserSignupSchema): RETURNING user_id,email,role,name ), au AS (INSERT - INTO public.basic_authentication (user_id, password, generated_password) - VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12)), FALSE) + INTO public.basic_authentication (user_id, password) + VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12))) ) INSERT INTO public.projects (name, active) VALUES (%(projectName)s, TRUE) diff --git a/api/chalicelib/core/users.py b/api/chalicelib/core/users.py index 3a4067f68..408fb03c1 100644 --- a/api/chalicelib/core/users.py +++ b/api/chalicelib/core/users.py @@ -21,10 +21,10 @@ def create_new_member(email, invitation_token, admin, name, owner=False): query = cur.mogrify(f"""\ WITH u AS (INSERT INTO public.users (email, role, name, data) VALUES (%(email)s, %(role)s, %(name)s, %(data)s) - RETURNING user_id,email,role,name,appearance + RETURNING user_id,email,role,name ), - au AS (INSERT INTO public.basic_authentication (user_id, generated_password, invitation_token, invited_at) - VALUES ((SELECT user_id FROM u), TRUE, %(invitation_token)s, timezone('utc'::text, now())) + au AS (INSERT INTO public.basic_authentication (user_id, invitation_token, invited_at) + VALUES ((SELECT user_id FROM u), %(invitation_token)s, timezone('utc'::text, now())) RETURNING invitation_token ) SELECT u.user_id, @@ -32,7 +32,6 @@ def create_new_member(email, invitation_token, admin, name, owner=False): u.email, u.role, u.name, - TRUE AS change_password, (CASE WHEN u.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN u.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN u.role = 'member' THEN TRUE ELSE FALSE END) AS member, @@ -61,7 +60,6 @@ def restore_member(user_id, email, invitation_token, admin, name, owner=False): email, role, name, - TRUE AS change_password, (CASE WHEN role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member;""", @@ -73,8 +71,7 @@ def restore_member(user_id, email, invitation_token, admin, name, owner=False): result = cur.fetchone() query = cur.mogrify("""\ UPDATE public.basic_authentication - SET generated_password = TRUE, - invitation_token = %(invitation_token)s, + SET invitation_token = %(invitation_token)s, invited_at = timezone('utc'::text, now()), change_pwd_expire_at = NULL, change_pwd_token = NULL @@ -132,11 +129,7 @@ def update(tenant_id, user_id, changes): else: sub_query_bauth.append(f"{helper.key_to_snake_case(key)} = %({key})s") else: - if key == "appearance": - sub_query_users.append(f"appearance = %(appearance)s::jsonb") - changes["appearance"] = json.dumps(changes[key]) - else: - sub_query_users.append(f"{helper.key_to_snake_case(key)} = %({key})s") + sub_query_users.append(f"{helper.key_to_snake_case(key)} = %({key})s") with pg_client.PostgresClient() as cur: if len(sub_query_users) > 0: @@ -151,11 +144,9 @@ def update(tenant_id, user_id, changes): users.email, users.role, users.name, - basic_authentication.generated_password AS change_password, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, - (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, - users.appearance;""", + (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member;""", {"user_id": user_id, **changes}) ) if len(sub_query_bauth) > 0: @@ -170,11 +161,9 @@ def update(tenant_id, user_id, changes): users.email, users.role, users.name, - basic_authentication.generated_password AS change_password, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, - (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, - users.appearance;""", + (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member;""", {"user_id": user_id, **changes}) ) @@ -244,15 +233,13 @@ def get(user_id, tenant_id): cur.execute( cur.mogrify( f"""SELECT - users.user_id AS id, + users.user_id, email, role, - name, - basic_authentication.generated_password, + name, (CASE WHEN role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member, - appearance, api_key FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id WHERE @@ -262,7 +249,7 @@ def get(user_id, tenant_id): {"userId": user_id}) ) r = cur.fetchone() - return helper.dict_to_camel_case(r, ignore_keys=["appearance"]) + return helper.dict_to_camel_case(r) def generate_new_api_key(user_id): @@ -282,7 +269,7 @@ def generate_new_api_key(user_id): def edit(user_id_to_update, tenant_id, changes, editor_id): - ALLOW_EDIT = ["name", "email", "admin", "appearance"] + ALLOW_EDIT = ["name", "email", "admin"] user = get(user_id=user_id_to_update, tenant_id=tenant_id) if editor_id != user_id_to_update or "admin" in changes and changes["admin"] != user["admin"]: admin = get(tenant_id=tenant_id, user_id=editor_id) @@ -315,11 +302,6 @@ def edit(user_id_to_update, tenant_id, changes, editor_id): return {"data": user} -def edit_appearance(user_id, tenant_id, changes): - updated_user = update(tenant_id=tenant_id, user_id=user_id, changes=changes) - return {"data": updated_user} - - def get_by_email_only(email): with pg_client.PostgresClient() as cur: cur.execute( @@ -329,8 +311,7 @@ def get_by_email_only(email): 1 AS tenant_id, users.email, users.role, - users.name, - basic_authentication.generated_password, + users.name, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member @@ -353,8 +334,7 @@ def get_by_email_reset(email, reset_token): 1 AS tenant_id, users.email, users.role, - users.name, - basic_authentication.generated_password, + users.name, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member @@ -377,8 +357,7 @@ def get_members(tenant_id): users.email, users.role, users.name, - users.created_at, - basic_authentication.generated_password, + users.created_at, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, @@ -581,11 +560,9 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): 1 AS tenant_id, users.role, users.name, - basic_authentication.generated_password AS change_password, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, - (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, - users.appearance + (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member FROM public.users INNER JOIN public.basic_authentication USING(user_id) WHERE users.email = %(email)s AND basic_authentication.password = crypt(%(password)s, basic_authentication.password) @@ -599,7 +576,7 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): if r is not None: if for_change_password: return True - r = helper.dict_to_camel_case(r, ignore_keys=["appearance"]) + r = helper.dict_to_camel_case(r) query = cur.mogrify( f"""UPDATE public.users SET jwt_iat = timezone('utc'::text, now()) diff --git a/api/routers/core.py b/api/routers/core.py index 813577b88..3008e94b7 100644 --- a/api/routers/core.py +++ b/api/routers/core.py @@ -966,6 +966,11 @@ def get_notifications(context: schemas.CurrentContext = Depends(OR_context)): return {"data": notifications.get_all(tenant_id=context.tenant_id, user_id=context.user_id)} +@app.get('/notifications/count', tags=['notifications']) +def get_notifications_count(context: schemas.CurrentContext = Depends(OR_context)): + return {"data": notifications.get_all_count(tenant_id=context.tenant_id, user_id=context.user_id)} + + @app.get('/notifications/{notificationId}/view', tags=['notifications']) def view_notifications(notificationId: int, context: schemas.CurrentContext = Depends(OR_context)): return {"data": notifications.view_notification(notification_ids=[notificationId], user_id=context.user_id)} @@ -1075,13 +1080,6 @@ def edit_account(data: schemas.EditUserSchema = Body(...), editor_id=context.user_id) -@app.post('/account/appearance', tags=["account"]) -@app.put('/account/appearance', tags=["account"]) -def edit_account_appearance(data: schemas.EditUserAppearanceSchema = Body(...), - context: schemas.CurrentContext = Depends(OR_context)): - return users.edit_appearance(tenant_id=context.tenant_id, user_id=context.user_id, changes=data.dict()) - - @app.post('/account/password', tags=["account"]) @app.put('/account/password', tags=["account"]) def change_client_password(data: schemas.EditUserPasswordSchema = Body(...), diff --git a/api/routers/core_dynamic.py b/api/routers/core_dynamic.py index e7e87e76c..7791c5677 100644 --- a/api/routers/core_dynamic.py +++ b/api/routers/core_dynamic.py @@ -67,17 +67,17 @@ def login(data: schemas.UserLoginSchema = Body(...)): @app.get('/account', tags=['accounts']) def get_account(context: schemas.CurrentContext = Depends(OR_context)): r = users.get(tenant_id=context.tenant_id, user_id=context.user_id) + t = tenants.get_by_tenant_id(context.tenant_id) + if t is not None: + t.pop("createdAt") + t["tenantName"] = t.pop("name") return { 'data': { **r, - "limits": { - "teamMember": -1, - "projects": -1, - "metadata": metadata.get_remaining_metadata_with_count(context.tenant_id) - }, + **t, **license.get_status(context.tenant_id), "smtp": helper.has_smtp(), - "iceServers": assist.get_ice_servers() + # "iceServers": assist.get_ice_servers() } } @@ -199,29 +199,25 @@ def search_sessions_by_metadata(key: str, value: str, projectId: Optional[int] = m_key=key, project_id=projectId)} -@app.get('/plans', tags=["plan"]) -def get_current_plan(context: schemas.CurrentContext = Depends(OR_context)): - return { - "data": license.get_status(context.tenant_id) - } - - @public_app.get('/general_stats', tags=["private"], include_in_schema=False) def get_general_stats(): return {"data": {"sessions:": sessions.count_all()}} -@app.get('/client', tags=['projects']) -def get_client(context: schemas.CurrentContext = Depends(OR_context)): - r = tenants.get_by_tenant_id(context.tenant_id) - if r is not None: - r.pop("createdAt") - return { - 'data': r - } - - @app.get('/projects', tags=['projects']) def get_projects(context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.get_projects(tenant_id=context.tenant_id, recording_state=True, gdpr=True, recorded=True, stack_integrations=True)} + + +@app.get('/limits', tags=['accounts']) +def get_limits(context: schemas.CurrentContext = Depends(OR_context)): + return { + 'data': { + "limits": { + "teamMember": -1, + "projects": -1, + "metadata": metadata.get_remaining_metadata_with_count(context.tenant_id) + }, + } + } diff --git a/api/schemas.py b/api/schemas.py index ff42fd7d3..fc61999ad 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -38,15 +38,10 @@ class EditUserSchema(BaseModel): name: Optional[str] = Field(None) email: Optional[EmailStr] = Field(None) admin: Optional[bool] = Field(False) - appearance: Optional[dict] = Field({}) _transform_email = validator('email', pre=True, allow_reuse=True)(transform_email) -class EditUserAppearanceSchema(BaseModel): - appearance: dict = Field(...) - - class ForgetPasswordPayloadSchema(_Grecaptcha): email: EmailStr = Field(...) diff --git a/ee/api/chalicelib/core/license.py b/ee/api/chalicelib/core/license.py index 2423567de..c1c9823d7 100644 --- a/ee/api/chalicelib/core/license.py +++ b/ee/api/chalicelib/core/license.py @@ -7,21 +7,11 @@ from chalicelib.utils import pg_client def get_status(tenant_id): with pg_client.PostgresClient() as cur: cur.execute( - cur.mogrify("SELECT * FROM public.tenants WHERE tenant_id=%(tenant_id)s;", {"tenant_id": tenant_id})) + # cur.mogrify("SELECT * FROM public.tenants WHERE tenant_id=%(tenant_id)s;", {"tenant_id": tenant_id})) + cur.mogrify("SELECT edition FROM public.tenants WHERE tenant_id=%(tenant_id)s;", {"tenant_id": tenant_id})) r = cur.fetchone() license = unlock.get_license() return { "hasActivePlan": unlock.is_valid(), - "current": { - "edition": r.get("edition", "").lower(), - "versionNumber": r.get("version_number", ""), - "license": license[0:2] + "*" * (len(license) - 4) + license[-2:], - "expirationDate": unlock.get_expiration_date(), - "teamMember": config("numberOfSeats", cast=int, default=0) - }, - "count": { - "teamMember": r.get("t_users"), - "projects": r.get("t_projects"), - "capturedSessions": r.get("t_sessions") - } + "edition": r.get("edition", "").lower(), } diff --git a/ee/api/chalicelib/core/notifications.py b/ee/api/chalicelib/core/notifications.py index 41c26b74c..5ba58f242 100644 --- a/ee/api/chalicelib/core/notifications.py +++ b/ee/api/chalicelib/core/notifications.py @@ -26,6 +26,27 @@ def get_all(tenant_id, user_id): return rows +def get_all_count(tenant_id, user_id): + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify("""\ + SELECT COUNT(notifications.*) + FROM public.notifications + LEFT JOIN (SELECT notification_id + FROM public.user_viewed_notifications + WHERE user_viewed_notifications.user_id = %(user_id)s) AS user_viewed_notifications USING (notification_id) + WHERE (notifications.tenant_id =%(tenant_id)s + OR notifications.user_id =%(user_id)s) AND user_viewed_notifications.notification_id IS NULL + ORDER BY created_at DESC + LIMIT 100;""", + {"tenant_id": tenant_id, "user_id": user_id}) + ) + rows = helper.list_to_camel_case(cur.fetchall()) + for r in rows: + r["createdAt"] = TimeUTC.datetime_to_timestamp(r["createdAt"]) + return rows + + def view_notification(user_id, notification_ids=[], tenant_id=None, startTimestamp=None, endTimestamp=None): if (notification_ids is None or len(notification_ids) == 0) and endTimestamp is None: return False diff --git a/ee/api/chalicelib/core/signup.py b/ee/api/chalicelib/core/signup.py index 4014f5e92..0415efc79 100644 --- a/ee/api/chalicelib/core/signup.py +++ b/ee/api/chalicelib/core/signup.py @@ -80,8 +80,8 @@ def create_step1(data: schemas.UserSignupSchema): RETURNING user_id,email,role,name,role_id ), au AS ( - INSERT INTO public.basic_authentication (user_id, password, generated_password) - VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12)), FALSE) + INSERT INTO public.basic_authentication (user_id, password) + VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12))) ) INSERT INTO public.projects (tenant_id, name, active) VALUES ((SELECT t.tenant_id FROM t), %(projectName)s, TRUE) diff --git a/ee/api/chalicelib/core/users.py b/ee/api/chalicelib/core/users.py index 5d28dc395..1f97fbd09 100644 --- a/ee/api/chalicelib/core/users.py +++ b/ee/api/chalicelib/core/users.py @@ -25,10 +25,10 @@ def create_new_member(tenant_id, email, invitation_token, admin, name, owner=Fal (SELECT COALESCE((SELECT role_id FROM roles WHERE tenant_id = %(tenant_id)s AND role_id = %(role_id)s), (SELECT role_id FROM roles WHERE tenant_id = %(tenant_id)s AND name = 'Member' LIMIT 1), (SELECT role_id FROM roles WHERE tenant_id = %(tenant_id)s AND name != 'Owner' LIMIT 1)))) - RETURNING tenant_id,user_id,email,role,name,appearance, role_id + RETURNING tenant_id,user_id,email,role,name, role_id ), - au AS (INSERT INTO public.basic_authentication (user_id, generated_password, invitation_token, invited_at) - VALUES ((SELECT user_id FROM u), TRUE, %(invitation_token)s, timezone('utc'::text, now())) + au AS (INSERT INTO public.basic_authentication (user_id, invitation_token, invited_at) + VALUES ((SELECT user_id FROM u), %(invitation_token)s, timezone('utc'::text, now())) RETURNING invitation_token ) SELECT u.user_id AS id, @@ -36,7 +36,6 @@ def create_new_member(tenant_id, email, invitation_token, admin, name, owner=Fal u.email, u.role, u.name, - TRUE AS change_password, (CASE WHEN u.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN u.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN u.role = 'member' THEN TRUE ELSE FALSE END) AS member, @@ -74,7 +73,6 @@ def restore_member(tenant_id, user_id, email, invitation_token, admin, name, own email, role, name, - TRUE AS change_password, (CASE WHEN role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member, @@ -88,8 +86,7 @@ def restore_member(tenant_id, user_id, email, invitation_token, admin, name, own result = cur.fetchone() query = cur.mogrify("""\ UPDATE public.basic_authentication - SET generated_password = TRUE, - invitation_token = %(invitation_token)s, + SET invitation_token = %(invitation_token)s, invited_at = timezone('utc'::text, now()), change_pwd_expire_at = NULL, change_pwd_token = NULL @@ -147,10 +144,7 @@ def update(tenant_id, user_id, changes): else: sub_query_bauth.append(f"{helper.key_to_snake_case(key)} = %({key})s") else: - if key == "appearance": - sub_query_users.append(f"appearance = %(appearance)s::jsonb") - changes["appearance"] = json.dumps(changes[key]) - elif helper.key_to_snake_case(key) == "role_id": + if helper.key_to_snake_case(key) == "role_id": sub_query_users.append("""role_id=(SELECT COALESCE((SELECT role_id FROM roles WHERE tenant_id = %(tenant_id)s AND role_id = %(role_id)s), (SELECT role_id FROM roles WHERE tenant_id = %(tenant_id)s AND name = 'Member' LIMIT 1), (SELECT role_id FROM roles WHERE tenant_id = %(tenant_id)s AND name != 'Owner' LIMIT 1)))""") @@ -171,11 +165,9 @@ def update(tenant_id, user_id, changes): users.email, users.role, users.name, - basic_authentication.generated_password AS change_password, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, - users.appearance, users.role_id;""", {"tenant_id": tenant_id, "user_id": user_id, **changes}) ) @@ -192,11 +184,9 @@ def update(tenant_id, user_id, changes): users.email, users.role, users.name, - basic_authentication.generated_password AS change_password, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, - users.appearance, users.role_id;""", {"tenant_id": tenant_id, "user_id": user_id, **changes}) ) @@ -272,12 +262,10 @@ def get(user_id, tenant_id): users.user_id AS id, email, role, - users.name, - basic_authentication.generated_password, + users.name, (CASE WHEN role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member, - appearance, api_key, origin, role_id, @@ -296,7 +284,7 @@ def get(user_id, tenant_id): {"userId": user_id, "tenant_id": tenant_id}) ) r = cur.fetchone() - return helper.dict_to_camel_case(r, ignore_keys=["appearance"]) + return helper.dict_to_camel_case(r) def generate_new_api_key(user_id): @@ -316,7 +304,7 @@ def generate_new_api_key(user_id): def edit(user_id_to_update, tenant_id, changes, editor_id): - ALLOW_EDIT = ["name", "email", "admin", "appearance", "roleId"] + ALLOW_EDIT = ["name", "email", "admin", "roleId"] user = get(user_id=user_id_to_update, tenant_id=tenant_id) if editor_id != user_id_to_update or "admin" in changes and changes["admin"] != user["admin"]: admin = get(tenant_id=tenant_id, user_id=editor_id) @@ -349,11 +337,6 @@ def edit(user_id_to_update, tenant_id, changes, editor_id): return {"data": user} -def edit_appearance(user_id, tenant_id, changes): - updated_user = update(tenant_id=tenant_id, user_id=user_id, changes=changes) - return {"data": updated_user} - - def get_by_email_only(email): with pg_client.PostgresClient() as cur: cur.execute( @@ -363,8 +346,7 @@ def get_by_email_only(email): users.tenant_id, users.email, users.role, - users.name, - basic_authentication.generated_password, + users.name, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, @@ -389,8 +371,7 @@ def get_by_email_reset(email, reset_token): users.tenant_id, users.email, users.role, - users.name, - basic_authentication.generated_password, + users.name, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member @@ -414,8 +395,7 @@ def get_members(tenant_id): users.email, users.role, users.name, - users.created_at, - basic_authentication.generated_password, + users.created_at, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, @@ -642,11 +622,9 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): users.tenant_id, users.role, users.name, - basic_authentication.generated_password AS change_password, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, - users.appearance, users.origin, users.role_id, roles.name AS role_name, @@ -678,7 +656,7 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): if r is not None: if for_change_password: return True - r = helper.dict_to_camel_case(r, ignore_keys=["appearance"]) + r = helper.dict_to_camel_case(r) jwt_iat = change_jwt_iat(r['id']) return { "jwt": authorizers.generate_jwt(r['id'], r['tenantId'], @@ -698,11 +676,9 @@ def authenticate_sso(email, internal_id, exp=None): users.tenant_id, users.role, users.name, - False AS change_password, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, - users.appearance, origin, role_id FROM public.users AS users @@ -713,7 +689,7 @@ def authenticate_sso(email, internal_id, exp=None): r = cur.fetchone() if r is not None: - r = helper.dict_to_camel_case(r, ignore_keys=["appearance"]) + r = helper.dict_to_camel_case(r) jwt_iat = TimeUTC.datetime_to_timestamp(change_jwt_iat(r['id'])) return authorizers.generate_jwt(r['id'], r['tenantId'], jwt_iat, aud=f"front:{helper.get_stage_name()}", @@ -740,11 +716,9 @@ def create_sso_user(tenant_id, email, admin, name, origin, role_id, internal_id= u.email, u.role, u.name, - TRUE AS change_password, (CASE WHEN u.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN u.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN u.role = 'member' THEN TRUE ELSE FALSE END) AS member, - u.appearance, origin FROM u;""", {"tenant_id": tenant_id, "email": email, "internal_id": internal_id, @@ -774,7 +748,6 @@ def restore_sso_user(user_id, tenant_id, email, admin, name, origin, role_id, in created_at= default, api_key= default, jwt_iat= NULL, - appearance= default, weekly_report= default WHERE user_id = %(user_id)s RETURNING * @@ -782,7 +755,6 @@ def restore_sso_user(user_id, tenant_id, email, admin, name, origin, role_id, in au AS ( UPDATE public.basic_authentication SET password= default, - generated_password= default, invitation_token= default, invited_at= default, change_pwd_token= default, @@ -795,11 +767,9 @@ def restore_sso_user(user_id, tenant_id, email, admin, name, origin, role_id, in u.email, u.role, u.name, - TRUE AS change_password, (CASE WHEN u.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN u.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN u.role = 'member' THEN TRUE ELSE FALSE END) AS member, - u.appearance, origin FROM u;""", {"tenant_id": tenant_id, "email": email, "internal_id": internal_id, diff --git a/ee/api/routers/core_dynamic.py b/ee/api/routers/core_dynamic.py index 31ed1d099..6d7cf8e73 100644 --- a/ee/api/routers/core_dynamic.py +++ b/ee/api/routers/core_dynamic.py @@ -72,18 +72,18 @@ def login(data: schemas.UserLoginSchema = Body(...)): @app.get('/account', tags=['accounts']) def get_account(context: schemas.CurrentContext = Depends(OR_context)): r = users.get(tenant_id=context.tenant_id, user_id=context.user_id) + t = tenants.get_by_tenant_id(context.tenant_id) + if t is not None: + t.pop("createdAt") + t["tenantName"] = t.pop("name") return { 'data': { **r, - "limits": { - "teamMember": -1, - "projects": -1, - "metadata": metadata.get_remaining_metadata_with_count(context.tenant_id) - }, + **t, **license.get_status(context.tenant_id), "smtp": helper.has_smtp(), "saml2": SAML2_helper.is_saml2_available(), - "iceServers": assist.get_ice_servers() + # "iceServers": assist.get_ice_servers() } } @@ -209,30 +209,25 @@ def search_sessions_by_metadata(key: str, value: str, projectId: Optional[int] = m_key=key, project_id=projectId)} -@app.get('/plans', tags=["plan"]) -def get_current_plan(context: schemas.CurrentContext = Depends(OR_context)): - return { - "data": license.get_status(context.tenant_id) - } - - @public_app.get('/general_stats', tags=["private"], include_in_schema=False) def get_general_stats(): return {"data": {"sessions:": sessions.count_all()}} -@app.get('/client', tags=['projects']) -def get_client(context: schemas.CurrentContext = Depends(OR_context)): - r = tenants.get_by_tenant_id(context.tenant_id) - if r is not None: - r.pop("createdAt") - - return { - 'data': r - } - - @app.get('/projects', tags=['projects']) def get_projects(context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.get_projects(tenant_id=context.tenant_id, recording_state=True, gdpr=True, recorded=True, stack_integrations=True, user_id=context.user_id)} + + +@app.get('/limits', tags=['accounts']) +def get_limits(context: schemas.CurrentContext = Depends(OR_context)): + return { + 'data': { + "limits": { + "teamMember": -1, + "projects": -1, + "metadata": metadata.get_remaining_metadata_with_count(context.tenant_id) + } + } + } diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.6.1/1.6.1.sql b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql similarity index 88% rename from ee/scripts/helm/db/init_dbs/postgresql/1.6.1/1.6.1.sql rename to ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index 325d419ba..1ab026565 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/1.6.1/1.6.1.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -1,18 +1,25 @@ BEGIN; -CREATE OR REPLACE FUNCTION openreplay_version() +CREATE OR REPLACE +FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.6.1-ee' -$$ LANGUAGE sql IMMUTABLE; +SELECT 'v1.6.1-ee' $$ LANGUAGE sql IMMUTABLE; ALTER TABLE IF EXISTS dashboards - ADD COLUMN IF NOT EXISTS description text NOT NULL DEFAULT ''; + ADD COLUMN IF NOT +EXISTS description text NOT NULL DEFAULT ''; -CREATE INDEX IF NOT EXISTS traces_created_at_idx ON traces (created_at); -CREATE INDEX IF NOT EXISTS traces_action_idx ON traces (action); -CREATE INDEX IF NOT EXISTS users_name_gin_idx ON users USING GIN (name gin_trgm_ops); +CREATE +INDEX IF NOT +EXISTS traces_created_at_idx ON traces (created_at); +CREATE +INDEX IF NOT +EXISTS traces_action_idx ON traces (action); +CREATE +INDEX IF NOT +EXISTS users_name_gin_idx ON users USING GIN (name gin_trgm_ops); INSERT INTO metrics (name, category, default_config, is_predefined, is_template, is_public, predefined_key, metric_type, view_type) @@ -115,9 +122,9 @@ VALUES ('Captured sessions', 'web vitals', '{ "col": 1, "row": 1, "position": 0 - }', true, true, true, 'avg_fps', 'predefined', 'overview') -ON CONFLICT (predefined_key) DO UPDATE - SET name=excluded.name, + }', true, true, true, 'avg_fps', 'predefined', 'overview') ON CONFLICT (predefined_key) DO +UPDATE +SET name =excluded.name, category=excluded.category, default_config=excluded.default_config, is_predefined=excluded.is_predefined, @@ -126,4 +133,10 @@ ON CONFLICT (predefined_key) DO UPDATE metric_type=excluded.metric_type, view_type=excluded.view_type; +ALTER TABLE users + DROP COLUMN appearance; + +ALTER TABLE basic_authentication + DROP COLUMN generated_password; + COMMIT; \ No newline at end of file diff --git a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql index ec29b1dfc..efb4bb1d1 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -7,7 +7,7 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE OR REPLACE FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.6.0-ee' +SELECT 'v1.7.0-ee' $$ LANGUAGE sql IMMUTABLE; @@ -187,67 +187,6 @@ $$ name text NOT NULL, created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), deleted_at timestamp without time zone NULL DEFAULT NULL, - appearance jsonb NOT NULL default '{ - "role": "dev", - "dashboard": { - "cpu": true, - "fps": false, - "avgCpu": true, - "avgFps": true, - "errors": true, - "crashes": true, - "overview": true, - "sessions": true, - "topMetrics": true, - "callsErrors": true, - "pageMetrics": true, - "performance": true, - "timeToRender": false, - "userActivity": false, - "avgFirstPaint": false, - "countSessions": true, - "errorsPerType": true, - "slowestImages": true, - "speedLocation": true, - "slowestDomains": true, - "avgPageLoadTime": true, - "avgTillFirstBit": false, - "avgTimeToRender": true, - "avgVisitedPages": false, - "avgImageLoadTime": true, - "busiestTimeOfDay": true, - "errorsPerDomains": true, - "missingResources": true, - "resourcesByParty": true, - "sessionsFeedback": false, - "slowestResources": true, - "avgUsedJsHeapSize": true, - "domainsErrors_4xx": true, - "domainsErrors_5xx": true, - "memoryConsumption": true, - "pagesDomBuildtime": false, - "pagesResponseTime": true, - "avgRequestLoadTime": true, - "avgSessionDuration": false, - "sessionsPerBrowser": false, - "applicationActivity": true, - "sessionsFrustration": false, - "avgPagesDomBuildtime": true, - "avgPagesResponseTime": false, - "avgTimeToInteractive": true, - "resourcesCountByType": true, - "resourcesLoadingTime": true, - "avgDomContentLoadStart": true, - "avgFirstContentfulPixel": false, - "resourceTypeVsResponseEnd": true, - "impactedSessionsByJsErrors": true, - "impactedSessionsBySlowPages": true, - "resourcesVsVisuallyComplete": true, - "pagesResponseTimeDistribution": true - }, - "sessionsLive": false, - "sessionsDevtools": true - }'::jsonb, api_key text UNIQUE default generate_api_key(20) not null, jwt_iat timestamp without time zone NULL DEFAULT NULL, data jsonb NOT NULL DEFAULT'{}'::jsonb, @@ -264,7 +203,6 @@ $$ ( user_id integer NOT NULL REFERENCES users (user_id) ON DELETE CASCADE, password text DEFAULT NULL, - generated_password boolean NOT NULL DEFAULT false, invitation_token text NULL DEFAULT NULL, invited_at timestamp without time zone NULL DEFAULT NULL, change_pwd_token text NULL DEFAULT NULL, diff --git a/scripts/helm/db/init_dbs/postgresql/1.6.1/1.6.1.sql b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql similarity index 97% rename from scripts/helm/db/init_dbs/postgresql/1.6.1/1.6.1.sql rename to scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index 4f1c7c28f..233f4fc5e 100644 --- a/scripts/helm/db/init_dbs/postgresql/1.6.1/1.6.1.sql +++ b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -2,7 +2,7 @@ BEGIN; CREATE OR REPLACE FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.6.1' +SELECT 'v1.7.0' $$ LANGUAGE sql IMMUTABLE; @@ -121,4 +121,10 @@ ON CONFLICT (predefined_key) DO UPDATE metric_type=excluded.metric_type, view_type=excluded.view_type; +ALTER TABLE users + DROP COLUMN appearance; + +ALTER TABLE basic_authentication + DROP COLUMN generated_password; + COMMIT; \ No newline at end of file diff --git a/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/scripts/helm/db/init_dbs/postgresql/init_schema.sql index 91a590688..519997f72 100644 --- a/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -6,7 +6,7 @@ CREATE SCHEMA IF NOT EXISTS events; CREATE OR REPLACE FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.6.0' +SELECT 'v1.7.0' $$ LANGUAGE sql IMMUTABLE; -- --- accounts.sql --- @@ -142,67 +142,6 @@ $$ name text NOT NULL, created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), deleted_at timestamp without time zone NULL DEFAULT NULL, - appearance jsonb NOT NULL default '{ - "role": "dev", - "dashboard": { - "cpu": true, - "fps": false, - "avgCpu": true, - "avgFps": true, - "errors": true, - "crashes": true, - "overview": true, - "sessions": true, - "topMetrics": true, - "callsErrors": true, - "pageMetrics": true, - "performance": true, - "timeToRender": false, - "userActivity": false, - "avgFirstPaint": false, - "countSessions": true, - "errorsPerType": true, - "slowestImages": true, - "speedLocation": true, - "slowestDomains": true, - "avgPageLoadTime": true, - "avgTillFirstBit": false, - "avgTimeToRender": true, - "avgVisitedPages": false, - "avgImageLoadTime": true, - "busiestTimeOfDay": true, - "errorsPerDomains": true, - "missingResources": true, - "resourcesByParty": true, - "sessionsFeedback": false, - "slowestResources": true, - "avgUsedJsHeapSize": true, - "domainsErrors_4xx": true, - "domainsErrors_5xx": true, - "memoryConsumption": true, - "pagesDomBuildtime": false, - "pagesResponseTime": true, - "avgRequestLoadTime": true, - "avgSessionDuration": false, - "sessionsPerBrowser": false, - "applicationActivity": true, - "sessionsFrustration": false, - "avgPagesDomBuildtime": true, - "avgPagesResponseTime": false, - "avgTimeToInteractive": true, - "resourcesCountByType": true, - "resourcesLoadingTime": true, - "avgDomContentLoadStart": true, - "avgFirstContentfulPixel": false, - "resourceTypeVsResponseEnd": true, - "impactedSessionsByJsErrors": true, - "impactedSessionsBySlowPages": true, - "resourcesVsVisuallyComplete": true, - "pagesResponseTimeDistribution": true - }, - "sessionsLive": false, - "sessionsDevtools": true - }'::jsonb, api_key text UNIQUE default generate_api_key(20) not null, jwt_iat timestamp without time zone NULL DEFAULT NULL, data jsonb NOT NULL DEFAULT '{}'::jsonb, @@ -213,7 +152,6 @@ $$ ( user_id integer NOT NULL REFERENCES users (user_id) ON DELETE CASCADE, password text DEFAULT NULL, - generated_password boolean NOT NULL DEFAULT false, invitation_token text NULL DEFAULT NULL, invited_at timestamp without time zone NULL DEFAULT NULL, change_pwd_token text NULL DEFAULT NULL,