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
This commit is contained in:
Taha Yassine Kraiem 2022-06-06 19:33:26 +02:00
parent a6c75d3cdd
commit cbe78cc58e
16 changed files with 153 additions and 307 deletions

View file

@ -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()
}

View file

@ -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

View file

@ -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)

View file

@ -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())

View file

@ -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(...),

View file

@ -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)
},
}
}

View file

@ -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(...)

View file

@ -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(),
}

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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)
}
}
}

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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,