Skip to content

Commit

Permalink
add users table with constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
techschool committed Nov 28, 2020
1 parent cd6c45f commit e6c8e85
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 2 deletions.
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ dropdb:
migrateup:
migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable" -verbose up

migrateup1:
migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable" -verbose up 1

migratedown:
migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable" -verbose down

migratedown1:
migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable" -verbose down 1

sqlc:
sqlc generate

Expand All @@ -28,4 +34,4 @@ server:
mock:
mockgen -package mockdb -destination db/mock/store.go github.com/techschool/simplebank/db/sqlc Store

.PHONY: postgres createdb dropdb migrateup migratedown sqlc test server mock
.PHONY: postgres createdb dropdb migrateup migratedown migrateup1 migratedown1 sqlc test server mock
8 changes: 8 additions & 0 deletions api/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"

"github.com/gin-gonic/gin"
"github.com/lib/pq"
db "github.com/techschool/simplebank/db/sqlc"
)

Expand All @@ -28,6 +29,13 @@ func (server *Server) createAccount(ctx *gin.Context) {

account, err := server.store.CreateAccount(ctx, arg)
if err != nil {
if pqErr, ok := err.(*pq.Error); ok {
switch pqErr.Code.Name() {
case "foreign_key_violation", "unique_violation":
ctx.JSON(http.StatusForbidden, errorResponse(err))
return
}
}
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}
Expand Down
5 changes: 5 additions & 0 deletions db/migration/000002_add_users.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE IF EXISTS "accounts" DROP CONSTRAINT IF EXISTS "owner_currency_key";

ALTER TABLE IF EXISTS "accounts" DROP CONSTRAINT IF EXISTS "accounts_owner_fkey";

DROP TABLE IF EXISTS "users";
12 changes: 12 additions & 0 deletions db/migration/000002_add_users.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CREATE TABLE "users" (
"username" varchar PRIMARY KEY,
"hashed_password" varchar NOT NULL,
"full_name" varchar NOT NULL,
"email" varchar UNIQUE NOT NULL,
"password_changed_at" timestamptz NOT NULL DEFAULT('0001-01-01 00:00:00+00'),
"created_at" timestamptz NOT NULL DEFAULT (now())
);

ALTER TABLE "accounts" ADD FOREIGN KEY ("owner") REFERENCES "users" ("username");

ALTER TABLE "accounts" ADD CONSTRAINT "owner_currency_key" UNIQUE ("owner", "currency");
30 changes: 30 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: 13 additions & 0 deletions db/query/user.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- name: CreateUser :one
INSERT INTO users (
username,
hashed_password,
full_name,
email
) VALUES (
$1, $2, $3, $4
) RETURNING *;

-- name: GetUser :one
SELECT * FROM users
WHERE username = $1 LIMIT 1;
4 changes: 3 additions & 1 deletion db/sqlc/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import (
)

func createRandomAccount(t *testing.T) Account {
user := createRandomUser(t)

arg := CreateAccountParams{
Owner: util.RandomOwner(),
Owner: user.Username,
Balance: util.RandomMoney(),
Currency: util.RandomCurrency(),
}
Expand Down
9 changes: 9 additions & 0 deletions db/sqlc/models.go

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

2 changes: 2 additions & 0 deletions db/sqlc/querier.go

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

64 changes: 64 additions & 0 deletions db/sqlc/user.sql.go

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

50 changes: 50 additions & 0 deletions db/sqlc/user_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package db

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/techschool/simplebank/util"
)

func createRandomUser(t *testing.T) User {
arg := CreateUserParams{
Username: util.RandomOwner(),
HashedPassword: "secret",
FullName: util.RandomOwner(),
Email: util.RandomEmail(),
}

user, err := testQueries.CreateUser(context.Background(), arg)
require.NoError(t, err)
require.NotEmpty(t, user)

require.Equal(t, arg.Username, user.Username)
require.Equal(t, arg.HashedPassword, user.HashedPassword)
require.Equal(t, arg.FullName, user.FullName)
require.Equal(t, arg.Email, user.Email)
require.Zero(t, user.PasswordChangedAt)
require.NotZero(t, user.CreatedAt)

return user
}

func TestCreateUser(t *testing.T) {
createRandomUser(t)
}

func TestGetUser(t *testing.T) {
user1 := createRandomUser(t)
user2, err := testQueries.GetUser(context.Background(), user1.Username)
require.NoError(t, err)
require.NotEmpty(t, user2)

require.Equal(t, user1.Username, user2.Username)
require.Equal(t, user1.HashedPassword, user2.HashedPassword)
require.Equal(t, user1.FullName, user2.FullName)
require.Equal(t, user1.Email, user2.Email)
require.WithinDuration(t, user1.PasswordChangedAt, user2.PasswordChangedAt, time.Second)
require.WithinDuration(t, user1.CreatedAt, user2.CreatedAt, time.Second)
}
6 changes: 6 additions & 0 deletions util/random.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package util

import (
"fmt"
"math/rand"
"strings"
"time"
Expand Down Expand Up @@ -46,3 +47,8 @@ func RandomCurrency() string {
n := len(currencies)
return currencies[rand.Intn(n)]
}

// RandomEmail generates a random email
func RandomEmail() string {
return fmt.Sprintf("%[email protected]", RandomString(6))
}

0 comments on commit e6c8e85

Please sign in to comment.