Skip to content

Commit

Permalink
⚡️ Added user.SelectByUsername. Renamed 'users' package to 'user'
Browse files Browse the repository at this point in the history
  • Loading branch information
lhbelfanti committed Jan 12, 2025
1 parent 4828186 commit 901f432
Show file tree
Hide file tree
Showing 22 changed files with 288 additions and 173 deletions.
6 changes: 3 additions & 3 deletions cmd/api/auth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import (
"encoding/json"
"net/http"

"ahbcc/cmd/api/users"
"ahbcc/cmd/api/user"
)

// SignUpHandlerV1 HTTP Handler of the endpoint /auth/signup
func SignUpHandlerV1(signUp SignUp) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

var user users.UserDTO
var user user.DTO
err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
log.Error(ctx, err.Error())
Expand Down Expand Up @@ -41,7 +41,7 @@ func SignUpHandlerV1(signUp SignUp) http.HandlerFunc {
}

// validateBody validates that mandatory fields are present
func validateBody(user users.UserDTO) error {
func validateBody(user user.DTO) error {
if user.Username == "" {
return MissingUsername
}
Expand Down
12 changes: 6 additions & 6 deletions cmd/api/auth/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import (
"github.com/stretchr/testify/assert"

"ahbcc/cmd/api/auth"
"ahbcc/cmd/api/users"
"ahbcc/cmd/api/user"
)

func TestSignUpHandlerV1_success(t *testing.T) {
mockSignUp := auth.MockSignUp(nil)
mockResponseWriter := httptest.NewRecorder()
mockUser := users.MockUserDTO()
mockUser := user.MockDTO()
mockBody, _ := json.Marshal(mockUser)
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/signup/v1", bytes.NewReader(mockBody))

Expand Down Expand Up @@ -53,10 +53,10 @@ func TestSignUpHandlerV1_failsWhenValidateBodyThrowsError(t *testing.T) {
mockResponseWriter := httptest.NewRecorder()

for _, test := range []struct {
mockUser users.UserDTO
mockUser user.DTO
}{
{mockUser: users.UserDTO{Username: "username"}},
{mockUser: users.UserDTO{Password: "password"}},
{mockUser: user.DTO{Username: "username"}},
{mockUser: user.DTO{Password: "password"}},
} {
mockBody, _ := json.Marshal(test.mockUser)
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/signup/v1", bytes.NewReader(mockBody))
Expand All @@ -75,7 +75,7 @@ func TestSignUpHandlerV1_failsWhenValidateBodyThrowsError(t *testing.T) {
func TestSignUpHandlerV1_failsWhenSignUpThrowsError(t *testing.T) {
mockSignUp := auth.MockSignUp(errors.New("failed to sign up"))
mockResponseWriter := httptest.NewRecorder()
mockUser := users.MockUserDTO()
mockUser := user.MockDTO()
mockBody, _ := json.Marshal(mockUser)
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/signup/v1", bytes.NewReader(mockBody))

Expand Down
6 changes: 3 additions & 3 deletions cmd/api/auth/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package auth

import (
"context"
"ahbcc/cmd/api/users"

"ahbcc/cmd/api/user"
)

// MockSignUp mocks SignUp function
func MockSignUp(err error) SignUp {
return func(ctx context.Context, user users.UserDTO) error {
return func(ctx context.Context, user user.DTO) error {
return err
}
}
32 changes: 16 additions & 16 deletions cmd/api/auth/signup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"github.com/stretchr/testify/assert"

"ahbcc/cmd/api/auth"
"ahbcc/cmd/api/users"
"ahbcc/cmd/api/user"
)

func TestSignUp_success(t *testing.T) {
mockUserExists := users.MockUserExists(false, nil)
mockInsertUser := users.MockInsert(nil)
mockUserDTO := users.MockUserDTO()
mockUserExists := user.MockExists(false, nil)
mockInsertUser := user.MockInsert(nil)
mockUserDTO := user.MockDTO()

signUp := auth.MakeSignUp(mockUserExists, mockInsertUser)

Expand All @@ -24,9 +24,9 @@ func TestSignUp_success(t *testing.T) {
}

func TestSignUp_failsWhenUserExistsThrowsError(t *testing.T) {
mockUserExists := users.MockUserExists(false, errors.New("failed to execute UserExists"))
mockInsertUser := users.MockInsert(nil)
mockUserDTO := users.MockUserDTO()
mockUserExists := user.MockExists(false, errors.New("failed to execute Exists"))
mockInsertUser := user.MockInsert(nil)
mockUserDTO := user.MockDTO()

signUp := auth.MakeSignUp(mockUserExists, mockInsertUser)

Expand All @@ -37,9 +37,9 @@ func TestSignUp_failsWhenUserExistsThrowsError(t *testing.T) {
}

func TestSignUp_failsWhenUserAlreadyExists(t *testing.T) {
mockUserExists := users.MockUserExists(true, nil)
mockInsertUser := users.MockInsert(nil)
mockUserDTO := users.MockUserDTO()
mockUserExists := user.MockExists(true, nil)
mockInsertUser := user.MockInsert(nil)
mockUserDTO := user.MockDTO()

signUp := auth.MakeSignUp(mockUserExists, mockInsertUser)

Expand All @@ -50,9 +50,9 @@ func TestSignUp_failsWhenUserAlreadyExists(t *testing.T) {
}

func TestSignUp_failsWhenGenerateFromPasswordThrowsError(t *testing.T) {
mockUserExists := users.MockUserExists(false, nil)
mockInsertUser := users.MockInsert(nil)
mockUserDTO := users.MockUserDTO()
mockUserExists := user.MockExists(false, nil)
mockInsertUser := user.MockInsert(nil)
mockUserDTO := user.MockDTO()
mockUserDTO.Password = "verylongpassword1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"

signUp := auth.MakeSignUp(mockUserExists, mockInsertUser)
Expand All @@ -64,9 +64,9 @@ func TestSignUp_failsWhenGenerateFromPasswordThrowsError(t *testing.T) {
}

func TestSignUp_failsWhenInsertThrowsError(t *testing.T) {
mockUserExists := users.MockUserExists(false, nil)
mockInsertUser := users.MockInsert(errors.New("failed to insert user"))
mockUserDTO := users.MockUserDTO()
mockUserExists := user.MockExists(false, nil)
mockInsertUser := user.MockInsert(errors.New("failed to insert user"))
mockUserDTO := user.MockDTO()

signUp := auth.MakeSignUp(mockUserExists, mockInsertUser)

Expand Down
8 changes: 4 additions & 4 deletions cmd/api/auth/singup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import (
"context"
"golang.org/x/crypto/bcrypt"

"ahbcc/cmd/api/users"
"ahbcc/cmd/api/user"
"ahbcc/internal/log"
)

// SignUp registers a new user in the system
type SignUp func(ctx context.Context, user users.UserDTO) error
type SignUp func(ctx context.Context, user user.DTO) error

// MakeSignUp creates a new SignUp
func MakeSignUp(userExists users.UserExists, insertUser users.Insert) SignUp {
return func(ctx context.Context, user users.UserDTO) error {
func MakeSignUp(userExists user.Exists, insertUser user.Insert) SignUp {
return func(ctx context.Context, user user.DTO) error {
exists, err := userExists(ctx, user.Username)
if err != nil {
log.Error(ctx, err.Error())
Expand Down
6 changes: 3 additions & 3 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"ahbcc/cmd/api/search/criteria"
"ahbcc/cmd/api/tweets"
"ahbcc/cmd/api/tweets/quotes"
"ahbcc/cmd/api/users"
"ahbcc/cmd/api/user"
"ahbcc/internal/database"
_http "ahbcc/internal/http"
"ahbcc/internal/log"
Expand Down Expand Up @@ -54,8 +54,8 @@ func main() {
insertAppliedMigration := migrations.MakeInsertAppliedMigration(db)
runMigrations := migrations.MakeRun(db, createMigrationsTable, isMigrationApplied, insertAppliedMigration)

userExists := users.MakeUserExists(db)
insertUser := users.MakeInsert(db)
userExists := user.MakeExists(db)
insertUser := user.MakeInsert(db)
signUp := auth.MakeSignUp(userExists, insertUser)

insertSingleQuote := quotes.MakeInsertSingle(db)
Expand Down
11 changes: 11 additions & 0 deletions cmd/api/user/dao.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package user

import "time"

// DAO represents a user
type DAO struct {
ID int `json:"id"`
Username string `json:"username"`
Password string `json:"password_hash"`
CreatedAt time.Time `json:"created_at"`
}
7 changes: 7 additions & 0 deletions cmd/api/user/dtos.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package user

// DTO represents a user to be inserted into the 'user' table
type DTO struct {
Username string `json:"username"`
Password string `json:"password"`
}
10 changes: 10 additions & 0 deletions cmd/api/user/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package user

import "errors"

var (
FailedToInsertUser = errors.New("failed to insert user")
FailedToRetrieveIfUserAlreadyExists = errors.New("failed to retrieve if user already exists")
NoUserFoundForTheGivenUsername = errors.New("no user found for the given username")
FailedExecuteQueryToRetrieveUser = errors.New("failed to execute query to retrieve user")
)
10 changes: 5 additions & 5 deletions cmd/api/users/insert.go → cmd/api/user/insert.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package users
package user

import (
"context"
Expand All @@ -7,18 +7,18 @@ import (
"ahbcc/internal/log"
)

// Insert inserts a new UserDTO into 'users' table
type Insert func(ctx context.Context, user UserDTO) error
// Insert inserts a new DTO into 'user' table
type Insert func(ctx context.Context, user DTO) error

// MakeInsert creates a new Insert
func MakeInsert(db database.Connection) Insert {
const query string = `
INSERT INTO users(username, password_hash)
INSERT INTO user(username, password_hash)
VALUES ($1, $2)
ON CONFLICT (username, password_hash) DO NOTHING;
`

return func(ctx context.Context, user UserDTO) error {
return func(ctx context.Context, user DTO) error {
_, err := db.Exec(ctx, query, user.Username, user.Password)
if err != nil {
log.Error(ctx, err.Error())
Expand Down
14 changes: 7 additions & 7 deletions cmd/api/users/insert_test.go → cmd/api/user/insert_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package users_test
package user_test

import (
"context"
Expand All @@ -9,16 +9,16 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

"ahbcc/cmd/api/users"
"ahbcc/cmd/api/user"
"ahbcc/internal/database"
)

func TestInsert_success(t *testing.T) {
mockPostgresConnection := new(database.MockPostgresConnection)
mockPostgresConnection.On("Exec", mock.Anything, mock.Anything, mock.Anything).Return(pgconn.CommandTag{}, nil)
mockUserDTO := users.MockUserDTO()
mockUserDTO := user.MockDTO()

insertUser := users.MakeInsert(mockPostgresConnection)
insertUser := user.MakeInsert(mockPostgresConnection)

got := insertUser(context.Background(), mockUserDTO)

Expand All @@ -29,11 +29,11 @@ func TestInsert_success(t *testing.T) {
func TestInsert_failsWhenInsertOperationThrowsError(t *testing.T) {
mockPostgresConnection := new(database.MockPostgresConnection)
mockPostgresConnection.On("Exec", mock.Anything, mock.Anything, mock.Anything).Return(pgconn.CommandTag{}, errors.New("failed to insert user"))
mockUserDTO := users.MockUserDTO()
mockUserDTO := user.MockDTO()

insertUser := users.MakeInsert(mockPostgresConnection)
insertUser := user.MakeInsert(mockPostgresConnection)

want := users.FailedToInsertUser
want := user.FailedToInsertUser
got := insertUser(context.Background(), mockUserDTO)

assert.Equal(t, want, got)
Expand Down
48 changes: 48 additions & 0 deletions cmd/api/user/mocks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package user

import (
"context"
"time"
)

// MockExists mocks Exists function
func MockExists(userExists bool, err error) Exists {
return func(ctx context.Context, username string) (bool, error) {
return userExists, err
}
}

// MockInsert mocks Insert function
func MockInsert(err error) Insert {
return func(ctx context.Context, user DTO) error {
return err
}
}

// MockDTO mocks user DTO
func MockDTO() DTO {
return DTO{
Username: "test@test.com",
Password: "password",
}
}

// MockDAO mocks user DAO
func MockDAO() DAO {
return DAO{
ID: 1,
Username: "username",
Password: "password",
CreatedAt: time.Date(2006, time.January, 1, 0, 0, 0, 0, time.Local),
}
}

// MockScanUserDAOValues mocks the properties of user DAO to be used in the Scan function
func MockScanUserDAOValues(dao DAO) []any {
return []any{
dao.ID,
dao.Username,
dao.Password,
dao.CreatedAt,
}
}
Loading

0 comments on commit 901f432

Please sign in to comment.