From 5368e934b6f7065326c84f286797a4a970be9d63 Mon Sep 17 00:00:00 2001 From: nochill Date: Sat, 23 Sep 2023 15:24:21 +0700 Subject: [PATCH] add get user detail --- api/location.go | 11 ++++ api/server.go | 2 + api/user.go | 117 +++++++++++++++++++++++++++++++++++-------- db/mock/store.go | 4 +- db/sqlc/querier.go | 1 - db/sqlc/store.go | 1 + db/sqlc/users.go | 64 +++++++++++++++++++++++ db/sqlc/users.sql.go | 30 ----------- 8 files changed, 176 insertions(+), 54 deletions(-) create mode 100644 db/sqlc/users.go diff --git a/api/location.go b/api/location.go index 61a3bbd..bf5fb35 100644 --- a/api/location.go +++ b/api/location.go @@ -149,6 +149,17 @@ func (server *Server) getTopListLocations(ctx *gin.Context) { } ctx.JSON(http.StatusOK, locations) + + // str, err := ctx.Cookie("kek123429") + + // if err != nil { + // ctx.JSON(http.StatusUnauthorized, ErrorResponse(err, "")) + // } + + // ctx.JSON(http.StatusOK, gin.H{ + // "str": str, + // "res": locations, + // }) } type getListRecentLocationsWithRatingsReq struct { diff --git a/api/server.go b/api/server.go index 87aede7..19021f9 100644 --- a/api/server.go +++ b/api/server.go @@ -38,6 +38,8 @@ func (server *Server) getRoutes() { router.Use(CORSMiddleware()) router.POST("/user/signup", server.createUser) + router.POST("/user/login", server.login) + router.POST("/user/logout", server.logout) // LOCATION router.POST("/locations", server.createLocation) diff --git a/api/user.go b/api/user.go index dc140cd..412e587 100644 --- a/api/user.go +++ b/api/user.go @@ -32,11 +32,9 @@ type createUserResponse struct { } type userTokenResponse struct { - SessionID int32 `json:"session_id"` - AccesToken string `json:"access_token"` - AccessTokenExpiresAt time.Time `json:"access_token_expires_at"` - RefreshToken string `json:"refresh_token"` - RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at"` + SessionID int32 `json:"session_id"` + AccesToken string `json:"access_token"` + AccessTokenExpiresAt time.Time `json:"access_token_expires_at"` } func (server *Server) createUser(ctx *gin.Context) { @@ -84,19 +82,19 @@ func (server *Server) createUser(ctx *gin.Context) { return } - refreshToken, refreshTokenPayload, err := server.TokenMaker.CreateToken( - user.Username, - int(user.ID), - server.Config.RefreshTokenDuration, - ) + // refreshToken, refreshTokenPayload, err := server.TokenMaker.CreateToken( + // user.Username, + // int(user.ID), + // server.Config.RefreshTokenDuration, + // ) session, err := server.Store.CreateSession(ctx, db.CreateSessionParams{ - Username: user.Username, - RefreshToken: refreshToken, - UserAgent: ctx.Request.UserAgent(), - ClientIp: ctx.ClientIP(), - IsBlocked: false, - ExpiresAt: refreshTokenPayload.ExpiredAt, + Username: user.Username, + // RefreshToken: refreshToken, + UserAgent: ctx.Request.UserAgent(), + ClientIp: ctx.ClientIP(), + IsBlocked: false, + // ExpiresAt: refreshTokenPayload.ExpiredAt, }) if err != nil { @@ -105,11 +103,9 @@ func (server *Server) createUser(ctx *gin.Context) { } tokenResponse := userTokenResponse{ - SessionID: session.ID, - AccesToken: accessToken, - AccessTokenExpiresAt: accessPayload.ExpiredAt, - RefreshToken: refreshToken, - RefreshTokenExpiresAt: refreshTokenPayload.ExpiredAt, + SessionID: session.ID, + AccesToken: accessToken, + AccessTokenExpiresAt: accessPayload.ExpiredAt, } res := createUserResponse{ @@ -127,8 +123,87 @@ func (server *Server) createUser(ctx *gin.Context) { UpdatedAt: user.UpdatedAt.Time, } + ctx.SetCookie( + "paseto", + accessToken, + accessPayload.ExpiredAt.Second(), + "/", + "localhost", + false, + true, + ) + ctx.JSON(http.StatusOK, gin.H{ "token": tokenResponse, "user": res, }) } + +func (server *Server) login(ctx *gin.Context) { + var req createUserRequest + + if err := ctx.ShouldBindJSON(&req); err != nil { + ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err)) + return + } + + user, err := server.Store.GetUser(ctx, req.Username) + if err != nil { + if err == sql.ErrNoRows { + ctx.JSON(http.StatusNotFound, ErrorResponse(err, "")) + return + } + ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong whlie try to get user")) + return + } + + err = util.CheckPassword(req.Password, user.Password) + if err != nil { + ctx.JSON(http.StatusUnauthorized, ErrorResponse(err, "Password not match")) + return + } + + accessToken, accessPayload, err := server.TokenMaker.CreateToken(user.Username, int(user.ID), server.Config.TokenDuration) + + if err != nil { + ctx.JSON(http.StatusInternalServerError, "Something went wrong while try to create token") + return + } + + _, err = server.Store.CreateSession(ctx, db.CreateSessionParams{ + Username: user.Username, + UserAgent: ctx.Request.UserAgent(), + ClientIp: ctx.ClientIP(), + IsBlocked: false, + }) + + if err != nil { + ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while try to create session")) + return + } + + ctx.SetCookie( + "paseto", + accessToken, + accessPayload.ExpiredAt.Second(), + "", + "localhost", + false, + true, + ) + + ctx.JSON(http.StatusOK, user) +} + +func (server *Server) logout(ctx *gin.Context) { + ctx.SetCookie( + "paseto", + "", + -1, + "/", + "", + false, + true, + ) + ctx.Writer.WriteHeader(http.StatusNoContent) +} diff --git a/db/mock/store.go b/db/mock/store.go index 6850c02..74b7228 100644 --- a/db/mock/store.go +++ b/db/mock/store.go @@ -200,10 +200,10 @@ func (mr *MockStoreMockRecorder) GetTopListLocations(arg0, arg1 interface{}) *go } // GetUser mocks base method. -func (m *MockStore) GetUser(arg0 context.Context, arg1 string) (db.User, error) { +func (m *MockStore) GetUser(arg0 context.Context, arg1 string) (db.GetUserRow, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetUser", arg0, arg1) - ret0, _ := ret[0].(db.User) + ret0, _ := ret[0].(db.GetUserRow) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/db/sqlc/querier.go b/db/sqlc/querier.go index 570a40e..b434b93 100644 --- a/db/sqlc/querier.go +++ b/db/sqlc/querier.go @@ -18,7 +18,6 @@ type Querier interface { GetLocation(ctx context.Context, id int32) (GetLocationRow, error) GetLocationTag(ctx context.Context, targetID int32) ([]string, error) GetSession(ctx context.Context, id int32) (UserSession, error) - GetUser(ctx context.Context, username string) (User, error) UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error) } diff --git a/db/sqlc/store.go b/db/sqlc/store.go index 403e206..1ff2fe4 100644 --- a/db/sqlc/store.go +++ b/db/sqlc/store.go @@ -11,6 +11,7 @@ type Store interface { Querier GetTopListLocations(ctx context.Context, arg GetTopListLocationsParams) ([]GetTopListLocationsRow, error) GetImagesByLocation(ctx context.Context, arg GetImagesByLocationParams) ([]GetImagesByLocationRow, error) + GetUser(ctx context.Context, username string) (GetUserRow, error) } type SQLStore struct { diff --git a/db/sqlc/users.go b/db/sqlc/users.go new file mode 100644 index 0000000..8f769f8 --- /dev/null +++ b/db/sqlc/users.go @@ -0,0 +1,64 @@ +package db + +import ( + "context" + "database/sql" + + "github.com/sqlc-dev/pqtype" +) + +const getUser = `-- name: GetUser :one +SELECT + id, + COALESCE(email, '') as email, + password, + username, + COALESCE(avatar_picture, '') as avatar_picture, + banned_at, + banned_until, + COALESCE(ban_reason, '') as ban_reason, + is_permaban, + is_admin, + is_critics, + is_verified, + social_media +FROM USERS +WHERE username = $1 +` + +type GetUserRow struct { + ID int32 `json:"id"` + Email string `json:"email"` + Password string `json:"-"` + Username string `json:"username"` + AvatarPicture string `json:"avatar_picture"` + BannedAt sql.NullTime `json:"banned_at"` + BannedUntil sql.NullTime `json:"banned_until"` + BanReason string `json:"ban_reason"` + IsPermaban bool `json:"is_permaban"` + IsAdmin bool `json:"is_admin"` + IsCritics bool `json:"is_critics"` + IsVerified bool `json:"is_verified"` + SocialMedia pqtype.NullRawMessage `json:"social_media"` +} + +func (q *Queries) GetUser(ctx context.Context, username string) (GetUserRow, error) { + row := q.db.QueryRowContext(ctx, getUser, username) + var i GetUserRow + err := row.Scan( + &i.ID, + &i.Email, + &i.Password, + &i.Username, + &i.AvatarPicture, + &i.BannedAt, + &i.BannedUntil, + &i.BanReason, + &i.IsPermaban, + &i.IsAdmin, + &i.IsCritics, + &i.IsVerified, + &i.SocialMedia, + ) + return i, err +} diff --git a/db/sqlc/users.sql.go b/db/sqlc/users.sql.go index c1d05ef..6dbb453 100644 --- a/db/sqlc/users.sql.go +++ b/db/sqlc/users.sql.go @@ -48,36 +48,6 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, e return i, err } -const getUser = `-- name: GetUser :one -SELECT id, email, username, password, avatar_picture, google_sign_in_payload, banned_at, banned_until, ban_reason, is_permaban, is_admin, is_critics, is_verified, is_active, social_media, created_at, updated_at FROM USERS -WHERE username = $1 -` - -func (q *Queries) GetUser(ctx context.Context, username string) (User, error) { - row := q.db.QueryRowContext(ctx, getUser, username) - var i User - err := row.Scan( - &i.ID, - &i.Email, - &i.Username, - &i.Password, - &i.AvatarPicture, - &i.GoogleSignInPayload, - &i.BannedAt, - &i.BannedUntil, - &i.BanReason, - &i.IsPermaban, - &i.IsAdmin, - &i.IsCritics, - &i.IsVerified, - &i.IsActive, - &i.SocialMedia, - &i.CreatedAt, - &i.UpdatedAt, - ) - return i, err -} - const updatePassword = `-- name: UpdatePassword :exec UPDATE users SET password = $1