feat: initial commit
Axum/Postgres server with auth, migrations, and Docker setup.
This commit is contained in:
3
migrations/20260812114905_create_user_table.down.sql
Normal file
3
migrations/20260812114905_create_user_table.down.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
DROP TABLE IF EXISTS auth_tokens;
|
||||
DROP TYPE IF EXISTS auth_token_kind;
|
||||
DROP TABLE IF EXISTS users;
|
||||
28
migrations/20260812114905_create_user_table.up.sql
Normal file
28
migrations/20260812114905_create_user_table.up.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
display_name TEXT NOT NULL,
|
||||
avatar_url TEXT,
|
||||
bio TEXT,
|
||||
email_verified BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TYPE auth_token_kind AS ENUM ('password_reset', 'email_verification', 'refresh_token');
|
||||
|
||||
CREATE TABLE auth_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
token_hash TEXT NOT NULL,
|
||||
kind auth_token_kind NOT NULL,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
used_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX auth_tokens_user_id_idx ON auth_tokens(user_id);
|
||||
CREATE INDEX auth_tokens_token_hash_idx ON auth_tokens(token_hash);
|
||||
4
migrations/20260812120000_create_workspaces.down.sql
Normal file
4
migrations/20260812120000_create_workspaces.down.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
DROP TABLE IF EXISTS workspace_invitations;
|
||||
DROP TABLE IF EXISTS workspace_members;
|
||||
DROP TABLE IF EXISTS workspaces;
|
||||
DROP TYPE IF EXISTS workspace_role;
|
||||
34
migrations/20260812120000_create_workspaces.up.sql
Normal file
34
migrations/20260812120000_create_workspaces.up.sql
Normal file
@@ -0,0 +1,34 @@
|
||||
CREATE TYPE workspace_role AS ENUM ('owner', 'admin', 'member');
|
||||
|
||||
CREATE TABLE workspaces (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
owner_id UUID NOT NULL REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TABLE workspace_members (
|
||||
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
role workspace_role NOT NULL DEFAULT 'member',
|
||||
display_name TEXT,
|
||||
avatar_url TEXT,
|
||||
joined_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (workspace_id, user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE workspace_invitations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
||||
created_by UUID NOT NULL REFERENCES users(id),
|
||||
token TEXT NOT NULL UNIQUE,
|
||||
max_uses INT,
|
||||
use_count INT NOT NULL DEFAULT 0,
|
||||
expires_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX workspace_members_user_id_idx ON workspace_members(user_id);
|
||||
3
migrations/20260812130000_create_conversations.down.sql
Normal file
3
migrations/20260812130000_create_conversations.down.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
DROP TABLE IF EXISTS conversation_members;
|
||||
DROP TABLE IF EXISTS conversations;
|
||||
DROP TYPE IF EXISTS conversation_kind;
|
||||
23
migrations/20260812130000_create_conversations.up.sql
Normal file
23
migrations/20260812130000_create_conversations.up.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
CREATE TYPE conversation_kind AS ENUM ('dm', 'group', 'channel');
|
||||
|
||||
CREATE TABLE conversations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
workspace_id UUID REFERENCES workspaces(id) ON DELETE CASCADE,
|
||||
kind conversation_kind NOT NULL,
|
||||
name TEXT,
|
||||
is_public BOOLEAN NOT NULL DEFAULT true,
|
||||
created_by UUID NOT NULL REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TABLE conversation_members (
|
||||
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
joined_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (conversation_id, user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX conversations_workspace_id_idx ON conversations(workspace_id);
|
||||
CREATE INDEX conversation_members_user_id_idx ON conversation_members(user_id);
|
||||
3
migrations/20260812140000_create_messages.down.sql
Normal file
3
migrations/20260812140000_create_messages.down.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
DROP TABLE IF EXISTS reactions;
|
||||
DROP TABLE IF EXISTS attachments;
|
||||
DROP TABLE IF EXISTS messages;
|
||||
31
migrations/20260812140000_create_messages.up.sql
Normal file
31
migrations/20260812140000_create_messages.up.sql
Normal file
@@ -0,0 +1,31 @@
|
||||
CREATE TABLE messages (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
content TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TABLE attachments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
message_id UUID NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
||||
url TEXT NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL,
|
||||
size_bytes BIGINT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE reactions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
message_id UUID NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
emoji TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (message_id, user_id, emoji)
|
||||
);
|
||||
|
||||
CREATE INDEX messages_conversation_id_created_at_idx ON messages(conversation_id, created_at DESC);
|
||||
CREATE INDEX reactions_message_id_idx ON reactions(message_id);
|
||||
Reference in New Issue
Block a user