mirror of
https://github.com/open-reception/appointment-booking-software.git
synced 2026-08-17 21:25:52 +02:00
Move significant config to base tenant config
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "tenant" ADD COLUMN "defaultLanguage" text DEFAULT 'en' NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "tenant" ADD COLUMN "links" json DEFAULT '{}'::json NOT NULL;
|
||||
@@ -0,0 +1,793 @@
|
||||
{
|
||||
"id": "c7e97210-1d91-4d46-942d-157da03e44e5",
|
||||
"prevId": "27656a23-f444-413b-8c60-57b59232a615",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.tenant": {
|
||||
"name": "tenant",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"short_name": {
|
||||
"name": "short_name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"long_name": {
|
||||
"name": "long_name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"descriptions": {
|
||||
"name": "descriptions",
|
||||
"type": "json",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"languages": {
|
||||
"name": "languages",
|
||||
"type": "json",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"defaultLanguage": {
|
||||
"name": "defaultLanguage",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'en'"
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "varchar(100000)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"database_url": {
|
||||
"name": "database_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"setup_state": {
|
||||
"name": "setup_state",
|
||||
"type": "setup_state",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'NEW'"
|
||||
},
|
||||
"links": {
|
||||
"name": "links",
|
||||
"type": "json",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::json"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"tenant_database_url_idx": {
|
||||
"name": "tenant_database_url_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "database_url",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"tenant_short_name_unique": {
|
||||
"name": "tenant_short_name_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["short_name"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.tenant_config": {
|
||||
"name": "tenant_config",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"tenant_id": {
|
||||
"name": "tenant_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "config_type",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"value": {
|
||||
"name": "value",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"tenant_config_tenant_name_idx": {
|
||||
"name": "tenant_config_tenant_name_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tenant_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
},
|
||||
{
|
||||
"expression": "name",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"tenant_config_tenant_id_tenant_id_fk": {
|
||||
"name": "tenant_config_tenant_id_tenant_id_fk",
|
||||
"tableFrom": "tenant_config",
|
||||
"tableTo": "tenant",
|
||||
"columnsFrom": ["tenant_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.user": {
|
||||
"name": "user",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "user_role",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'STAFF'"
|
||||
},
|
||||
"tenant_id": {
|
||||
"name": "tenant_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"last_login_at": {
|
||||
"name": "last_login_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"is_active": {
|
||||
"name": "is_active",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": true
|
||||
},
|
||||
"confirmation_state": {
|
||||
"name": "confirmation_state",
|
||||
"type": "confirmation_state",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "'INVITED'"
|
||||
},
|
||||
"token": {
|
||||
"name": "token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"token_valid_until": {
|
||||
"name": "token_valid_until",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"passphrase_hash": {
|
||||
"name": "passphrase_hash",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"recovery_passphrase": {
|
||||
"name": "recovery_passphrase",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'de'"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"user_email_idx": {
|
||||
"name": "user_email_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "email",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"user_tenant_id_tenant_id_fk": {
|
||||
"name": "user_tenant_id_tenant_id_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "tenant",
|
||||
"columnsFrom": ["tenant_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"user_email_unique": {
|
||||
"name": "user_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["email"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.user_invite": {
|
||||
"name": "user_invite",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"invite_code": {
|
||||
"name": "invite_code",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "user_role",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tenant_id": {
|
||||
"name": "tenant_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"invited_by": {
|
||||
"name": "invited_by",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'de'"
|
||||
},
|
||||
"used": {
|
||||
"name": "used",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": false
|
||||
},
|
||||
"used_at": {
|
||||
"name": "used_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_user_id": {
|
||||
"name": "created_user_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"expires_at": {
|
||||
"name": "expires_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"user_invite_code_idx": {
|
||||
"name": "user_invite_code_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "invite_code",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"user_invite_email_idx": {
|
||||
"name": "user_invite_email_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "email",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"user_invite_tenant_idx": {
|
||||
"name": "user_invite_tenant_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tenant_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"user_invite_tenant_id_tenant_id_fk": {
|
||||
"name": "user_invite_tenant_id_tenant_id_fk",
|
||||
"tableFrom": "user_invite",
|
||||
"tableTo": "tenant",
|
||||
"columnsFrom": ["tenant_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"user_invite_invited_by_user_id_fk": {
|
||||
"name": "user_invite_invited_by_user_id_fk",
|
||||
"tableFrom": "user_invite",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": ["invited_by"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"user_invite_created_user_id_user_id_fk": {
|
||||
"name": "user_invite_created_user_id_user_id_fk",
|
||||
"tableFrom": "user_invite",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": ["created_user_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"user_invite_invite_code_unique": {
|
||||
"name": "user_invite_invite_code_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["invite_code"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.user_passkey": {
|
||||
"name": "user_passkey",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"public_key": {
|
||||
"name": "public_key",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"counter": {
|
||||
"name": "counter",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 0
|
||||
},
|
||||
"device_name": {
|
||||
"name": "device_name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"last_used_at": {
|
||||
"name": "last_used_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"user_passkey_user_idx": {
|
||||
"name": "user_passkey_user_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "user_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"user_passkey_user_id_user_id_fk": {
|
||||
"name": "user_passkey_user_id_user_id_fk",
|
||||
"tableFrom": "user_passkey",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": ["user_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.user_session": {
|
||||
"name": "user_session",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"session_token": {
|
||||
"name": "session_token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"access_token": {
|
||||
"name": "access_token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"refresh_token": {
|
||||
"name": "refresh_token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"ip_address": {
|
||||
"name": "ip_address",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"user_agent": {
|
||||
"name": "user_agent",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"expires_at": {
|
||||
"name": "expires_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"last_used_at": {
|
||||
"name": "last_used_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"user_session_user_idx": {
|
||||
"name": "user_session_user_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "user_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"user_session_token_idx": {
|
||||
"name": "user_session_token_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "session_token",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"user_session_user_id_user_id_fk": {
|
||||
"name": "user_session_user_id_user_id_fk",
|
||||
"tableFrom": "user_session",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": ["user_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"user_session_session_token_unique": {
|
||||
"name": "user_session_session_token_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["session_token"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"public.config_type": {
|
||||
"name": "config_type",
|
||||
"schema": "public",
|
||||
"values": ["BOOLEAN", "NUMBER", "STRING"]
|
||||
},
|
||||
"public.confirmation_state": {
|
||||
"name": "confirmation_state",
|
||||
"schema": "public",
|
||||
"values": ["INVITED", "CONFIRMED", "ACCESS_GRANTED"]
|
||||
},
|
||||
"public.setup_state": {
|
||||
"name": "setup_state",
|
||||
"schema": "public",
|
||||
"values": ["NEW", "SETTINGS_CREATED", "AGENTS_SET_UP", "FIRST_CHANNEL_CREATED"]
|
||||
},
|
||||
"public.user_role": {
|
||||
"name": "user_role",
|
||||
"schema": "public",
|
||||
"values": ["GLOBAL_ADMIN", "TENANT_ADMIN", "STAFF"]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,13 @@
|
||||
"when": 1759421310945,
|
||||
"tag": "0005_confused_rockslide",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "7",
|
||||
"when": 1760360156572,
|
||||
"tag": "0006_legal_dracula",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -565,7 +565,7 @@
|
||||
"sections": {
|
||||
"general": "Allgemein",
|
||||
"address": "Adresse",
|
||||
"legal": "Rechtliches",
|
||||
"links": "Links",
|
||||
"advanced": "Erweitert"
|
||||
},
|
||||
"fields": {
|
||||
|
||||
@@ -574,7 +574,7 @@
|
||||
"sections": {
|
||||
"general": "General",
|
||||
"address": "Address",
|
||||
"legal": "Legal",
|
||||
"links": "Links",
|
||||
"advanced": "Advanced"
|
||||
},
|
||||
"fields": {
|
||||
|
||||
@@ -54,12 +54,19 @@ export const tenant = pgTable(
|
||||
descriptions: json("descriptions").$type<{ [key: string]: string }>().notNull(),
|
||||
/** Active languages for this tenant (array of language codes) */
|
||||
languages: json("languages").$type<string[]>().notNull(),
|
||||
/** Active languages for this tenant (array of language codes) */
|
||||
defaultLanguage: text("defaultLanguage").notNull().default("en"),
|
||||
/** Organization logo as binary data (PNG, JPEG, GIF, or WEBP) */
|
||||
logo: varchar("logo", { length: 100_000 }),
|
||||
/** Database connection string for this tenant's isolated database */
|
||||
databaseUrl: text("database_url").notNull(),
|
||||
/** STate of tenant setup */
|
||||
setupState: tenantSetupState("setup_state").notNull().default("NEW"),
|
||||
/** Links (object) */
|
||||
links: json("links")
|
||||
.$type<{ imprint?: string; privacyStatement?: string; website?: string }>()
|
||||
.notNull()
|
||||
.default({}),
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
updatedAt: timestamp("updated_at").defaultNow(),
|
||||
},
|
||||
|
||||
@@ -109,7 +109,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -140,7 +142,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -171,7 +175,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -202,7 +208,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -258,7 +266,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -322,7 +332,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -362,7 +374,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -396,7 +410,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -430,7 +446,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -483,7 +501,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
@@ -527,7 +547,9 @@ describe("Email System", () => {
|
||||
longName: "Test Organization",
|
||||
descriptions: { en: "Tenant Description" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "FIRST_CHANNEL_CREATED" as const,
|
||||
createdAt: new Date(),
|
||||
|
||||
@@ -31,8 +31,10 @@ describe("generateBaseUrl", () => {
|
||||
updatedAt: new Date(),
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
};
|
||||
|
||||
const result = generateBaseUrl(requestUrl, tenant);
|
||||
@@ -54,9 +56,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "Test Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -73,9 +77,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -92,9 +98,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -131,9 +139,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -150,9 +160,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -169,9 +181,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "New Tenant Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -188,9 +202,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "New Tenant Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -207,9 +223,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "Tenant Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -226,9 +244,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -245,9 +265,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -267,9 +289,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -287,9 +311,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
@@ -307,9 +333,11 @@ describe("generateBaseUrl", () => {
|
||||
longName: "ACME Corp",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "",
|
||||
setupState: "NEW",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
@@ -8,11 +8,17 @@ describe("sendTenantAdminInviteEmail", () => {
|
||||
longName: "Test Corporation GmbH",
|
||||
descriptions: { en: "A test corporation" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
databaseUrl: "postgresql://test",
|
||||
setupState: "NEW" as const,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
logo: null,
|
||||
links: {
|
||||
website: "https://testcorp.com",
|
||||
imprint: "https://testcorp.com/imprint",
|
||||
privacyStatement: "https://testcorp.com/privacy",
|
||||
},
|
||||
};
|
||||
|
||||
it("should accept correct parameters and not throw for German language", () => {
|
||||
|
||||
@@ -89,7 +89,9 @@ describe("TenantAdminService", () => {
|
||||
longName: "",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
description: "A test clinic",
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
};
|
||||
|
||||
const mockCreatedTenant = {
|
||||
|
||||
@@ -27,16 +27,12 @@ export type TenantCreationRequest = z.infer<typeof tenantCreationSchema>;
|
||||
|
||||
export interface TenantConfiguration extends Record<string, string | number | boolean> {
|
||||
brandColor: string;
|
||||
defaultLanguage: string;
|
||||
maxChannels: number;
|
||||
maxTeamMembers: number;
|
||||
autoDeleteDays: number;
|
||||
requireEmail: boolean;
|
||||
requirePhone: boolean;
|
||||
nextChannelColor: number;
|
||||
website: string;
|
||||
imprint: string;
|
||||
privacyStatement: string;
|
||||
}
|
||||
|
||||
export class TenantAdminService {
|
||||
@@ -49,16 +45,12 @@ export class TenantAdminService {
|
||||
static getConfigDefaults(): TenantConfiguration {
|
||||
return {
|
||||
brandColor: "#E11E15",
|
||||
defaultLanguage: "DE",
|
||||
maxChannels: -1,
|
||||
maxTeamMembers: -1,
|
||||
autoDeleteDays: 30,
|
||||
requireEmail: true,
|
||||
requirePhone: false,
|
||||
nextChannelColor: 0,
|
||||
website: "",
|
||||
imprint: "",
|
||||
privacyStatement: "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -104,6 +96,12 @@ export class TenantAdminService {
|
||||
databaseUrl: "",
|
||||
descriptions: { en: "" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
links: {
|
||||
website: "",
|
||||
imprint: "",
|
||||
privacyStatement: "",
|
||||
},
|
||||
};
|
||||
newTenant.databaseUrl = urlParts.join("/") + "/" + newTenant.shortName;
|
||||
|
||||
@@ -219,7 +217,11 @@ export class TenantAdminService {
|
||||
throw new NotFoundError(`Tenant with ID ${id} not found`);
|
||||
}
|
||||
|
||||
log.debug("Tenant service loaded successfully", { tenantId: id, data: tenant.#tenant });
|
||||
log.debug("Tenant service loaded successfully", {
|
||||
tenantId: id,
|
||||
// Do not log logo to not spam logs
|
||||
data: { ...tenant.#tenant, logo: tenant.#tenant.logo ? "removed-from-log-but-set" : null },
|
||||
});
|
||||
return tenant;
|
||||
} catch (error) {
|
||||
log.error("Failed to get tenant by ID", { tenantId: id, error: String(error) });
|
||||
|
||||
@@ -45,7 +45,9 @@ function createSystemTenant(): SelectTenant {
|
||||
longName: "Open Reception",
|
||||
descriptions: { en: "Secure appointment booking platform" },
|
||||
languages: ["en"],
|
||||
defaultLanguage: "en",
|
||||
logo: null,
|
||||
links: { website: "", imprint: "", privacyStatement: "" },
|
||||
databaseUrl: "",
|
||||
setupState: "FIRST_CHANNEL_CREATED",
|
||||
createdAt: new Date(),
|
||||
|
||||
+13
-12
@@ -27,7 +27,6 @@
|
||||
{ key: 180, label: m["settings.form.fields.autoDeleteDays.options.180"]() },
|
||||
{ key: 365, label: m["settings.form.fields.autoDeleteDays.options.365"]() },
|
||||
];
|
||||
const tenantLocales = get(tenants).currentTenant?.languages ?? []; // TODO: allow update within form
|
||||
const availableLocales = supportedLocales.map((it) => ({
|
||||
key: it,
|
||||
label: translatedLocales[it as keyof typeof translatedLocales],
|
||||
@@ -40,12 +39,14 @@
|
||||
shortName: entity.shortName,
|
||||
longName: entity.longName,
|
||||
logo: entity.logo,
|
||||
descriptions: tenantLocales.reduce(
|
||||
(acc, locale) => ({ ...acc, [locale]: "" }),
|
||||
descriptions: supportedLocales.reduce(
|
||||
(acc, locale) => {
|
||||
return { ...acc, [locale]: entity.descriptions[locale] || "" };
|
||||
},
|
||||
{} as { [key: string]: string },
|
||||
),
|
||||
address: entity.address,
|
||||
legal: entity.legal,
|
||||
links: entity.links,
|
||||
settings: {
|
||||
autoDeleteDays: entity.settings.autoDeleteDays,
|
||||
requirePhone: entity.settings.requirePhone || false,
|
||||
@@ -131,7 +132,7 @@
|
||||
: m["settings.form.fields.defaultLanguage.placeholder"]()}
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{#each $formData.defaultLanguage as language (language)}
|
||||
{#each $formData.languages as language (language)}
|
||||
<Select.Item value={language}>
|
||||
{availableLocales.find((x) => x.key === language)?.label}
|
||||
</Select.Item>
|
||||
@@ -238,12 +239,12 @@
|
||||
</Form.Field>
|
||||
</div>
|
||||
</FormGridItem>
|
||||
<FormGridItem title={m["settings.form.sections.legal"]()}>
|
||||
<Form.Field {form} name="legal.website" class="flex-3/5">
|
||||
<FormGridItem title={m["settings.form.sections.links"]()}>
|
||||
<Form.Field {form} name="links.website" class="flex-3/5">
|
||||
<Form.Control>
|
||||
{#snippet children({ props })}
|
||||
<Form.Label>{m["settings.form.fields.website.title"]()}</Form.Label>
|
||||
<Input {...props} bind:value={$formData.legal.website} type="text" />
|
||||
<Input {...props} bind:value={$formData.links.website} type="text" />
|
||||
{/snippet}
|
||||
</Form.Control>
|
||||
<Form.Description>
|
||||
@@ -251,11 +252,11 @@
|
||||
</Form.Description>
|
||||
<Form.FieldErrors />
|
||||
</Form.Field>
|
||||
<Form.Field {form} name="legal.imprint" class="flex-3/5">
|
||||
<Form.Field {form} name="links.imprint" class="flex-3/5">
|
||||
<Form.Control>
|
||||
{#snippet children({ props })}
|
||||
<Form.Label>{m["settings.form.fields.imprint.title"]()}</Form.Label>
|
||||
<Input {...props} bind:value={$formData.legal.imprint} type="text" />
|
||||
<Input {...props} bind:value={$formData.links.imprint} type="text" />
|
||||
{/snippet}
|
||||
</Form.Control>
|
||||
<Form.Description>
|
||||
@@ -263,11 +264,11 @@
|
||||
</Form.Description>
|
||||
<Form.FieldErrors />
|
||||
</Form.Field>
|
||||
<Form.Field {form} name="legal.privacyStatement" class="flex-3/5">
|
||||
<Form.Field {form} name="links.privacyStatement" class="flex-3/5">
|
||||
<Form.Control>
|
||||
{#snippet children({ props })}
|
||||
<Form.Label>{m["settings.form.fields.privacyStatement.title"]()}</Form.Label>
|
||||
<Input {...props} bind:value={$formData.legal.privacyStatement} type="text" />
|
||||
<Input {...props} bind:value={$formData.links.privacyStatement} type="text" />
|
||||
{/snippet}
|
||||
</Form.Control>
|
||||
<Form.Description>
|
||||
|
||||
@@ -17,7 +17,7 @@ export const formSchema = z
|
||||
zip: z.string().min(4, { message: m["form.errors.zip"]() }),
|
||||
city: z.string().min(1, { message: m["form.errors.city"]() }),
|
||||
}),
|
||||
legal: z.object({
|
||||
links: z.object({
|
||||
website: z.string().url({ message: m["form.errors.url"]() }).optional().default(""),
|
||||
imprint: z.string().url({ message: m["form.errors.url"]() }).optional().default(""),
|
||||
privacyStatement: z.string().url({ message: m["form.errors.url"]() }).optional().default(""),
|
||||
@@ -32,7 +32,7 @@ export const formSchema = z
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: m["settings.form.fields.defaultLanguage.errors.notInLanguages"](),
|
||||
path: ["settings", "defaultLanguage"],
|
||||
path: ["defaultLanguage"],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -34,15 +34,15 @@ export const load = async (event) => {
|
||||
return {
|
||||
id: body.tenant.id,
|
||||
languages: body.tenant.languages,
|
||||
defaultLanguage: "en", // TODO: has to be moved to base
|
||||
defaultLanguage: body.tenant.defaultLanguage,
|
||||
shortName: body.tenant.shortName,
|
||||
longName: body.tenant.longName,
|
||||
logo: body.tenant.logo || "",
|
||||
descriptions: body.tenant.descriptions,
|
||||
legal: {
|
||||
website: "https://example.com", // TODO: has to be moved to base
|
||||
imprint: "https://example.com/imprint", // TODO: has to be moved to base
|
||||
privacyStatement: "https://example.com/privacy", // TODO: has to be moved to base
|
||||
links: {
|
||||
website: body.tenant.links.website || "",
|
||||
imprint: body.tenant.links.imprint || "",
|
||||
privacyStatement: body.tenant.links.privacyStatement || "",
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -122,9 +122,7 @@ export const actions: Actions = {
|
||||
longName: form.data.longName,
|
||||
logo: form.data.logo,
|
||||
descriptions: removeEmptyTranslations(form.data.descriptions),
|
||||
website: form.data.legal.website,
|
||||
imprint: form.data.legal.imprint,
|
||||
privacyStatement: form.data.legal.privacyStatement,
|
||||
links: form.data.links,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -444,8 +444,6 @@ export const GET: RequestHandler = async ({ params, locals }) => {
|
||||
|
||||
try {
|
||||
const tenantId = params.id;
|
||||
console.log("🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈");
|
||||
console.log("tenantId", tenantId);
|
||||
|
||||
if (!tenantId) {
|
||||
throw new ValidationError(ERRORS.TENANTS.NO_TENANT_ID);
|
||||
@@ -460,7 +458,6 @@ export const GET: RequestHandler = async ({ params, locals }) => {
|
||||
|
||||
const tenantService = await TenantAdminService.getTenantById(tenantId);
|
||||
const tenantData = tenantService.tenantData;
|
||||
console.log("tenantData", tenantData);
|
||||
|
||||
log.debug("Retrieved tenant data", { tenantService });
|
||||
|
||||
|
||||
@@ -30,11 +30,6 @@ registerOpenAPIRoute("/tenants/{id}/config", "GET", {
|
||||
type: "object",
|
||||
properties: {
|
||||
brandColor: { type: "string", description: "Brand color", example: "#E11E15" },
|
||||
defaultLanguage: {
|
||||
type: "string",
|
||||
description: "Default language code",
|
||||
example: "DE",
|
||||
},
|
||||
maxChannels: {
|
||||
type: "number",
|
||||
description: "Maximum channels (-1 for unlimited)",
|
||||
@@ -108,7 +103,6 @@ registerOpenAPIRoute("/tenants/{id}/config", "PUT", {
|
||||
type: "object",
|
||||
properties: {
|
||||
brandColor: { type: "string", description: "Brand color" },
|
||||
defaultLanguage: { type: "string", description: "Default language code" },
|
||||
maxChannels: { type: "number", description: "Maximum channels (-1 for unlimited)" },
|
||||
maxTeamMembers: {
|
||||
type: "number",
|
||||
|
||||
@@ -22,11 +22,6 @@ registerOpenAPIRoute("/tenants/config/defaults", "GET", {
|
||||
description: "Default brand color",
|
||||
example: "#E11E15",
|
||||
},
|
||||
defaultLanguage: {
|
||||
type: "string",
|
||||
description: "Default language code",
|
||||
example: "DE",
|
||||
},
|
||||
maxChannels: {
|
||||
type: "number",
|
||||
description: "Maximum channels (-1 for unlimited)",
|
||||
@@ -55,7 +50,6 @@ registerOpenAPIRoute("/tenants/config/defaults", "GET", {
|
||||
},
|
||||
required: [
|
||||
"brandColor",
|
||||
"defaultLanguage",
|
||||
"maxChannels",
|
||||
"maxTeamMembers",
|
||||
"autoDeleteDays",
|
||||
|
||||
@@ -276,16 +276,12 @@ describe("/api/tenants", () => {
|
||||
|
||||
const mockDefaults = {
|
||||
brandColor: "#E11E15",
|
||||
defaultLanguage: "DE",
|
||||
maxChannels: -1,
|
||||
maxTeamMembers: -1,
|
||||
autoDeleteDays: 30,
|
||||
requireEmail: true,
|
||||
requirePhone: false,
|
||||
nextChannelColor: 0,
|
||||
website: "",
|
||||
imprint: "",
|
||||
privacyStatement: "",
|
||||
};
|
||||
|
||||
vi.mocked(TenantAdminService.getConfigDefaults).mockReturnValue(mockDefaults);
|
||||
|
||||
Reference in New Issue
Block a user