package api import ( "database/sql" "net/http" "time" db "git.nochill.in/nochill/hiling_go/db/sqlc" "git.nochill.in/nochill/hiling_go/util" "github.com/gin-gonic/gin" "github.com/lib/pq" ) type createUserRequest struct { Username string `json:"username" binding:"required,alphanum"` Password string `json:"password" binding:"required,min=7"` } type createUserResponse struct { ID int32 `json:"id"` Username string `json:"username"` AvatarPicture string `json:"avatar_picture"` // avatar_url 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"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func (server *Server) createUser(ctx *gin.Context) { var req createUserRequest if err := ctx.ShouldBindJSON(&req); err != nil { if err != nil { ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err)) return } } hashedPassword, err := util.HashPassword(req.Password) if err != nil { ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong")) return } arg := db.CreateUserParams{ Username: req.Username, Password: hashedPassword, } user, err := server.Store.CreateUser(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.StatusConflict, ErrorResponse(err, "Username already used")) return } } ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong")) return } accessToken, _, err := server.TokenMaker.CreateToken( user.Username, int(user.ID), server.Config.TokenDuration, ) if err != nil { ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while creating token")) return } // refreshToken, refreshTokenPayload, err := server.TokenMaker.CreateToken( // user.Username, // int(user.ID), // server.Config.RefreshTokenDuration, // ) _, err = server.Store.CreateSession(ctx, db.CreateSessionParams{ Username: user.Username, // RefreshToken: refreshToken, UserAgent: ctx.Request.UserAgent(), ClientIp: ctx.ClientIP(), IsBlocked: false, // ExpiresAt: refreshTokenPayload.ExpiredAt, }) if err != nil { ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while saving sessions")) return } res := createUserResponse{ ID: user.ID, Username: user.Username, AvatarPicture: user.AvatarPicture.String, BannedAt: sql.NullTime{Valid: user.BannedAt.Valid, Time: user.BannedAt.Time}, BannedUntil: sql.NullTime{Valid: user.BannedUntil.Valid, Time: user.BannedUntil.Time}, BanReason: user.BanReason.String, IsPermaban: user.IsPermaban.Bool, IsAdmin: user.IsAdmin.Bool, IsCritics: user.IsCritics.Bool, IsVerified: user.IsVerified.Bool, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, } ctx.SetCookie( "paseto", accessToken, int(server.Config.CookieDuration), "/", "localhost", false, false, ) ctx.JSON(http.StatusOK, 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, _, 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, int(server.Config.CookieDuration), "/", "localhost", false, false, ) ctx.JSON(http.StatusOK, user) } func (server *Server) logout(ctx *gin.Context) { ctx.SetCookie( "paseto", "", -1, "/", "", false, true, ) ctx.Writer.WriteHeader(http.StatusNoContent) }