Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add login to users - #15 #27

Merged
merged 1 commit into from
Jun 22, 2024
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
1,662 changes: 834 additions & 828 deletions api/openapi.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/go-chi/chi v1.5.5 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/jaswdr/faker/v2 v2.3.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/stretchr/testify v1.9.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4=
github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk=
github.com/jaswdr/faker/v2 v2.3.0 h1:jgQ9UmU2Eb5tSQ8JkUS4tPoyTM2OtThQpOpwk7Fa9RY=
github.com/jaswdr/faker/v2 v2.3.0/go.mod h1:ROK8xwQV0hYOLDUtxCQgHGcl10jbVzIvqHxcIDdwY2Q=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
Expand Down
2 changes: 2 additions & 0 deletions internal/app/database/struct_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ func RegisterAllUpdates() map[string][]DatabaseUpdateFunc {
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0011_update0011testdata)
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0011_update0012)
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0012_update0012testdata)
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0012_update0013)
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0013_update0013testdata)
return allUpdates
}

Expand Down
30 changes: 30 additions & 0 deletions internal/app/database/update0012_update0013.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package database

import (
"database/sql"
"log/slog"
"runtime"
)

func DatabaseUpdate_update0012_update0013(db *sql.DB, getInfo bool) (string, string, string, error) {

// WARNING!!!
// Do not change the update if it has already been installed by other developers or in production.
// To correct the database, create a new update and register it in the list of updates.

fromUpdateId, toUpdateId := ParseNameFuncUpdate(runtime.Caller(0))
description := "Added column display_name to users"
if getInfo {
return fromUpdateId, toUpdateId, description, nil
}
query := `
ALTER TABLE users
ADD COLUMN display_name varchar(255);
`
_, err := db.Exec(query)
if err != nil {
slog.Error("Problem with update, query: " + query + "\n error:" + err.Error())
return fromUpdateId, toUpdateId, description, err
}
return fromUpdateId, toUpdateId, description, nil
}
46 changes: 46 additions & 0 deletions internal/app/database/update0013_update0013testdata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package database

import (
"database/sql"
"fmt"
"log"
"log/slog"
"runtime"

"github.com/jaswdr/faker/v2"
)

func DatabaseUpdate_update0013_update0013testdata(db *sql.DB, getInfo bool) (string, string, string, error) {

// WARNING!!!
// Do not change the update if it has already been installed by other developers or in production.
// To correct the database, create a new update and register it in the list of updates.

fromUpdateId, toUpdateId := ParseNameFuncUpdate(runtime.Caller(0))
description := "Insert test data to game_services"
if getInfo {
return fromUpdateId, toUpdateId, description, nil
}
query := `
SELECT id from users
`
rows, err := db.Query(query)
if err != nil {
slog.Error("Problem with select, query: " + query + "\n error:" + err.Error())
return fromUpdateId, toUpdateId, description, err
}
fake := faker.New()
for rows.Next() {
var id int
if err := rows.Scan(&id); err != nil {
log.Fatalf("Error scanning row: %v", err)
}
query := fmt.Sprintf("UPDATE users SET display_name = '%s' WHERE id = %d", fake.Person().Name(), id)
_, err := db.Exec(query)
if err != nil {
slog.Error("Problem with update, query: " + query + "\n error:" + err.Error())
return fromUpdateId, toUpdateId, description, err
}
}
return fromUpdateId, toUpdateId, description, nil
}
1 change: 1 addition & 0 deletions internal/app/db/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "ctf01d/internal/app/server"

type User struct {
Id int `db:"id"`
DisplayName string `db:"display_name"`
Username string `db:"user_name"`
Role server.UserRequestRole `db:"role"`
AvatarUrl string `db:"avatar_url"`
Expand Down
10 changes: 5 additions & 5 deletions internal/app/handlers/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ import (
func (h *Handlers) PostApiV1AuthSignin(w http.ResponseWriter, r *http.Request) {
var req server.PostApiV1AuthSigninJSONBody
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
slog.Warn(err.Error(), "handler", "LoginSessionHandler")
slog.Warn(err.Error(), "handler", "PostApiV1AuthSignin")
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
userRepo := repository.NewUserRepository(h.DB)
user, err := userRepo.GetByUserName(r.Context(), *req.UserName)
if err != nil || !api_helpers.CheckPasswordHash(*req.Password, user.PasswordHash) {
slog.Warn(err.Error(), "handler", "LoginSessionHandler")
slog.Warn(err.Error(), "handler", "PostApiV1AuthSignin")
api_helpers.RespondWithJSON(w, http.StatusUnauthorized, map[string]string{"error": "Invalid password or user"})
return
}

repo := repository.NewSessionRepository(h.DB)
sessionId, err := repo.StoreSessionInDB(r.Context(), user.Id)
if err != nil {
slog.Warn(err.Error(), "handler", "LoginSessionHandler")
slog.Warn(err.Error(), "handler", "PostApiV1AuthSignin")
api_helpers.RespondWithJSON(w, http.StatusInternalServerError, map[string]string{"error": "Failed to store session"})
return
}
Expand All @@ -47,14 +47,14 @@ func (h *Handlers) PostApiV1AuthSignin(w http.ResponseWriter, r *http.Request) {
func (h *Handlers) PostApiV1AuthSignout(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("session_id")
if err != nil {
slog.Warn(err.Error(), "handler", "LogoutSessionHandler")
slog.Warn(err.Error(), "handler", "PostApiV1AuthSignout")
api_helpers.RespondWithJSON(w, http.StatusUnauthorized, map[string]string{"error": "No session found"})
return
}
repo := repository.NewSessionRepository(h.DB)
err = repo.DeleteSessionInDB(r.Context(), cookie.Value)
if err != nil {
slog.Warn(err.Error(), "handler", "LogoutSessionHandler")
slog.Warn(err.Error(), "handler", "PostApiV1AuthSignout")
api_helpers.RespondWithJSON(w, http.StatusInternalServerError, map[string]string{"error": "Failed to delete session"})
return
}
Expand Down
17 changes: 9 additions & 8 deletions internal/app/repository/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ func NewUserRepository(db *sql.DB) UserRepository {
}

func (r *userRepo) Create(ctx context.Context, user *models.User) error {
query := `INSERT INTO users (user_name, avatar_url, role, status, password_hash) VALUES ($1, $2, $3, $4, $5) RETURNING id`
err := r.db.QueryRowContext(ctx, query, user.Username, user.AvatarUrl, user.Role, user.Status, user.PasswordHash).Scan(&user.Id)
query := `INSERT INTO users (display_name, user_name, avatar_url, role, status, password_hash) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id`
err := r.db.QueryRowContext(ctx, query, user.DisplayName, user.Username, user.AvatarUrl, user.Role, user.Status, user.PasswordHash).Scan(&user.Id)
if err != nil {
return err
}

return nil
}

Expand All @@ -45,9 +46,9 @@ func (r *userRepo) AddUserToTeams(ctx context.Context, userId int, teamIds *[]in
}

func (r *userRepo) GetById(ctx context.Context, id int) (*models.User, error) {
query := `SELECT id, user_name, avatar_url, role, status FROM users WHERE id = $1`
query := `SELECT id, display_name, user_name, avatar_url, role, status FROM users WHERE id = $1`
user := &models.User{}
err := r.db.QueryRowContext(ctx, query, id).Scan(&user.Id, &user.Username, &user.AvatarUrl, &user.Role, &user.Status)
err := r.db.QueryRowContext(ctx, query, id).Scan(&user.Id, &user.DisplayName, &user.Username, &user.AvatarUrl, &user.Role, &user.Status)
if err != nil {
return nil, err
}
Expand All @@ -65,8 +66,8 @@ func (r *userRepo) GetByUserName(ctx context.Context, name string) (*models.User
}

func (r *userRepo) Update(ctx context.Context, user *models.User) error {
query := `UPDATE users SET user_name = $1, avatar_url = $2, role = $3, status = $4, password_hash = $5 WHERE id = $6`
_, err := r.db.ExecContext(ctx, query, user.Username, user.AvatarUrl, user.Role, user.Status, user.PasswordHash, user.Id)
query := `UPDATE users SET user_name = $1, avatar_url = $2, role = $3, status = $4, password_hash = $5, login = $6 WHERE id = $7`
_, err := r.db.ExecContext(ctx, query, user.Username, user.AvatarUrl, user.Role, user.Status, user.PasswordHash, user.DisplayName, user.Id)
return err
}

Expand All @@ -93,7 +94,7 @@ func (r *userRepo) Delete(ctx context.Context, id int) error {
}

func (r *userRepo) List(ctx context.Context) ([]*models.User, error) {
query := `SELECT id, user_name, avatar_url, role, status FROM users`
query := `SELECT id, display_name, user_name, avatar_url, role, status FROM users`
rows, err := r.db.QueryContext(ctx, query)
if err != nil {
return nil, err
Expand All @@ -103,7 +104,7 @@ func (r *userRepo) List(ctx context.Context) ([]*models.User, error) {
var users []*models.User
for rows.Next() {
var user models.User
if err := rows.Scan(&user.Id, &user.Username, &user.AvatarUrl, &user.Role, &user.Status); err != nil {
if err := rows.Scan(&user.Id, &user.DisplayName, &user.Username, &user.AvatarUrl, &user.Role, &user.Status); err != nil {
return nil, err
}
users = append(users, &user)
Expand Down
14 changes: 10 additions & 4 deletions internal/app/server/server.gen.go

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

22 changes: 12 additions & 10 deletions internal/app/view/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ import (
)

type User struct {
Id int `json:"id"`
Username string `json:"user_name"`
Role string `json:"role,omitempty"`
AvatarUrl string `json:"avatar_url,omitempty"`
Status string `json:"status,omitempty"`
Id int `json:"id"`
DisplayName string `json:"display_name"`
Username string `json:"user_name"`
Role string `json:"role,omitempty"`
AvatarUrl string `json:"avatar_url,omitempty"`
Status string `json:"status,omitempty"`
}

func NewUserFromModel(u *db.User) *server.UserResponse {
userRole := helpers.ConvertUserRequestRoleToUserResponseRole(u.Role)
return &server.UserResponse{
Id: &u.Id,
UserName: &u.Username,
Role: &userRole,
AvatarUrl: &u.AvatarUrl,
Status: &u.Status,
Id: &u.Id,
UserName: &u.Username,
DisplayName: &u.DisplayName,
Role: &userRole,
AvatarUrl: &u.AvatarUrl,
Status: &u.Status,
}
}

Expand Down
Loading