diff --git a/api/chalicelib/core/license.py b/api/chalicelib/core/license.py index 4a562ea7b..469753878 100644 --- a/api/chalicelib/core/license.py +++ b/api/chalicelib/core/license.py @@ -1,12 +1,9 @@ -from chalicelib.utils import pg_client +EDITION = 'foss' def get_status(tenant_id=None): - with pg_client.PostgresClient() as cur: - # cur.execute("SELECT * FROM public.tenants;") - cur.execute("SELECT edition FROM public.tenants;") - r = cur.fetchone() return { "hasActivePlan": True, - "edition": r.get("edition", "").upper() + "edition": EDITION, + "expirationDate": -1 } diff --git a/api/chalicelib/core/signup.py b/api/chalicelib/core/signup.py index 4d320e0be..146da7305 100644 --- a/api/chalicelib/core/signup.py +++ b/api/chalicelib/core/signup.py @@ -67,8 +67,8 @@ def create_step1(data: schemas.UserSignupSchema): } query = f"""\ WITH t AS ( - INSERT INTO public.tenants (name, version_number, edition) - VALUES (%(organizationName)s, (SELECT openreplay_version()), 'fos') + INSERT INTO public.tenants (name, version_number) + VALUES (%(organizationName)s, (SELECT openreplay_version())) RETURNING api_key ), u AS ( diff --git a/api/chalicelib/core/telemetry.py b/api/chalicelib/core/telemetry.py index fa27fbe1c..e12200809 100644 --- a/api/chalicelib/core/telemetry.py +++ b/api/chalicelib/core/telemetry.py @@ -1,10 +1,11 @@ from chalicelib.utils import pg_client import requests +from chalicelib.core import license -def process_data(data, edition='fos'): +def process_data(data): return { - 'edition': edition, + 'edition': license.EDITION, 'tracking': data["opt_out"], 'version': data["version_number"], 'user_id': data["user_id"], diff --git a/api/chalicelib/core/tenants.py b/api/chalicelib/core/tenants.py index db154525c..e5b8cc63c 100644 --- a/api/chalicelib/core/tenants.py +++ b/api/chalicelib/core/tenants.py @@ -1,7 +1,7 @@ import schemas from chalicelib.utils import pg_client from chalicelib.utils import helper -from chalicelib.core import users +from chalicelib.core import users, license def get_by_tenant_id(tenant_id): @@ -13,7 +13,7 @@ def get_by_tenant_id(tenant_id): name, api_key, created_at, - edition, + '{license.EDITION}' AS edition, version_number, opt_out FROM public.tenants @@ -67,7 +67,7 @@ def update(tenant_id, user_id, data: schemas.UpdateTenantSchema): admin = users.get(user_id=user_id, tenant_id=tenant_id) if not admin["admin"] and not admin["superAdmin"]: - return {"error": "unauthorized"} + return {"errors": ["unauthorized, needs admin or owner"]} if data.name is None and data.opt_out is None: return {"errors": ["please provide 'name' of 'optOut' attribute for update"]} changes = {} diff --git a/api/chalicelib/core/users.py b/api/chalicelib/core/users.py index 408fb03c1..0e9852e2d 100644 --- a/api/chalicelib/core/users.py +++ b/api/chalicelib/core/users.py @@ -4,6 +4,7 @@ import secrets from decouple import config from fastapi import BackgroundTasks +import schemas from chalicelib.core import authorizers, metadata, projects from chalicelib.core import tenants, assist from chalicelib.utils import dev, email_helper @@ -240,7 +241,8 @@ def get(user_id, tenant_id): (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, - api_key + api_key, + TRUE AS has_password FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id WHERE users.user_id = %(userId)s @@ -268,37 +270,36 @@ def generate_new_api_key(user_id): return helper.dict_to_camel_case(r) -def edit(user_id_to_update, tenant_id, changes, editor_id): - ALLOW_EDIT = ["name", "email", "admin"] +def edit(user_id_to_update, tenant_id, changes: schemas.EditUserSchema, editor_id): 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"]: + if editor_id != user_id_to_update or changes.admin is not None and changes.admin != user["admin"]: admin = get(tenant_id=tenant_id, user_id=editor_id) if not admin["superAdmin"] and not admin["admin"]: return {"errors": ["unauthorized"]} + _changes = {} if editor_id == user_id_to_update: - if user["superAdmin"]: - changes.pop("admin") - elif user["admin"] != changes["admin"]: - return {"errors": ["cannot change your own role"]} + if changes.admin is not None: + if user["superAdmin"]: + changes.admin = None + elif changes.admin != user["admin"]: + return {"errors": ["cannot change your own role"]} - keys = list(changes.keys()) - for k in keys: - if k not in ALLOW_EDIT or changes[k] is None: - changes.pop(k) - keys = list(changes.keys()) + if changes.email is not None and changes.email != user["email"]: + if email_exists(changes.email): + return {"errors": ["email already exists."]} + if get_deleted_user_by_email(changes.email) is not None: + return {"errors": ["email previously deleted."]} + _changes["email"] = changes.email - if len(keys) > 0: - if "email" in keys and changes["email"] != user["email"]: - if email_exists(changes["email"]): - return {"errors": ["email already exists."]} - if get_deleted_user_by_email(changes["email"]) is not None: - return {"errors": ["email previously deleted."]} - if "admin" in keys: - changes["role"] = "admin" if changes.pop("admin") else "member" - if len(changes.keys()) > 0: - updated_user = update(tenant_id=tenant_id, user_id=user_id_to_update, changes=changes) + if changes.name is not None and len(changes.name) > 0: + _changes["name"] = changes.name - return {"data": updated_user} + if changes.admin is not None: + _changes["role"] = "admin" if changes.admin else "member" + + if len(_changes.keys()) > 0: + updated_user = update(tenant_id=tenant_id, user_id=user_id_to_update, changes=_changes) + return {"data": updated_user} return {"data": user} diff --git a/api/chalicelib/utils/helper.py b/api/chalicelib/utils/helper.py index 042b2a94b..2716cf111 100644 --- a/api/chalicelib/utils/helper.py +++ b/api/chalicelib/utils/helper.py @@ -365,10 +365,6 @@ def has_smtp(): return config("EMAIL_HOST") is not None and len(config("EMAIL_HOST")) > 0 -def get_edition(): - return "ee" if "ee" in config("ENTERPRISE_BUILD", default="").lower() else "foss" - - def old_search_payload_to_flat(values): # in case the old search body was passed if values.get("events") is not None: diff --git a/api/routers/core.py b/api/routers/core.py index 3008e94b7..5265287e6 100644 --- a/api/routers/core.py +++ b/api/routers/core.py @@ -1076,7 +1076,7 @@ def generate_new_user_token(context: schemas.CurrentContext = Depends(OR_context @app.put('/account', tags=["account"]) def edit_account(data: schemas.EditUserSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): - return users.edit(tenant_id=context.tenant_id, user_id_to_update=context.user_id, changes=data.dict(), + return users.edit(tenant_id=context.tenant_id, user_id_to_update=context.user_id, changes=data, editor_id=context.user_id) diff --git a/api/routers/core_dynamic.py b/api/routers/core_dynamic.py index 7791c5677..918d81541 100644 --- a/api/routers/core_dynamic.py +++ b/api/routers/core_dynamic.py @@ -24,7 +24,7 @@ def get_all_signup(): return {"data": {"tenants": tenants.tenants_exists(), "sso": None, "ssoProvider": None, - "edition": helper.get_edition()}} + "edition": license.EDITION}} @public_app.post('/login', tags=["authentication"]) @@ -181,7 +181,7 @@ def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = @app.post('/client/members/{memberId}', tags=["client"]) def edit_member(memberId: int, data: schemas.EditMemberSchema, context: schemas.CurrentContext = Depends(OR_context)): - return users.edit(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data.dict(), + return users.edit(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data, user_id_to_update=memberId) diff --git a/api/schemas.py b/api/schemas.py index fc61999ad..cb83789cd 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -12,7 +12,7 @@ def attribute_to_camel_case(snake_str): def transform_email(email: str) -> str: - return email.lower() if isinstance(email, str) else email + return email.lower().strip() if isinstance(email, str) else email class _Grecaptcha(BaseModel): @@ -37,7 +37,7 @@ class UserSignupSchema(UserLoginSchema): class EditUserSchema(BaseModel): name: Optional[str] = Field(None) email: Optional[EmailStr] = Field(None) - admin: Optional[bool] = Field(False) + admin: Optional[bool] = Field(None) _transform_email = validator('email', pre=True, allow_reuse=True)(transform_email) @@ -127,13 +127,11 @@ class CreateMemberSchema(BaseModel): _transform_email = validator('email', pre=True, allow_reuse=True)(transform_email) -class EditMemberSchema(BaseModel): +class EditMemberSchema(EditUserSchema): name: str = Field(...) email: EmailStr = Field(...) admin: bool = Field(False) - _transform_email = validator('email', pre=True, allow_reuse=True)(transform_email) - class EditPasswordByInvitationSchema(BaseModel): invitation: str = Field(...) @@ -796,6 +794,7 @@ class MetricTableViewType(str, Enum): class MetricType(str, Enum): timeseries = "timeseries" table = "table" + predefined = "predefined" class TableMetricOfType(str, Enum): diff --git a/ee/api/chalicelib/core/license.py b/ee/api/chalicelib/core/license.py index c1c9823d7..c067d4758 100644 --- a/ee/api/chalicelib/core/license.py +++ b/ee/api/chalicelib/core/license.py @@ -1,17 +1,12 @@ -from decouple import config - from chalicelib.core import unlock -from chalicelib.utils import pg_client + +EDITION = 'ee' 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 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(), - "edition": r.get("edition", "").lower(), + "edition": EDITION, + "expirationDate": unlock.get_expiration_date() } diff --git a/ee/api/chalicelib/core/signup.py b/ee/api/chalicelib/core/signup.py index 0415efc79..605520df4 100644 --- a/ee/api/chalicelib/core/signup.py +++ b/ee/api/chalicelib/core/signup.py @@ -64,8 +64,8 @@ def create_step1(data: schemas.UserSignupSchema): "data": json.dumps({"lastAnnouncementView": TimeUTC.now()})} query = """\ WITH t AS ( - INSERT INTO public.tenants (name, version_number, edition) - VALUES (%(companyName)s, (SELECT openreplay_version()), 'ee') + INSERT INTO public.tenants (name, version_number) + VALUES (%(companyName)s, (SELECT openreplay_version())) RETURNING tenant_id, api_key ), r AS ( diff --git a/ee/api/chalicelib/core/telemetry.py b/ee/api/chalicelib/core/telemetry.py index 9c82290fb..51fd55787 100644 --- a/ee/api/chalicelib/core/telemetry.py +++ b/ee/api/chalicelib/core/telemetry.py @@ -1,10 +1,11 @@ from chalicelib.utils import pg_client +from chalicelib.core import license import requests -def process_data(data, edition='fos'): +def process_data(data): return { - 'edition': edition, + 'edition': license.EDITION, 'tracking': data["opt_out"], 'version': data["version_number"], 'user_id': data["user_id"], @@ -56,7 +57,7 @@ def compute(): ) data = cur.fetchall() requests.post('https://api.openreplay.com/os/telemetry', - json={"stats": [process_data(d, edition='ee') for d in data]}) + json={"stats": [process_data(d) for d in data]}) def new_client(tenant_id): @@ -67,4 +68,4 @@ def new_client(tenant_id): FROM public.tenants WHERE tenant_id=%(tenant_id)s;""", {"tenant_id": tenant_id})) data = cur.fetchone() - requests.post('https://api.openreplay.com/os/signup', json=process_data(data, edition='ee')) \ No newline at end of file + requests.post('https://api.openreplay.com/os/signup', json=process_data(data)) diff --git a/ee/api/chalicelib/core/tenants.py b/ee/api/chalicelib/core/tenants.py index 45491f654..cecb8a9cf 100644 --- a/ee/api/chalicelib/core/tenants.py +++ b/ee/api/chalicelib/core/tenants.py @@ -1,4 +1,4 @@ -from chalicelib.core import users +from chalicelib.core import users, license from chalicelib.utils import helper from chalicelib.utils import pg_client @@ -12,7 +12,7 @@ def get_by_tenant_key(tenant_key): t.name, t.api_key, t.created_at, - t.edition, + '{license.EDITION}' AS edition, t.version_number, t.opt_out FROM public.tenants AS t @@ -32,7 +32,7 @@ def get_by_tenant_id(tenant_id): t.name, t.api_key, t.created_at, - t.edition, + '{license.EDITION}' AS edition, t.version_number, t.opt_out, t.user_id AS tenant_key @@ -90,7 +90,7 @@ def update(tenant_id, user_id, data): admin = users.get(user_id=user_id, tenant_id=tenant_id) if not admin["admin"] and not admin["superAdmin"]: - return {"error": "unauthorized"} + return {"errors": ["unauthorized, needs admin or owner"]} if "name" not in data and "optOut" not in data: return {"errors": ["please provide 'name' of 'optOut' attribute for update"]} changes = {} diff --git a/ee/api/chalicelib/core/users.py b/ee/api/chalicelib/core/users.py index 1f97fbd09..91c2384c4 100644 --- a/ee/api/chalicelib/core/users.py +++ b/ee/api/chalicelib/core/users.py @@ -4,6 +4,8 @@ import secrets from decouple import config from fastapi import BackgroundTasks +import schemas +import schemas_ee from chalicelib.core import authorizers, metadata, projects, roles from chalicelib.core import tenants, assist from chalicelib.utils import dev, SAML2_helper @@ -303,37 +305,44 @@ def generate_new_api_key(user_id): return helper.dict_to_camel_case(r) -def edit(user_id_to_update, tenant_id, changes, editor_id): - ALLOW_EDIT = ["name", "email", "admin", "roleId"] +def edit(user_id_to_update, tenant_id, changes: schemas_ee.EditUserSchema, editor_id): 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"]: + if editor_id != user_id_to_update or changes.admin is not None and changes.admin != user["admin"]: admin = get(tenant_id=tenant_id, user_id=editor_id) if not admin["superAdmin"] and not admin["admin"]: return {"errors": ["unauthorized"]} + _changes = {} if editor_id == user_id_to_update: - if user["superAdmin"]: - changes.pop("admin") - elif user["admin"] != changes["admin"]: - return {"errors": ["cannot change your own role"]} + if changes.admin is not None: + if user["superAdmin"]: + changes.admin = None + elif changes.admin != user["admin"]: + return {"errors": ["cannot change your own role"]} + if changes.roleId is not None: + if user["superAdmin"]: + changes.roleId = None + elif changes.roleId != user["roleId"]: + return {"errors": ["cannot change your own role"]} - keys = list(changes.keys()) - for k in keys: - if k not in ALLOW_EDIT or changes[k] is None: - changes.pop(k) - keys = list(changes.keys()) + if changes.email is not None and changes.email != user["email"]: + if email_exists(changes.email): + return {"errors": ["email already exists."]} + if get_deleted_user_by_email(changes.email) is not None: + return {"errors": ["email previously deleted."]} + _changes["email"] = changes.email - if len(keys) > 0: - if "email" in keys and changes["email"] != user["email"]: - if email_exists(changes["email"]): - return {"errors": ["email already exists."]} - if get_deleted_user_by_email(changes["email"]) is not None: - return {"errors": ["email previously deleted."]} - if "admin" in keys: - changes["role"] = "admin" if changes.pop("admin") else "member" - if len(changes.keys()) > 0: - updated_user = update(tenant_id=tenant_id, user_id=user_id_to_update, changes=changes) + if changes.name is not None and len(changes.name) > 0: + _changes["name"] = changes.name - return {"data": updated_user} + if changes.admin is not None: + _changes["role"] = "admin" if changes.admin else "member" + + if changes.roleId is not None: + _changes["roleId"] = changes.roleId + + if len(_changes.keys()) > 0: + updated_user = update(tenant_id=tenant_id, user_id=user_id_to_update, changes=_changes) + return {"data": updated_user} return {"data": user} diff --git a/ee/api/routers/core_dynamic.py b/ee/api/routers/core_dynamic.py index 6d7cf8e73..667d42c79 100644 --- a/ee/api/routers/core_dynamic.py +++ b/ee/api/routers/core_dynamic.py @@ -187,7 +187,7 @@ def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = @app.post('/client/members/{memberId}', tags=["client"]) def edit_member(memberId: int, data: schemas_ee.EditMemberSchema, context: schemas.CurrentContext = Depends(OR_context)): - return users.edit(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data.dict(), + return users.edit(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data, user_id_to_update=memberId) diff --git a/ee/api/schemas_ee.py b/ee/api/schemas_ee.py index 794dfdd64..0375521ad 100644 --- a/ee/api/schemas_ee.py +++ b/ee/api/schemas_ee.py @@ -1,6 +1,6 @@ from typing import Optional, List, Literal -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, EmailStr import schemas from chalicelib.utils.TimeUTC import TimeUTC @@ -21,7 +21,14 @@ class CreateMemberSchema(schemas.CreateMemberSchema): roleId: Optional[int] = Field(None) -class EditMemberSchema(schemas.EditMemberSchema): +class EditUserSchema(schemas.EditUserSchema): + roleId: Optional[int] = Field(None) + + +class EditMemberSchema(EditUserSchema): + name: str = Field(...) + email: EmailStr = Field(...) + admin: bool = Field(False) roleId: int = Field(...) diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index 1ab026565..01153848f 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -1,25 +1,42 @@ BEGIN; CREATE OR REPLACE -FUNCTION openreplay_version() + 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 ''; + EXISTS description text NOT NULL DEFAULT ''; CREATE -INDEX IF NOT -EXISTS traces_created_at_idx ON traces (created_at); + INDEX IF NOT + EXISTS traces_created_at_idx ON traces (created_at); CREATE -INDEX IF NOT -EXISTS traces_action_idx ON traces (action); + 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); + INDEX IF NOT + EXISTS users_name_gin_idx ON users USING GIN (name gin_trgm_ops); + + + +ALTER TABLE users + DROP COLUMN IF EXISTS appearance; + +ALTER TABLE basic_authentication + DROP COLUMN IF EXISTS generated_password; + +ALTER TABLE tenants + DROP COLUMN IF EXISTS edition; + +ALTER TABLE dashboards + ALTER COLUMN user_id DROP NOT NULL; + +COMMIT; INSERT INTO metrics (name, category, default_config, is_predefined, is_template, is_public, predefined_key, metric_type, view_type) @@ -122,21 +139,13 @@ 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, is_template=excluded.is_template, is_public=excluded.is_public, 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 + view_type=excluded.view_type; \ 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 efb4bb1d1..5bf02f4e1 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -147,7 +147,6 @@ $$ api_key text UNIQUE default generate_api_key(20) 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, - edition varchar(3) NOT NULL, version_number text NOT NULL, license text NULL, opt_out bool NOT NULL DEFAULT FALSE, @@ -777,7 +776,7 @@ $$ ( dashboard_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, - user_id integer NOT NULL REFERENCES users (user_id) ON DELETE SET NULL, + user_id integer REFERENCES users (user_id) ON DELETE SET NULL, name text NOT NULL, description text NOT NULL DEFAULT '', is_public boolean NOT NULL DEFAULT TRUE, diff --git a/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index 233f4fc5e..3f5552640 100644 --- a/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql +++ b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -9,6 +9,22 @@ $$ LANGUAGE sql IMMUTABLE; ALTER TABLE IF EXISTS dashboards ADD COLUMN IF NOT EXISTS description text NOT NULL DEFAULT ''; + + +ALTER TABLE users + DROP COLUMN IF EXISTS appearance; + +ALTER TABLE basic_authentication + DROP COLUMN IF EXISTS generated_password; + +ALTER TABLE tenants + DROP COLUMN IF EXISTS edition; + +ALTER TABLE dashboards + ALTER COLUMN user_id DROP NOT NULL; + +COMMIT; + INSERT INTO metrics (name, category, default_config, is_predefined, is_template, is_public, predefined_key, metric_type, view_type) VALUES ('Captured sessions', 'web vitals', '{ @@ -119,12 +135,4 @@ ON CONFLICT (predefined_key) DO UPDATE is_template=excluded.is_template, is_public=excluded.is_public, 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 + view_type=excluded.view_type; \ 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 519997f72..6cbd17dc8 100644 --- a/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -121,7 +121,6 @@ $$ name text NOT NULL, api_key text NOT NULL DEFAULT generate_api_key(20), created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'), - edition varchar(3) NOT NULL, version_number text NOT NULL, license text NULL, opt_out bool NOT NULL DEFAULT FALSE, @@ -928,7 +927,7 @@ $$ ( dashboard_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, - user_id integer NOT NULL REFERENCES users (user_id) ON DELETE SET NULL, + user_id integer REFERENCES users (user_id) ON DELETE SET NULL, name text NOT NULL, description text NOT NULL DEFAULT '', is_public boolean NOT NULL DEFAULT TRUE,