Skip to content

Commit c876301

Browse files
committed
migrate project to support postgres
0 parents  commit c876301

107 files changed

Lines changed: 7383 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Binaries
2+
/server
3+
/server.exe
4+
5+
# Vendor directory (if not using Go modules)
6+
vendor/
7+
8+
# OS-specific files
9+
*.exe
10+
*.dll
11+
*.so
12+
*.dylib
13+
14+
# Test output
15+
*.out
16+
17+
# Logs
18+
*.log
19+
20+
# Coverage files
21+
*.cover
22+
*.coverage
23+
*.cov
24+
25+
# Build directories
26+
bin/
27+
obj/
28+
build/
29+
dist/
30+
31+
# IDE/editor directories and files
32+
.vscode/
33+
.idea/
34+
*.swp
35+
*~
36+
37+
# Git
38+
.git/
39+
.gitignore
40+
41+
# Docker
42+
.dockerignore
43+
Dockerfile
44+
45+
# Dependency management files
46+
go.sum
47+
48+
# Any other files you want to exclude
49+
.DS_Store
50+
.github/
51+
.tools/
52+
logs/
53+
*.md

.editorconfig

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# EditorConfig is awesome: https://EditorConfig.org
2+
3+
# top-most EditorConfig file
4+
root = true
5+
6+
# Unix-style newlines with a newline ending every file
7+
[*]
8+
end_of_line = lf
9+
insert_final_newline = true
10+
11+
# Go files
12+
[*.go]
13+
indent_style = tab
14+
indent_size = 2
15+
16+
# JavaScript files
17+
[*.js]
18+
indent_style = space
19+
indent_size = 2
20+
21+
# Markdown files
22+
[*.md]
23+
max_line_length = 80
24+
trim_trailing_whitespace = false
25+
26+
# JSON files
27+
[*.json]
28+
indent_style = space
29+
indent_size = 2
30+
31+
# YAML files
32+
[*.yml, *.yaml]
33+
indent_style = space
34+
indent_size = 2

.env.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# debug, release, test
2+
GO_MODE=debug
3+
4+
SERVER_HOST=0.0.0.0
5+
SERVER_PORT=8080
6+
7+
DB_HOST=postgres
8+
DB_PORT=5432
9+
DB_NAME=goserver_dev_db
10+
DB_USER=goserver_dev_db_user
11+
DB_USER_PWD=changeit
12+
DB_MIN_POOL_SIZE=2
13+
DB_MAX_POOL_SIZE=5
14+
DB_QUERY_TIMEOUT_SEC=60
15+
16+
REDIS_HOST=redis
17+
REDIS_PORT=6379
18+
REDIS_PASSWORD=changeit
19+
20+
# 2 DAYS: 172800 Sec
21+
ACCESS_TOKEN_VALIDITY_SEC=172800
22+
# 7 DAYS: 604800 Sec
23+
REFRESH_TOKEN_VALIDITY_SEC=604800
24+
TOKEN_ISSUER=api.goserve.afteracademy.com
25+
TOKEN_AUDIENCE=goserve.afteracademy.com
26+
27+
RSA_PRIVATE_KEY_PATH="keys/private.pem"
28+
RSA_PUBLIC_KEY_PATH="keys/public.pem"

.extra/docs/goserve-banner.png

10.9 KB
Loading

.extra/docs/goserve-cover.png

18.4 KB
Loading

.extra/docs/request-flow.svg

Lines changed: 4 additions & 0 deletions
Loading

.extra/setup/pgseed.sql

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
-- Enable UUID
2+
CREATE EXTENSION IF NOT EXISTS pgcrypto;
3+
4+
-- Create Tables
5+
-- ----------------
6+
7+
-- Api Keys Table
8+
CREATE TABLE IF NOT EXISTS api_keys (
9+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
10+
key TEXT NOT NULL UNIQUE,
11+
permissions TEXT[],
12+
comments TEXT[],
13+
version INTEGER,
14+
status BOOLEAN DEFAULT TRUE,
15+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
16+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
17+
);
18+
19+
-- Api Keys Indexes
20+
CREATE INDEX IF NOT EXISTS api_keys_key_status_idx
21+
ON api_keys (key, status);
22+
23+
-- Roles Table
24+
CREATE TABLE IF NOT EXISTS roles (
25+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
26+
code TEXT NOT NULL UNIQUE,
27+
status BOOLEAN DEFAULT TRUE,
28+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
29+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
30+
);
31+
32+
-- Users Table
33+
CREATE TABLE IF NOT EXISTS users (
34+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
35+
name TEXT NOT NULL,
36+
email TEXT NOT NULL UNIQUE,
37+
password TEXT NOT NULL,
38+
profile_pic_url TEXT,
39+
verified BOOLEAN DEFAULT FALSE,
40+
status BOOLEAN DEFAULT TRUE,
41+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
42+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
43+
);
44+
45+
-- Join Table for Users <-> Roles
46+
CREATE TABLE IF NOT EXISTS user_roles (
47+
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
48+
role_id UUID REFERENCES roles(id) ON DELETE CASCADE,
49+
PRIMARY KEY (user_id, role_id)
50+
);
51+
52+
-- Keystore Table
53+
CREATE TABLE IF NOT EXISTS keystore (
54+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
55+
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
56+
p_key TEXT NOT NULL,
57+
s_key TEXT NOT NULL,
58+
status BOOLEAN DEFAULT TRUE,
59+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
60+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
61+
);
62+
63+
-- Keystore Table Indexes
64+
CREATE INDEX IF NOT EXISTS keystore_user_status_idx
65+
ON keystore (user_id, status);
66+
67+
CREATE INDEX IF NOT EXISTS keystore_user_pkey_status_idx
68+
ON keystore (user_id, p_key, status);
69+
70+
CREATE INDEX IF NOT EXISTS keystore_user_pkey_skey_status_idx
71+
ON keystore (user_id, p_key, s_key, status);
72+
73+
-- Messages Table
74+
CREATE TABLE messages (
75+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
76+
type TEXT NOT NULL,
77+
msg TEXT NOT NULL,
78+
status BOOLEAN DEFAULT TRUE,
79+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
80+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
81+
);
82+
83+
-- Blogs Table
84+
CREATE TABLE IF NOT EXISTS blogs (
85+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
86+
title TEXT NOT NULL,
87+
description TEXT NOT NULL,
88+
text TEXT,
89+
draft_text TEXT NOT NULL,
90+
tags TEXT[],
91+
author_id UUID NOT NULL REFERENCES users(id),
92+
img_url TEXT,
93+
slug TEXT NOT NULL UNIQUE,
94+
score DOUBLE PRECISION DEFAULT 0.01,
95+
submitted BOOLEAN DEFAULT FALSE,
96+
drafted BOOLEAN DEFAULT TRUE,
97+
published BOOLEAN DEFAULT FALSE,
98+
status BOOLEAN DEFAULT TRUE,
99+
published_at TIMESTAMP,
100+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
101+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
102+
);
103+
104+
-- Blogs Table Indexes
105+
CREATE INDEX IF NOT EXISTS blogs_publish_idx
106+
ON blogs (published_at DESC, score DESC)
107+
WHERE published = TRUE AND status = TRUE;
108+
109+
CREATE INDEX IF NOT EXISTS blogs_tags_gin_idx
110+
ON blogs
111+
USING GIN (tags);
112+
113+
CREATE INDEX IF NOT EXISTS blogs_search_idx
114+
ON blogs
115+
USING GIN (to_tsvector('english', title));
116+
117+
-- Insert Data
118+
-- --------------
119+
120+
-- Insert API Key
121+
INSERT INTO api_keys (key, permissions, comments, version, status, created_at, updated_at)
122+
VALUES (
123+
'1D3F2DD1A5DE725DD4DF1D82BBB37',
124+
ARRAY['GENERAL'],
125+
ARRAY['To be used by the xyz vendor'],
126+
1,
127+
true,
128+
NOW(),
129+
NOW()
130+
)
131+
ON CONFLICT (key) DO NOTHING;
132+
133+
-- Insert Roles
134+
INSERT INTO roles (code, status, created_at, updated_at)
135+
VALUES
136+
('LEARNER', true, NOW(), NOW()),
137+
('AUTHOR', true, NOW(), NOW()),
138+
('EDITOR', true, NOW(), NOW()),
139+
('ADMIN', true, NOW(), NOW())
140+
ON CONFLICT (code) DO NOTHING;
141+
142+
-- Insert Admin User
143+
INSERT INTO users (name, email, password, status, created_at, updated_at)
144+
VALUES (
145+
'Admin',
146+
'admin@afteracademy.com',
147+
'$2a$10$psWmSrmtyZYvtIt/FuJL1OLqsK3iR1fZz5.wUYFuSNkkt.EOX9mLa',
148+
true,
149+
NOW(),
150+
NOW()
151+
)
152+
ON CONFLICT (email) DO NOTHING;
153+
154+
-- Map Admin User to ALL Roles
155+
INSERT INTO user_roles (user_id, role_id)
156+
SELECT u.id, r.id
157+
FROM users u
158+
CROSS JOIN roles r
159+
WHERE u.email = 'admin@afteracademy.com'
160+
ON CONFLICT DO NOTHING;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Docker Compose CI
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout code
14+
uses: actions/checkout@v4
15+
- name: Create .env
16+
run: cp .env.example .env
17+
- name: Create .test.env
18+
run: cp .test.env.example .test.env
19+
- name: Create pems
20+
run: go run .tools/rsa/keygen.go
21+
- name: Build docker images
22+
run: docker compose build
23+
- name: Run docker images
24+
run: docker compose up -d
25+
- name: Run tests
26+
run: docker exec -t goserve_example_api_server_postgres go test -v ./...
27+
- name: Clean up
28+
if: success() || failure()
29+
run: docker compose down --rmi all -v --remove-orphans

.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
.DS_Store
5+
# Binaries for programs and plugins
6+
*.exe
7+
*.exe~
8+
*.dll
9+
*.so
10+
*.dylib
11+
12+
# Test binary, built with `go test -c`
13+
*.test
14+
!Dockerfile.test
15+
16+
# Output of the go coverage tool, specifically when used with LiteIDE
17+
*.out
18+
19+
# Dependency directories (remove the comment below to include it)
20+
# vendor/
21+
22+
# Go workspace file
23+
go.work
24+
go.work.sum
25+
26+
# Environment varibles
27+
*.env
28+
*.env.test
29+
30+
#keys
31+
keys/*
32+
!keys/*.md
33+
!keys/*.txt
34+
*.pem
35+
36+
__debug*
37+
38+
build

.test.env.example

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# debug, release, test
2+
GO_MODE=debug
3+
4+
SERVER_HOST=localhost
5+
SERVER_PORT=8081
6+
7+
DB_HOST=postgres-test
8+
DB_PORT=5432
9+
DB_NAME=goserver_test_db
10+
DB_USER=goserver_test_db_user
11+
DB_USER_PWD=changeit
12+
DB_MIN_POOL_SIZE=2
13+
DB_MAX_POOL_SIZE=5
14+
DB_QUERY_TIMEOUT_SEC=60
15+
16+
REDIS_HOST=redis-test
17+
REDIS_PORT=6379
18+
REDIS_PASSWORD=changeit
19+
20+
# 2 DAYS: 172800 Sec
21+
ACCESS_TOKEN_VALIDITY_SEC=172800
22+
# 7 DAYS: 604800 Sec
23+
REFRESH_TOKEN_VALIDITY_SEC=604800
24+
TOKEN_ISSUER=api.goserve.afteracademy.com
25+
TOKEN_AUDIENCE=goserve.afteracademy.com
26+
27+
# test run from the test directory one level below the src
28+
RSA_PRIVATE_KEY_PATH="../keys/private.pem"
29+
RSA_PUBLIC_KEY_PATH="../keys/public.pem"

0 commit comments

Comments
 (0)