users.go (4955B)
1 package main 2 3 import ( 4 "log" 5 "net/http" 6 7 "github.com/gin-gonic/gin" 8 "jacobedwards.org/spaceplanner.app/internal/backend" 9 ) 10 11 type CreateUserParams struct { 12 Creds Credentials `json:"credentials" binding:"required"` 13 Email string `json:"email" binding:"required"` 14 EmailStrict *bool `json:"email_strict"` 15 } 16 17 type CodeReq struct { 18 Code string `json:"code"` 19 } 20 21 func (e *Env) CreateUser(c *gin.Context) { 22 var params CreateUserParams 23 if err := c.ShouldBind(¶ms); err != nil { 24 RespondError(c, http.StatusUnauthorized, "Unable to create user: %s", err.Error()) 25 return 26 } 27 28 user, err := e.backend.CreateUser(params.Creds.Username, params.Creds.Password) 29 if err != nil { 30 RespondError(c, http.StatusBadRequest, 31 "Unable to create user: %s", err.Error()) 32 return 33 } 34 35 err = e.backend.UpdateUserSetting(nil, user.Name, "email", params.Email) 36 if err == nil && params.EmailStrict != nil { 37 err = e.backend.UpdateUserSetting(nil, user.Name, "email_strict", *params.EmailStrict) 38 } 39 if err != nil { 40 RespondError(c, 400, "Invalid Email or Email Policy: %s", err.Error()) 41 err2 := e.backend.DeleteUser(user.Name) 42 if err2 != nil { 43 log.Printf("%s: User cannot be deleted: %s", user.Name, err2.Error()) 44 } 45 return 46 } 47 48 if _, err := e.backend.VerifyEmail(user.Name, nil); err != nil { 49 log.Printf("Unable to send verification email: %s", err.Error()) 50 } 51 52 Respond(c, http.StatusCreated, user) 53 } 54 55 func (e *Env) VerifiedUserEmail(c *gin.Context) { 56 user := c.Param("user") 57 58 emails, err := e.backend.UserEmails(user) 59 if err != nil { 60 RespondError(c, 500, "Unable to get user's emails") 61 } else { 62 Respond(c, 200, emails.Verified) 63 } 64 } 65 66 func (e *Env) VerifyUserEmailCode(c *gin.Context) { 67 user := c.Param("user") 68 var req CodeReq 69 70 if err := c.ShouldBind(&req); err != nil { 71 RespondError(c, 400, "Unable to read request: %s", err.Error()) 72 return 73 } 74 if verified, err := e.backend.VerifyEmail(user, &req.Code); err != nil { 75 RespondError(c, 500, "Unable to verify email: %s", err.Error()) 76 } else { 77 Respond(c, 200, gin.H{"valid": verified}) 78 } 79 } 80 81 func (e *Env) SendUserEmailCode(c *gin.Context) { 82 user := c.Param("user") 83 84 if err := e.backend.SendVerificationEmail(user); err != nil { 85 RespondError(c, 500, "Unable to send verification email: %s", err.Error()) 86 } else { 87 Respond(c, 200, nil) 88 } 89 } 90 91 func (e *Env) DeleteUser(c *gin.Context) { 92 user := c.Param("user") 93 err := e.backend.DeleteUser(user) 94 if err != nil { 95 RespondError(c, http.StatusBadRequest, "Unable to delete user: %s", err.Error()) 96 return 97 } 98 Respond(c, http.StatusOK, backend.User{ Name: user }) 99 } 100 101 func (e *Env) GetUser(c *gin.Context) { 102 name := c.Param("user") 103 if name == "" { 104 RespondError(c, http.StatusNotFound, "No username given") 105 return 106 } 107 108 user, err := e.backend.GetUser(nil, name) 109 if err != nil { 110 RespondError(c, http.StatusOK, "%q: Unable to get user: %s", 111 name, err.Error()) 112 return 113 } 114 115 Respond(c, http.StatusOK, user) 116 } 117 118 func (e *Env) GetUserSettings(c *gin.Context) { 119 user := c.Param("user") 120 if user == "" { 121 RespondError(c, http.StatusNotFound, "No username given") 122 return 123 } 124 125 settings, err := e.backend.GetUserSettings(nil, user) 126 if err != nil { 127 RespondError(c, 400, "Unable to get settings: %s", err.Error()) 128 } else { 129 Respond(c, http.StatusOK, settings) 130 } 131 } 132 133 func (e *Env) UpdateUserSettings(c *gin.Context) { 134 user := c.Param("user") 135 if user == "" { 136 RespondError(c, http.StatusNotFound, "No username given") 137 return 138 } 139 140 patches := make([]backend.Patch, 16) 141 if err := c.ShouldBind(&patches); err != nil { 142 RespondError(c, 400, "Unable to read patchset") 143 return 144 } 145 146 tx, err := e.backend.DB.Begin() 147 if err != nil { 148 RespondError(c, 500, "Unable to begin transaction") 149 return 150 } 151 defer tx.Rollback() 152 153 settings, err := e.backend.GetUserSettings(tx, user) 154 if err != nil { 155 RespondError(c, 400, "Unable to get settings") 156 return 157 } 158 159 if err = applyPatchset(settings, patches); err != nil { 160 RespondError(c, 400, "Unable to apply patches: %s", err.Error()) 161 return 162 } 163 164 if _, err := e.backend.DeleteUserSettings(tx, user); err != nil { 165 RespondError(c, 400, "Unable to truncate settings: %s", err.Error()) 166 return 167 } 168 if err := e.backend.UpdateUserSettings(tx, user, settings); err != nil { 169 RespondError(c, 400, "Unable to set settings: %s", err.Error()) 170 return 171 } 172 if err = tx.Commit(); err != nil { 173 RespondError(c, 400, "Unable to commit transaction: %s", err.Error()) 174 return 175 } 176 177 Respond(c, http.StatusOK, settings) 178 } 179 180 // In the future I want to return an array of backend.Service types 181 func (e *Env) UserService(c *gin.Context) { 182 type body struct { 183 Services []string `json:"services"` 184 } 185 186 service, err := e.backend.UserService(c.Param("user")) 187 if err != nil { 188 RespondError(c, 500, "Unable to get service") 189 } else { 190 var body body 191 body.Services = make([]string, 0, 1) 192 if service != nil { 193 body.Services = append(body.Services, *service) 194 } 195 Respond(c, 200, body) 196 } 197 }