mirror of
https://git.meshkee.com/Meshkee/backend.git
synced 2026-08-11 22:30:59 +04:30
Initial commit: Meshkee CMS API
NestJS backend with Prisma, Docker Compose for Postgres/Redis, and deploy docs for the production VM.
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
-- Meshkee CMS — initial schema
|
||||
-- Tables: users, businesses, domains
|
||||
|
||||
-- Reusable trigger to keep updated_at in sync
|
||||
CREATE OR REPLACE FUNCTION set_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- users
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE users (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
cell_number VARCHAR(20) NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255),
|
||||
first_name VARCHAR(100),
|
||||
last_name VARCHAR(100),
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
cell_verified_at TIMESTAMPTZ,
|
||||
last_login_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT users_cell_number_unique UNIQUE (cell_number),
|
||||
CONSTRAINT users_cell_number_format CHECK (cell_number ~ '^\+[1-9]\d{6,14}$'),
|
||||
CONSTRAINT users_email_format_optional CHECK (
|
||||
email IS NULL OR email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_cell_number ON users (cell_number);
|
||||
CREATE INDEX idx_users_is_active ON users (is_active) WHERE is_active = TRUE;
|
||||
|
||||
CREATE TRIGGER users_set_updated_at
|
||||
BEFORE UPDATE ON users
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- businesses (created by super admin — no direct user owner column)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE businesses (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
slug VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
settings JSONB NOT NULL DEFAULT '{}',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT businesses_slug_unique UNIQUE (slug),
|
||||
CONSTRAINT businesses_slug_format CHECK (slug ~ '^[a-z0-9]+(?:-[a-z0-9]+)*$')
|
||||
);
|
||||
|
||||
CREATE INDEX idx_businesses_is_active ON businesses (is_active) WHERE is_active = TRUE;
|
||||
|
||||
CREATE TRIGGER businesses_set_updated_at
|
||||
BEFORE UPDATE ON businesses
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- domains (many per business)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE domains (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
business_id BIGINT NOT NULL,
|
||||
host VARCHAR(253) NOT NULL,
|
||||
is_primary BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
verified_at TIMESTAMPTZ,
|
||||
ssl_enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT domains_host_unique UNIQUE (host),
|
||||
CONSTRAINT domains_business_id_fkey
|
||||
FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE,
|
||||
CONSTRAINT domains_host_format CHECK (
|
||||
host ~ '^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$'
|
||||
OR host ~ '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$'
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_domains_business_id ON domains (business_id);
|
||||
CREATE INDEX idx_domains_host ON domains (host);
|
||||
CREATE INDEX idx_domains_business_primary ON domains (business_id) WHERE is_primary = TRUE;
|
||||
|
||||
CREATE UNIQUE INDEX idx_domains_one_primary_per_business
|
||||
ON domains (business_id)
|
||||
WHERE is_primary = TRUE;
|
||||
|
||||
CREATE TRIGGER domains_set_updated_at
|
||||
BEFORE UPDATE ON domains
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION set_updated_at();
|
||||
Reference in New Issue
Block a user