Add schema template and create audit log cli
This commit is contained in:
@@ -0,0 +1,140 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"ersteller-lib"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := godotenv.Load()
|
||||||
|
if err != nil {
|
||||||
|
ersteller_lib.LogError("Error loading .env file: %v", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
dbUrl := os.Getenv("DATABASE_URL")
|
||||||
|
connpool, err := ersteller_lib.CreatePostgresConnpool(dbUrl)
|
||||||
|
if err != nil {
|
||||||
|
ersteller_lib.LogError("Failed to create connection pool: %v", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// https://medium.com/israeli-tech-radar/postgresql-trigger-based-audit-log-fd9d9d5e412c
|
||||||
|
sql := `
|
||||||
|
CREATE TABLE IF NOT EXISTS audit_log (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
table_name TEXT,
|
||||||
|
record_id TEXT,
|
||||||
|
operation_type TEXT,
|
||||||
|
changed_at TIMESTAMP DEFAULT now(),
|
||||||
|
changed_by TEXT,
|
||||||
|
original_values jsonb,
|
||||||
|
new_values jsonb
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION audit_trigger() RETURNS TRIGGER AS $$
|
||||||
|
DECLARE
|
||||||
|
new_data jsonb;
|
||||||
|
old_data jsonb;
|
||||||
|
key text;
|
||||||
|
new_values jsonb;
|
||||||
|
old_values jsonb;
|
||||||
|
user_id text;
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
user_id := current_setting('audit.user_id', true);
|
||||||
|
|
||||||
|
IF user_id IS NULL THEN
|
||||||
|
user_id := current_user;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
new_values := '{}';
|
||||||
|
old_values := '{}';
|
||||||
|
|
||||||
|
IF TG_OP = 'INSERT' THEN
|
||||||
|
new_data := to_jsonb(NEW);
|
||||||
|
new_values := new_data;
|
||||||
|
|
||||||
|
ELSIF TG_OP = 'UPDATE' THEN
|
||||||
|
new_data := to_jsonb(NEW);
|
||||||
|
old_data := to_jsonb(OLD);
|
||||||
|
|
||||||
|
FOR key IN SELECT jsonb_object_keys(new_data) INTERSECT SELECT jsonb_object_keys(old_data)
|
||||||
|
LOOP
|
||||||
|
IF new_data ->> key != old_data ->> key THEN
|
||||||
|
new_values := new_values || jsonb_build_object(key, new_data ->> key);
|
||||||
|
old_values := old_values || jsonb_build_object(key, old_data ->> key);
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
ELSIF TG_OP = 'DELETE' THEN
|
||||||
|
old_data := to_jsonb(OLD);
|
||||||
|
old_values := old_data;
|
||||||
|
|
||||||
|
FOR key IN SELECT jsonb_object_keys(old_data)
|
||||||
|
LOOP
|
||||||
|
old_values := old_values || jsonb_build_object(key, old_data ->> key);
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
||||||
|
INSERT INTO audit_log (table_name, record_id, operation_type, changed_by, original_values, new_values)
|
||||||
|
VALUES (TG_TABLE_NAME, NEW.id, TG_OP, user_id, old_values, new_values);
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
ELSE
|
||||||
|
INSERT INTO audit_log (table_name, record_id, operation_type, changed_by, original_values, new_values)
|
||||||
|
VALUES (TG_TABLE_NAME, OLD.id, TG_OP, user_id, old_values, new_values);
|
||||||
|
|
||||||
|
RETURN OLD;
|
||||||
|
END IF;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE TRIGGER audit_log_trigger
|
||||||
|
BEFORE INSERT OR UPDATE OR DELETE
|
||||||
|
ON public."marketDataLead"
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION audit_trigger();
|
||||||
|
|
||||||
|
CREATE OR REPLACE TRIGGER audit_log_trigger
|
||||||
|
BEFORE INSERT OR UPDATE OR DELETE
|
||||||
|
ON public.group
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION audit_trigger();
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE TRIGGER audit_log_trigger
|
||||||
|
BEFORE INSERT OR UPDATE OR DELETE
|
||||||
|
ON public."groupMembership"
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION audit_trigger();
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE TRIGGER audit_log_trigger
|
||||||
|
BEFORE INSERT OR UPDATE OR DELETE
|
||||||
|
ON public."marketDataLeadNote"
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION audit_trigger();
|
||||||
|
|
||||||
|
CREATE OR REPLACE TRIGGER audit_log_trigger
|
||||||
|
BEFORE INSERT OR UPDATE OR DELETE
|
||||||
|
ON public.settings
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION audit_trigger();
|
||||||
|
|
||||||
|
CREATE OR REPLACE TRIGGER audit_log_trigger
|
||||||
|
BEFORE INSERT OR UPDATE OR DELETE
|
||||||
|
ON public.user
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION audit_trigger();
|
||||||
|
`
|
||||||
|
_, err = connpool.Exec(context.Background(), sql)
|
||||||
|
if err != nil {
|
||||||
|
ersteller_lib.LogError("Failed to create audit log table: %v", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
println("Created audit log table")
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ require (
|
|||||||
github.com/doug-martin/goqu/v9 v9.19.0
|
github.com/doug-martin/goqu/v9 v9.19.0
|
||||||
github.com/gorilla/sessions v1.4.0
|
github.com/gorilla/sessions v1.4.0
|
||||||
github.com/jackc/pgx/v5 v5.7.5
|
github.com/jackc/pgx/v5 v5.7.5
|
||||||
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/labstack/echo/v4 v4.13.4
|
github.com/labstack/echo/v4 v4.13.4
|
||||||
github.com/markbates/goth v1.81.0
|
github.com/markbates/goth v1.81.0
|
||||||
github.com/mattn/go-sqlite3 v1.14.29
|
github.com/mattn/go-sqlite3 v1.14.29
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
|
|||||||
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
|
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
|
||||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/labstack/echo/v4 v4.13.4 h1:oTZZW+T3s9gAu5L8vmzihV7/lkXGZuITzTQkTEhcXEA=
|
github.com/labstack/echo/v4 v4.13.4 h1:oTZZW+T3s9gAu5L8vmzihV7/lkXGZuITzTQkTEhcXEA=
|
||||||
github.com/labstack/echo/v4 v4.13.4/go.mod h1:g63b33BZ5vZzcIUF8AtRH40DrTlXnx4UMC8rBdndmjQ=
|
github.com/labstack/echo/v4 v4.13.4/go.mod h1:g63b33BZ5vZzcIUF8AtRH40DrTlXnx4UMC8rBdndmjQ=
|
||||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
generator db {
|
||||||
|
provider = "go run github.com/steebchen/prisma-client-go"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
model user {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
email String @unique @default("")
|
||||||
|
state Json @default("{}")
|
||||||
|
admin Boolean @default(false)
|
||||||
|
password String @default("")
|
||||||
|
created_at DateTime @default(now()) @db.Timestamptz(3)
|
||||||
|
updated_at DateTime @default(now()) @updatedAt @db.Timestamptz(3)
|
||||||
|
googleAuth googleAuth[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model googleAuth {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
credentials Json @default("{}")
|
||||||
|
user_id Int @default(0)
|
||||||
|
created_at DateTime @default(now()) @db.Timestamptz(3)
|
||||||
|
updated_at DateTime @default(now()) @updatedAt @db.Timestamptz(3)
|
||||||
|
user user @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
||||||
|
}
|
||||||
|
|
||||||
|
model audit_log {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
table_name String?
|
||||||
|
record_id String?
|
||||||
|
operation_type String?
|
||||||
|
changed_at DateTime? @default(now()) @db.Timestamp(6)
|
||||||
|
changed_by String?
|
||||||
|
original_values Json?
|
||||||
|
new_values Json?
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user