package api import ( "database/sql" "errors" "net/http" "time" "github.com/gin-gonic/gin" db "github.com/itsscb/df/bff/db/sqlc" "github.com/itsscb/df/bff/token" ) type createAccountRequest struct { Passwordhash string `binding:"required" json:"passwordhash"` PrivacyAccepted bool `json:"privacy_accepted"` Firstname string `binding:"required" json:"firstname"` Lastname string `binding:"required" json:"lastname"` Birthday time.Time `binding:"required" json:"birthday"` Email string `binding:"required" json:"email"` Phone string `json:"phone"` City string `binding:"required" json:"city"` Zip string `binding:"required" json:"zip"` Street string `binding:"required" json:"street"` Country string `binding:"required" json:"country"` } func (server *Server) createAccount(ctx *gin.Context) { var req createAccountRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } arg := db.CreateAccountTxParams{ CreateAccountParams: db.CreateAccountParams{ Passwordhash: req.Passwordhash, PrivacyAccepted: sql.NullBool{ Valid: true, Bool: req.PrivacyAccepted, }, Firstname: req.Firstname, Lastname: req.Lastname, Birthday: req.Birthday, Email: req.Email, City: req.City, Zip: req.Zip, Street: req.Street, Country: req.Country, Creator: req.Email, Phone: sql.NullString{ Valid: req.Phone != "", String: req.Phone, }, }, AfterCreate: func(a db.Account) error { return nil }, } account, err := server.store.CreateAccountTx(ctx, arg) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } ctx.JSON(http.StatusOK, account) } type getAccountRequest struct { ID uint64 `uri:"id" binding:"required,min=1" json:"id"` } func (server *Server) getAccount(ctx *gin.Context) { var req getAccountRequest if err := ctx.ShouldBindUri(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } account, err := server.store.GetAccount(ctx, req.ID) if err != nil { if err == sql.ErrNoRows { ctx.JSON(http.StatusNotFound, errorResponse(err)) return } ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) if account.ID != authPayload.AccountID { err := errors.New("account doesn't belong to the authenticated user") ctx.JSON(http.StatusUnauthorized, errorResponse(err)) return } ctx.JSON(http.StatusOK, account) } type listAccountRequest struct { PageID int32 `form:"page_id" binding:"required,min=1"` PageSize int32 `form:"page_size" binding:"required,min=5,max=50"` } func (server *Server) listAccounts(ctx *gin.Context) { var req listAccountRequest if err := ctx.ShouldBindQuery(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) account, err := server.store.GetAccount(ctx, authPayload.AccountID) if err != nil { if err == sql.ErrNoRows { ctx.JSON(http.StatusNotFound, errorResponse(err)) return } ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } if account.PermissionLevel < 1 { err := errors.New("only for admin users") ctx.JSON(http.StatusUnauthorized, errorResponse(err)) return } arg := db.ListAccountsParams{ Limit: req.PageSize, Offset: (req.PageID - 1) * req.PageSize, } accounts, err := server.store.ListAccounts(ctx, arg) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } ctx.JSON(http.StatusOK, accounts) } type updateAccountPrivacyRequest struct { ID uint64 `binding:"required" json:"ID"` PrivacyAccepted *bool `binding:"required" json:"privacy_accepted"` } func (server *Server) updateAccountPrivacy(ctx *gin.Context) { var req updateAccountPrivacyRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } account, err := server.store.GetAccount(ctx, req.ID) if err != nil { ctx.JSON(http.StatusNotFound, errorResponse(err)) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) if account.ID != authPayload.AccountID { err := errors.New("account doesn't belong to the authenticated user") ctx.JSON(http.StatusUnauthorized, errorResponse(err)) return } account, err = server.store.UpdateAccountPrivacyTx(ctx, db.UpdateAccountPrivacyTxParams{ ID: req.ID, Changer: account.Email, PrivacyAccepted: req.PrivacyAccepted, }) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } ctx.JSON(http.StatusOK, account) } type updateAccountRequest struct { ID uint64 `binding:"required" json:"ID"` NewPassword string `json:"new_password"` Firstname string `json:"firstname"` Lastname string `json:"lastname"` Birthday time.Time `json:"birthday"` Email string `json:"email"` Phone string `json:"phone"` City string `json:"city"` Zip string `json:"zip"` Street string `json:"street"` Country string `json:"country"` } func (server *Server) updateAccount(ctx *gin.Context) { var req updateAccountRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } account, err := server.store.GetAccount(ctx, req.ID) if err != nil { ctx.JSON(http.StatusNotFound, errorResponse(err)) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) if account.ID != authPayload.AccountID { err := errors.New("account doesn't belong to the authenticated user") ctx.JSON(http.StatusUnauthorized, errorResponse(err)) return } arg := db.UpdateAccountTxParams{ ID: req.ID, Changer: account.Email, Passwordhash: sql.NullString{ String: req.NewPassword, Valid: req.NewPassword != "", }, Firstname: sql.NullString{ String: req.Firstname, Valid: req.Firstname != "", }, Lastname: sql.NullString{ String: req.Lastname, Valid: req.Lastname != "", }, Birthday: sql.NullTime{ Time: req.Birthday, Valid: req.Birthday != time.Time{}, }, Email: sql.NullString{ String: req.Email, Valid: req.Email != "", }, City: sql.NullString{ String: req.City, Valid: req.City != "", }, Zip: sql.NullString{ String: req.Zip, Valid: req.Zip != "", }, Street: sql.NullString{ String: req.Street, Valid: req.Street != "", }, Country: sql.NullString{ String: req.Country, Valid: req.Country != "", }, Phone: sql.NullString{ String: req.Phone, Valid: req.Phone != "", }, } account, err = server.store.UpdateAccountTx(ctx, arg) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } ctx.JSON(http.StatusOK, account) }