feat: Create collection file for routes
This commit is contained in:
8
.idea/dictionaries/project.xml
generated
Normal file
8
.idea/dictionaries/project.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<component name="ProjectDictionaryState">
|
||||||
|
<dictionary name="project">
|
||||||
|
<words>
|
||||||
|
<w>ossp</w>
|
||||||
|
<w>secnex</w>
|
||||||
|
</words>
|
||||||
|
</dictionary>
|
||||||
|
</component>
|
8
.idea/sqldialects.xml
generated
Normal file
8
.idea/sqldialects.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="SqlDialectMappings">
|
||||||
|
<file url="file://$PROJECT_DIR$/sql/secnex_support.sql" dialect="PostgreSQL" />
|
||||||
|
<file url="file://$PROJECT_DIR$/sql/tenante_admin.sql" dialect="PostgreSQL" />
|
||||||
|
<file url="PROJECT" dialect="PostgreSQL" />
|
||||||
|
</component>
|
||||||
|
</project>
|
4
.idea/tenante-api.iml
generated
Normal file
4
.idea/tenante-api.iml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
</module>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
151
.idea/workspace.xml
generated
Normal file
151
.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="ALL" />
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="2d8b3225-34c3-4749-bb3b-3a6f310611b0" name="Changes" comment="" />
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="FileTemplateManagerImpl">
|
||||||
|
<option name="RECENT_TEMPLATES">
|
||||||
|
<list>
|
||||||
|
<option value="Go File" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="GOROOT" url="file:///opt/homebrew/opt/go/libexec" />
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="KubernetesApiPersistence">{}</component>
|
||||||
|
<component name="KubernetesApiProvider">{
|
||||||
|
"isMigrated": true
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectColorInfo">{
|
||||||
|
"associatedIndex": 5
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectId" id="310w7j0QRBrZfOep9zvchx4XLdf" />
|
||||||
|
<component name="ProjectLevelVcsManager">
|
||||||
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent">{
|
||||||
|
"keyToString": {
|
||||||
|
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
|
"DefaultGoTemplateProperty": "Go File",
|
||||||
|
"Go Build.go build github.com/tenante/api.executor": "Run",
|
||||||
|
"Go Build.go build main.go.executor": "Run",
|
||||||
|
"Go Build.go build tenante-api main.go.executor": "Run",
|
||||||
|
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||||
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
|
"RunOnceActivity.go.formatter.settings.were.checked": "true",
|
||||||
|
"RunOnceActivity.go.migrated.go.modules.settings": "true",
|
||||||
|
"RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
|
||||||
|
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
|
"git-widget-placeholder": "main",
|
||||||
|
"go.import.settings.migrated": "true",
|
||||||
|
"go.sdk.automatically.set": "true",
|
||||||
|
"last_opened_file_path": "/Users/bbenouarets/Projects/secnex/tenante-api",
|
||||||
|
"node.js.detected.package.eslint": "true",
|
||||||
|
"node.js.detected.package.tslint": "true",
|
||||||
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"ts.external.directory.path": "/Users/bbenouarets/Projects/secnex/tenante-api/node_modules/typescript/lib",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
|
},
|
||||||
|
"keyToStringList": {
|
||||||
|
"DatabaseDriversLRU": [
|
||||||
|
"postgresql"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}</component>
|
||||||
|
<component name="RecentsManager">
|
||||||
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$" />
|
||||||
|
</key>
|
||||||
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$/server" />
|
||||||
|
<recent name="$PROJECT_DIR$/sql" />
|
||||||
|
</key>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager">
|
||||||
|
<configuration default="true" type="GoApplicationRunConfiguration" factoryName="Go Application">
|
||||||
|
<module name="tenante-api" />
|
||||||
|
<working_directory value="$PROJECT_DIR$" />
|
||||||
|
<go_parameters value="-i" />
|
||||||
|
<kind value="FILE" />
|
||||||
|
<directory value="$PROJECT_DIR$" />
|
||||||
|
<filePath value="$PROJECT_DIR$" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<configuration name="go build github.com/tenante/api" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
|
||||||
|
<module name="tenante-api" />
|
||||||
|
<working_directory value="$PROJECT_DIR$" />
|
||||||
|
<kind value="PACKAGE" />
|
||||||
|
<package value="github.com/tenante/api" />
|
||||||
|
<directory value="$PROJECT_DIR$" />
|
||||||
|
<filePath value="$PROJECT_DIR$/main.go" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<configuration default="true" type="GoTestRunConfiguration" factoryName="Go Test">
|
||||||
|
<module name="tenante-api" />
|
||||||
|
<working_directory value="$PROJECT_DIR$" />
|
||||||
|
<go_parameters value="-i" />
|
||||||
|
<kind value="DIRECTORY" />
|
||||||
|
<directory value="$PROJECT_DIR$" />
|
||||||
|
<filePath value="$PROJECT_DIR$" />
|
||||||
|
<framework value="gotest" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<recent_temporary>
|
||||||
|
<list>
|
||||||
|
<item itemvalue="Go Build.go build github.com/tenante/api" />
|
||||||
|
</list>
|
||||||
|
</recent_temporary>
|
||||||
|
</component>
|
||||||
|
<component name="SharedIndexes">
|
||||||
|
<attachedChunks>
|
||||||
|
<set>
|
||||||
|
<option value="bundled-js-predefined-d6986cc7102b-e03c56caf84a-JavaScript-WS-252.23892.411" />
|
||||||
|
</set>
|
||||||
|
</attachedChunks>
|
||||||
|
</component>
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="2d8b3225-34c3-4749-bb3b-3a6f310611b0" name="Changes" comment="" />
|
||||||
|
<created>1754674133452</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1754674133452</updated>
|
||||||
|
<workItem from="1754831940990" duration="393000" />
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
|
<option name="version" value="3" />
|
||||||
|
</component>
|
||||||
|
<component name="Vcs.Log.Tabs.Properties">
|
||||||
|
<option name="TAB_STATES">
|
||||||
|
<map>
|
||||||
|
<entry key="MAIN">
|
||||||
|
<value>
|
||||||
|
<State />
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="VgoProject">
|
||||||
|
<settings-migrated>true</settings-migrated>
|
||||||
|
</component>
|
||||||
|
</project>
|
30
database/connection.go
Normal file
30
database/connection.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Connection struct {
|
||||||
|
Connection *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnection(host string, port int, user string, password string, dbName string, sslMode string) *Connection {
|
||||||
|
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", host, port, user, password, dbName, sslMode)
|
||||||
|
db, err := sql.Open("postgres", psqlInfo)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return &Connection{Connection: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Connection) Close() error {
|
||||||
|
return db.Connection.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Connection) Ping() bool {
|
||||||
|
fmt.Println("🔥 Pinging database...")
|
||||||
|
return db.Connection.Ping() == nil
|
||||||
|
}
|
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module github.com/tenante/api
|
||||||
|
|
||||||
|
go 1.24.5
|
||||||
|
|
||||||
|
require github.com/lib/pq v1.10.9
|
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
15
main.go
Normal file
15
main.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tenante/api/database"
|
||||||
|
"github.com/tenante/api/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
db := database.NewConnection("localhost", 5432, "postgres", "postgres", "tenante_admin_PRD", "disable")
|
||||||
|
api := server.NewApiServer(8081, db)
|
||||||
|
err := api.Start()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
39
server/api.go
Normal file
39
server/api.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tenante/api/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ApiServer struct {
|
||||||
|
Port int
|
||||||
|
DatabaseConnection *database.Connection
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApiServer(port int, database *database.Connection) *ApiServer {
|
||||||
|
return &ApiServer{Port: port, DatabaseConnection: database}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *ApiServer) Start() error {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
mux.HandleFunc("/_/health", api.HealthCheckRoute)
|
||||||
|
|
||||||
|
srv := &http.Server{
|
||||||
|
Addr: fmt.Sprintf(":%d", api.Port),
|
||||||
|
Handler: mux,
|
||||||
|
ReadTimeout: 15 * time.Second,
|
||||||
|
WriteTimeout: 15 * time.Second,
|
||||||
|
IdleTimeout: 60 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("🚀 Server starting on %s...\n", srv.Addr)
|
||||||
|
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
13
server/response.go
Normal file
13
server/response.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
type HealthCheckResponse struct {
|
||||||
|
Database bool `json:"database"`
|
||||||
|
API bool `json:"api"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InternalServerErrorResponse struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
24
server/route.go
Normal file
24
server/route.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *ApiServer) HealthCheckRoute(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
response := HealthCheckResponse{
|
||||||
|
Database: api.DatabaseConnection.Ping(),
|
||||||
|
API: true,
|
||||||
|
Status: "OK",
|
||||||
|
}
|
||||||
|
err := json.NewEncoder(w).Encode(response)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
_, err := w.Write([]byte("Internal Server Error"))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
sql/secnex_support.sql
Normal file
12
sql/secnex_support.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- CREATE DATABASE "secnex_PRD";
|
||||||
|
|
||||||
|
CREATE SCHEMA IF NOT EXISTS "support";
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS "public"."user" (
|
||||||
|
"id" SERIAL PRIMARY KEY,
|
||||||
|
"name" VARCHAR(255) NOT NULL,
|
||||||
|
"email" VARCHAR(255) NOT NULL,
|
||||||
|
"password" VARCHAR(255) NOT NULL,
|
||||||
|
"created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
165
sql/tenante_admin.sql
Normal file
165
sql/tenante_admin.sql
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
-- CREATE DATABASE "tenante_admin_PRD";
|
||||||
|
|
||||||
|
-- Drop all tables
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
tabName text;
|
||||||
|
BEGIN
|
||||||
|
FOR tabName IN
|
||||||
|
SELECT tablename
|
||||||
|
FROM pg_tables
|
||||||
|
WHERE schemaname = 'public'
|
||||||
|
LOOP
|
||||||
|
EXECUTE 'DROP TABLE IF EXISTS public."' || tabName || '" CASCADE';
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Install uuid extension
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
|
-- Create the ORGANIZATION table
|
||||||
|
CREATE TABLE IF NOT EXISTS "organization" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
slug TEXT NOT NULL UNIQUE,
|
||||||
|
"ssoConfigurationId" UUID,
|
||||||
|
"ssoDomain" UUID,
|
||||||
|
"ssoEnabled" BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deletedAt" TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the PROJECT table
|
||||||
|
CREATE TABLE IF NOT EXISTS "project" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
slug TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deletedAt" TIMESTAMPTZ,
|
||||||
|
"organizationId" UUID REFERENCES organization(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT unique_name_per_org UNIQUE ("organizationId", name),
|
||||||
|
CONSTRAINT unique_slug_per_org UNIQUE ("organizationId", slug)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the USER table
|
||||||
|
CREATE TABLE IF NOT EXISTS "user" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"firstName" TEXT NOT NULL,
|
||||||
|
"lastName" TEXT NOT NULL,
|
||||||
|
"displayName" TEXT NOT NULL,
|
||||||
|
"username" TEXT NOT NULL UNIQUE,
|
||||||
|
"email" TEXT NOT NULL UNIQUE,
|
||||||
|
"password" TEXT NOT NULL,
|
||||||
|
"verified" BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
"verifiedAt" TIMESTAMPTZ,
|
||||||
|
"enabled" BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deletedAt" TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the ACCOUNT table
|
||||||
|
CREATE TABLE IF NOT EXISTS "account" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"userId" UUID REFERENCES "user"(id) ON DELETE CASCADE,
|
||||||
|
"provider" TEXT NOT NULL,
|
||||||
|
"providerAccountId" TEXT NOT NULL,
|
||||||
|
"refreshToken" TEXT,
|
||||||
|
"accessToken" TEXT NOT NULL,
|
||||||
|
"accessTokenExpires" TIMESTAMPTZ NOT NULL,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deletedAt" TIMESTAMPTZ,
|
||||||
|
CONSTRAINT unique_provider_per_user UNIQUE ("userId", "provider"),
|
||||||
|
CONSTRAINT unique_provider_account_per_user UNIQUE ("userId", "provider", "providerAccountId")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the MFA table to store MFA data
|
||||||
|
CREATE TABLE IF NOT EXISTS "mfa" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"userId" UUID REFERENCES "user"(id) ON DELETE CASCADE,
|
||||||
|
"secret" TEXT NOT NULL UNIQUE,
|
||||||
|
"enabled" BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create ENUM for user roles
|
||||||
|
DROP TYPE IF EXISTS "user_role" CASCADE;
|
||||||
|
CREATE TYPE "user_role" AS ENUM ('owner', 'admin', 'member', 'guest');
|
||||||
|
|
||||||
|
-- Create the PROJECT_USER table to link users to projects and assign roles
|
||||||
|
CREATE TABLE IF NOT EXISTS "project_user" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"userId" UUID REFERENCES "user"(id) ON DELETE CASCADE,
|
||||||
|
"projectId" UUID REFERENCES "project"(id) ON DELETE CASCADE,
|
||||||
|
"role" "user_role" NOT NULL DEFAULT 'guest',
|
||||||
|
"createdBy" UUID REFERENCES "user"(id) ON DELETE SET NULL,
|
||||||
|
"updatedBy" UUID REFERENCES "user"(id) ON DELETE SET NULL,
|
||||||
|
"deletedBy" UUID REFERENCES "user"(id) ON DELETE SET NULL,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deletedAt" TIMESTAMPTZ,
|
||||||
|
CONSTRAINT unique_user_per_project UNIQUE ("userId", "projectId"),
|
||||||
|
CONSTRAINT unique_role_per_user_per_project UNIQUE ("userId", "projectId", "role")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the APP table to link apps to projects and assign roles
|
||||||
|
CREATE TABLE IF NOT EXISTS "app" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
slug TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
"projectId" UUID REFERENCES "project"(id) ON DELETE CASCADE,
|
||||||
|
"createdBy" UUID REFERENCES "user"(id) ON DELETE SET NULL,
|
||||||
|
"updatedBy" UUID REFERENCES "user"(id) ON DELETE SET NULL,
|
||||||
|
"deletedBy" UUID REFERENCES "user"(id) ON DELETE SET NULL,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deletedAt" TIMESTAMPTZ,
|
||||||
|
CONSTRAINT unique_name_per_project UNIQUE ("projectId", name),
|
||||||
|
CONSTRAINT unique_slug_per_project UNIQUE ("projectId", slug)
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP TYPE IF EXISTS "user_audit_action" CASCADE;
|
||||||
|
CREATE TYPE "user_audit_action" AS ENUM ('login', 'password_change', 'reset_password', '2fa_enable', '2fa_disable', '2fa_generate_backup', 'request_deletion', 'stop_deletion');
|
||||||
|
|
||||||
|
-- Create USER_AUDIT table (to log any user changes and activities e.g., login attempts, password changes, 2FA changes
|
||||||
|
CREATE TABLE IF NOT EXISTS "user_audit" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"action" "user_audit_action" NOT NULL DEFAULT 'login',
|
||||||
|
"ipAddress" TEXT NOT NULL,
|
||||||
|
"userAgent" TEXT NOT NULL,
|
||||||
|
"appId" UUID REFERENCES "app"(id) ON DELETE SET NULL,
|
||||||
|
"userId" UUID REFERENCES "user"(id) ON DELETE CASCADE,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deletedAt" TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the SESSION table to save session data
|
||||||
|
CREATE TABLE IF NOT EXISTS "session" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"userId" UUID REFERENCES "user"(id) ON DELETE CASCADE,
|
||||||
|
"ipAddress" TEXT NOT NULL,
|
||||||
|
"userAgent" TEXT NOT NULL,
|
||||||
|
"refreshToken" TEXT NOT NULL,
|
||||||
|
"appId" UUID REFERENCES "app"(id) ON DELETE SET NULL,
|
||||||
|
"expiresAt" TIMESTAMPTZ NOT NULL,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the EVENT table to save webhook data and more
|
||||||
|
CREATE TABLE IF NOT EXISTS "event" (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
payload JSONB NOT NULL DEFAULT '{}',
|
||||||
|
"appId" UUID REFERENCES "app"(id) ON DELETE SET NULL,
|
||||||
|
"userId" UUID REFERENCES "user"(id) ON DELETE SET NULL,
|
||||||
|
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
);
|
Reference in New Issue
Block a user