Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@ FROM golang:1.24.1-alpine3.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o main main.go
RUN apk add curl
RUN curl -L https://github.com/golang-migrate/migrate/releases/download/v4.18.1/migrate.linux-amd64.tar.gz | tar xvz

#Run stage
FROM alpine:3.21
WORKDIR /app
COPY --from=builder /app/main .
COPY --from=builder /app/migrate ./migrate
COPY app.env .
COPY start.sh .
COPY wait-for.sh .
COPY db/migration ./migration
COPY db/migration ./db/migration

EXPOSE 8080
CMD [ "/app/main" ]
Expand Down
17 changes: 16 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,19 @@ server:
go run main.go
mock:
mockgen -package mockdb -destination db/mock/store.go SimpleBank/db/sqlc Store
.PHONY: createdb dropdb postgres migratedown migrateup migratedown1 migrateup1 db_docs db_schema sqlc test server mock

proto:
rm -rf pb/*.go
rm -rf doc/swagger/*.swagger.json
rm -rf doc/statik
protoc --proto_path=proto \
--go_out=pb --go_opt=paths=source_relative \
--go-grpc_out=pb --go-grpc_opt=paths=source_relative \
--grpc-gateway_out=pb --grpc-gateway_opt=paths=source_relative \
--openapiv2_out=doc/swagger --openapiv2_opt=allow_merge=true,merge_file_name=simple_bank \
proto/*.proto
statik -src=./doc/swagger -dest=./doc

evans:
evans --host localhost --port 9090 -r repl
.PHONY: createdb dropdb postgres migratedown migrateup migratedown1 migrateup1 db_docs db_schema sqlc test server mock proto evans
5 changes: 4 additions & 1 deletion app.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
ENVIRONMENT=development
DB_DRIVER=postgres
DB_SOURCE=postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable
SERVER_ADDRESS=0.0.0.0:8080
MIGRATION_URL=file://db/migration
HTTP_SERVER_ADDRESS=0.0.0.0:8080
GRPC_SERVER_ADDRESS=0.0.0.0:9090
TOKEN_SYMMETRIC_KEY=12345678901234567890123456789012
ACCESS_TOKEN_DURATION=15m
REFRESH_TOKEN_DURATION=24h
2 changes: 1 addition & 1 deletion db/migration/000003_add_sessions.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ CREATE TABLE "sessions" (
"username" varchar NOT NULL ,
"refresh_token" varchar NOT NULL,
"user_agent" varchar NOT NULL,
"client_ip" varchar UNIQUE NOT NULL,
"client_ip" varchar NOT NULL,
"is_blocked" boolean NOT NULL DEFAULT false,
"expires_at" timestamptz NOT NULL ,
"created_at" timestamptz NOT NULL DEFAULT (now())
Expand Down
15 changes: 15 additions & 0 deletions db/mock/store.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion db/query/user.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,15 @@ INSERT INTO users (

-- name: GetUser :one
SELECT * FROM users
WHERE username = $1 LIMIT 1;
WHERE username = $1 LIMIT 1;

-- name: UpdateUser :one
UPDATE users
SET
hashed_password = COALESCE(sqlc.narg(hashed_password), hashed_password),
password_changed_at = COALESCE(sqlc.narg(password_changed_at), password_changed_at),
full_name = COALESCE(sqlc.narg(full_name), full_name),
email = COALESCE(sqlc.narg(email), email)
WHERE
username = sqlc.arg(username)
RETURNING *;
2 changes: 1 addition & 1 deletion db/sqlc/account.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion db/sqlc/db.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion db/sqlc/entry.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion db/sqlc/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion db/sqlc/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion db/sqlc/session.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions db/sqlc/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func (store *SQLStore) execTx(ctx context.Context, fn func(*Queries) error) erro
if rbErr := tx.Rollback(); rbErr != nil {
return fmt.Errorf("tx err: %v, rollback: %v", err, rbErr)
}
return err
}
return tx.Commit()
}
Expand Down
2 changes: 1 addition & 1 deletion db/sqlc/transfer.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 42 additions & 1 deletion db/sqlc/user.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 68 additions & 0 deletions db/sqlc/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"
"testing"
"time"
"database/sql"
)

func createRandomUser(t *testing.T) User {
Expand Down Expand Up @@ -50,3 +51,70 @@ func TestGetUser(t *testing.T) {
require.WithinDuration(t, user1.CreatedAt, user2.CreatedAt, time.Second)
require.WithinDuration(t, user1.PasswordChangedAt, user2.PasswordChangedAt, time.Second)
}

func TestUpdateUserOnlyFullName(t *testing.T){
oldUser := createRandomUser(t)

newFullName := util.RandomOwner()
testQueries.UpdateUser(context.Background(), UpdateUserParams{
FullName: sql.NullString{String: newFullName, Valid: true},
Username: oldUser.Username,
})
newUser, err := testQueries.GetUser(context.Background(), oldUser.Username)
require.NoError(t, err)
require.Equal(t, oldUser.HashedPassword, newUser.HashedPassword)
require.Equal(t, oldUser.Email, newUser.Email)
require.Equal(t, oldUser.FullName != newUser.FullName, true)
}

func TestUpdateUserOnlyEmail(t *testing.T){
oldUser := createRandomUser(t)

newEmail := util.RandomEmail()
testQueries.UpdateUser(context.Background(), UpdateUserParams{
Email: sql.NullString{String: newEmail, Valid: true},
Username: oldUser.Username,
})
newUser, err := testQueries.GetUser(context.Background(), oldUser.Username)
require.NoError(t, err)
require.Equal(t, oldUser.HashedPassword, newUser.HashedPassword)
require.Equal(t, newEmail, newUser.Email)
require.Equal(t, oldUser.FullName, newUser.FullName)
}

func TestUpdateUserOnlyHashedPassword(t *testing.T){
oldUser := createRandomUser(t)

newHashedPassword, err := util.HashPassword(util.RandomString(6))
require.NoError(t, err)
testQueries.UpdateUser(context.Background(), UpdateUserParams{
HashedPassword: sql.NullString{String: newHashedPassword, Valid: true},
Username: oldUser.Username,
})
newUser, err := testQueries.GetUser(context.Background(), oldUser.Username)
require.NoError(t, err)
require.Equal(t, newHashedPassword, newUser.HashedPassword)
require.Equal(t, oldUser.Email, newUser.Email)
require.Equal(t, oldUser.FullName, newUser.FullName)
}

func TestUpdateUserAllFields(t *testing.T){
oldUser := createRandomUser(t)

newEmail := util.RandomEmail()
newFullName := util.RandomOwner()
newHashedPassword, err := util.HashPassword(util.RandomString(6))
require.NoError(t, err)
testQueries.UpdateUser(context.Background(), UpdateUserParams{
Email: sql.NullString{String: newEmail, Valid: true},
FullName: sql.NullString{String: newFullName, Valid: true},
HashedPassword: sql.NullString{String: newHashedPassword, Valid: true},
Username: oldUser.Username,
})
newUser, err := testQueries.GetUser(context.Background(), oldUser.Username)
require.NoError(t, err)
require.Equal(t, newHashedPassword, newUser.HashedPassword)
require.NotEqual(t, oldUser.Email, newEmail)
require.Equal(t, newEmail, newUser.Email)
require.Equal(t, newFullName, newUser.FullName)
}
14 changes: 14 additions & 0 deletions doc/statik/statik.go

Large diffs are not rendered by default.

Binary file added doc/swagger/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/swagger/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions doc/swagger/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}

*,
*:before,
*:after {
box-sizing: inherit;
}

body {
margin: 0;
background: #fafafa;
}
19 changes: 19 additions & 0 deletions doc/swagger/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>

<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>
6 changes: 6 additions & 0 deletions doc/swagger/oauth2-redirect.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<html lang="en-US">
<body>
<script src="oauth2-redirect.js"></script>
</body>
</html>
1 change: 1 addition & 0 deletions doc/swagger/oauth2-redirect.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading