diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..406ca2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +db_password.txt +makefile +internal/db +config/config.toml diff --git a/README.md b/README.md index e0aea8b..8561ace 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # TECH STACK: - - database: sqlite + - database: postgres - web framework: golang `net/http` - migration tool: [goose](https://pressly.github.io/goose/) - sql builder: [sqlc](https://docs.sqlc.dev/en/stable/tutorials/getting-started-sqlite.html) @@ -9,9 +9,10 @@ ## TODO: - [] add route directory to separate public and private route -- [] define user schema (because we are using `sqlite` i should completely ensure what i want to add to my users tables) +- [x] define user schema (because we are using `sqlite` i should completely ensure what i want to add to my users tables) - [] implement a functional and pretty log system via `log/slog` -- [] dockerize project +- [x] dockerize project - [] implement oauth as an option for our auth - [] implement the crud apis for markdown part - [] render and show markdown file +- [] add an optional `-config` flag that user put its config file path in there. if it is empty, we use the `./config/config.toml` path diff --git a/config/config.toml b/config/config.toml deleted file mode 100644 index 4913fb0..0000000 --- a/config/config.toml +++ /dev/null @@ -1,9 +0,0 @@ -[server] -port = 2525 -read_timeout = 5 -write_timeout = 5 - -[auth] -jwt_secret = "ZKBKziWs9KNps6c68LUYhpI8q07136LoM5wRK2nTwK4pwnTbQmUilFDjzuHVFam5iMmQFsHsNN/T18wAuw0UEg==" -jwt_issuer = "test" -jwt_expires_at = "5h" diff --git a/config/config.toml.example b/config/config.toml.example new file mode 100644 index 0000000..0534902 --- /dev/null +++ b/config/config.toml.example @@ -0,0 +1,9 @@ +[server] +port = 2525 +read_timeout = 5 +write_timeout = 5 + +[auth] +jwt_secret = "" +jwt_issuer = "" +jwt_expires_at = "" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f318987 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +services: + db: + image: postgres:18.4-alpine3.24 + volumes: + - db_data:/var/lib/postgresql + restart: always + shm_size: 128mb + environment: + POSTGRES_USER: marky_super_user + POSTGRES_DB: marky + POSTGRES_PASSWORD_FILE: /run/secrets/db_password + secrets: + - db_password + ports: + - 5050:5432 + +secrets: + db_password: + file: db_password.txt + +volumes: + db_data: diff --git a/go.mod b/go.mod index 88164c5..5f89418 100644 --- a/go.mod +++ b/go.mod @@ -6,4 +6,11 @@ require ( github.com/BurntSushi/toml v1.6.0 github.com/golang-jwt/jwt/v5 v5.3.1 github.com/google/uuid v1.6.0 + github.com/jackc/pgx/v5 v5.10.0 +) + +require ( + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + golang.org/x/text v0.29.0 // indirect ) diff --git a/go.sum b/go.sum index 6a74845..42e730d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,32 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.10.0 h1:VhSvgU2jSli8o3AqIEOTJr7rZwAEUVo4E4XhR94Zfr0= +github.com/jackc/pgx/v5 v5.10.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/auth/jwt.go b/internal/auth/jwt.go index 8af5d91..2e96e64 100644 --- a/internal/auth/jwt.go +++ b/internal/auth/jwt.go @@ -23,13 +23,13 @@ func NewAuth(env env.Config) *auth { } } -func (a *auth) GenerateJWT(userID uuid.UUID) (string, error) { +func (a *auth) GenerateJWT(userRID uuid.UUID) (string, error) { utcNow := time.Now().UTC() claims := &jwt.RegisteredClaims{ Issuer: a.authConfig.JWTIssuer, IssuedAt: jwt.NewNumericDate(utcNow), ExpiresAt: jwt.NewNumericDate(utcNow.Add(a.authConfig.JWTExpiresAt)), - Subject: userID.String(), + Subject: userRID.String(), } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) @@ -47,7 +47,7 @@ func (a *auth) ValidateJWT(tokenString string) (uuid.UUID, error) { return nil, errors.New("unexpected signing method for jwt token") } - return []byte(tokenString), nil + return []byte(a.authConfig.JWTSecret), nil }) if err != nil { return uuid.Nil, err @@ -61,12 +61,12 @@ func (a *auth) ValidateJWT(tokenString string) (uuid.UUID, error) { if err != nil { return uuid.Nil, err } - userID, err := uuid.Parse(claimsSubject) + userRID, err := uuid.Parse(claimsSubject) if err != nil { return uuid.Nil, err } - return userID, nil + return userRID, nil } // TODO: i think this function is to basic diff --git a/makefile b/makefile deleted file mode 100644 index d7bb227..0000000 --- a/makefile +++ /dev/null @@ -1,2 +0,0 @@ -run: - go run ./cmd/web . diff --git a/sql/queries/users.sql b/sql/queries/users.sql new file mode 100644 index 0000000..ae27907 --- /dev/null +++ b/sql/queries/users.sql @@ -0,0 +1,13 @@ +-- name: SelectUsers :many +SELECT * FROM users +WHERE deleted_at IS NULL; + +-- name: SelectUserByRID :one +SELECT * FROM users +WHERE r_id = $1 AND deleted_at IS NULL +LIMIT 1; + +-- name: SelectUserByEmail :one +SELECT * FROM users +WHERE email = $1 AND deleted_at IS NULL +LIMIT 1; diff --git a/sql/schema/001_users.sql b/sql/schema/001_users.sql new file mode 100644 index 0000000..4bd52e2 --- /dev/null +++ b/sql/schema/001_users.sql @@ -0,0 +1,12 @@ +-- +goose up +create table users( + id bigint primary key generated always as identity, + created_at timestamp not null default current_timestamp, + updated_at timestamp not null default current_timestamp, + deleted_at timestamp default null, + r_id uuid not null unique default gen_random_uuid(), + email text unique not null +); + +-- +goose down +DROP TABLE users; diff --git a/sqlc.yaml b/sqlc.yaml index 7650d9f..bb8a9c2 100644 --- a/sqlc.yaml +++ b/sqlc.yaml @@ -1,9 +1,10 @@ version: "2" sql: - - engine: sqlite + - engine: postgresql queries: "sql/queries" schema: "sql/schema" gen: go: package: "db" + sql_package: "pgx/v5" out: "internal/db"