github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/routers/controllers/user.go (about) 1 package controllers 2 3 import ( 4 "encoding/json" 5 "fmt" 6 7 model "github.com/cloudreve/Cloudreve/v3/models" 8 "github.com/cloudreve/Cloudreve/v3/pkg/authn" 9 "github.com/cloudreve/Cloudreve/v3/pkg/request" 10 "github.com/cloudreve/Cloudreve/v3/pkg/serializer" 11 "github.com/cloudreve/Cloudreve/v3/pkg/thumb" 12 "github.com/cloudreve/Cloudreve/v3/pkg/util" 13 "github.com/cloudreve/Cloudreve/v3/service/user" 14 "github.com/duo-labs/webauthn/webauthn" 15 "github.com/gin-gonic/gin" 16 ) 17 18 // StartLoginAuthn 开始注册WebAuthn登录 19 func StartLoginAuthn(c *gin.Context) { 20 userName := c.Param("username") 21 expectedUser, err := model.GetActiveUserByEmail(userName) 22 if err != nil { 23 c.JSON(200, serializer.Err(serializer.CodeUserNotFound, "", err)) 24 return 25 } 26 27 instance, err := authn.NewAuthnInstance() 28 if err != nil { 29 c.JSON(200, serializer.Err(serializer.CodeInitializeAuthn, "Cannot initialize authn", err)) 30 return 31 } 32 33 options, sessionData, err := instance.BeginLogin(expectedUser) 34 35 if err != nil { 36 c.JSON(200, ErrorResponse(err)) 37 return 38 } 39 40 val, err := json.Marshal(sessionData) 41 if err != nil { 42 c.JSON(200, ErrorResponse(err)) 43 return 44 } 45 46 util.SetSession(c, map[string]interface{}{ 47 "registration-session": val, 48 }) 49 c.JSON(200, serializer.Response{Code: 0, Data: options}) 50 } 51 52 // FinishLoginAuthn 完成注册WebAuthn登录 53 func FinishLoginAuthn(c *gin.Context) { 54 userName := c.Param("username") 55 expectedUser, err := model.GetActiveUserByEmail(userName) 56 if err != nil { 57 c.JSON(200, serializer.Err(serializer.CodeUserNotFound, "", err)) 58 return 59 } 60 61 sessionDataJSON := util.GetSession(c, "registration-session").([]byte) 62 63 var sessionData webauthn.SessionData 64 err = json.Unmarshal(sessionDataJSON, &sessionData) 65 66 instance, err := authn.NewAuthnInstance() 67 if err != nil { 68 c.JSON(200, serializer.Err(serializer.CodeInitializeAuthn, "Cannot initialize authn", err)) 69 return 70 } 71 72 _, err = instance.FinishLogin(expectedUser, sessionData, c.Request) 73 74 if err != nil { 75 c.JSON(200, serializer.Err(serializer.CodeWebAuthnCredentialError, "Verification failed", err)) 76 return 77 } 78 79 util.SetSession(c, map[string]interface{}{ 80 "user_id": expectedUser.ID, 81 }) 82 c.JSON(200, serializer.BuildUserResponse(expectedUser)) 83 } 84 85 // StartRegAuthn 开始注册WebAuthn信息 86 func StartRegAuthn(c *gin.Context) { 87 currUser := CurrentUser(c) 88 89 instance, err := authn.NewAuthnInstance() 90 if err != nil { 91 c.JSON(200, serializer.Err(serializer.CodeInitializeAuthn, "Cannot initialize authn", err)) 92 return 93 } 94 95 options, sessionData, err := instance.BeginRegistration(currUser) 96 97 if err != nil { 98 c.JSON(200, ErrorResponse(err)) 99 return 100 } 101 102 val, err := json.Marshal(sessionData) 103 if err != nil { 104 c.JSON(200, ErrorResponse(err)) 105 return 106 } 107 108 util.SetSession(c, map[string]interface{}{ 109 "registration-session": val, 110 }) 111 c.JSON(200, serializer.Response{Code: 0, Data: options}) 112 } 113 114 // FinishRegAuthn 完成注册WebAuthn信息 115 func FinishRegAuthn(c *gin.Context) { 116 currUser := CurrentUser(c) 117 sessionDataJSON := util.GetSession(c, "registration-session").([]byte) 118 119 var sessionData webauthn.SessionData 120 err := json.Unmarshal(sessionDataJSON, &sessionData) 121 122 instance, err := authn.NewAuthnInstance() 123 if err != nil { 124 c.JSON(200, serializer.Err(serializer.CodeInitializeAuthn, "Cannot initialize authn", err)) 125 return 126 } 127 128 credential, err := instance.FinishRegistration(currUser, sessionData, c.Request) 129 130 if err != nil { 131 c.JSON(200, ErrorResponse(err)) 132 return 133 } 134 135 err = currUser.RegisterAuthn(credential) 136 if err != nil { 137 c.JSON(200, ErrorResponse(err)) 138 return 139 } 140 141 c.JSON(200, serializer.Response{ 142 Code: 0, 143 Data: map[string]interface{}{ 144 "id": credential.ID, 145 "fingerprint": fmt.Sprintf("% X", credential.Authenticator.AAGUID), 146 }, 147 }) 148 } 149 150 // UserLogin 用户登录 151 func UserLogin(c *gin.Context) { 152 var service user.UserLoginService 153 if err := c.ShouldBindJSON(&service); err == nil { 154 res := service.Login(c) 155 c.JSON(200, res) 156 } else { 157 c.JSON(200, ErrorResponse(err)) 158 } 159 } 160 161 // UserRegister 用户注册 162 func UserRegister(c *gin.Context) { 163 var service user.UserRegisterService 164 if err := c.ShouldBindJSON(&service); err == nil { 165 res := service.Register(c) 166 c.JSON(200, res) 167 } else { 168 c.JSON(200, ErrorResponse(err)) 169 } 170 } 171 172 // User2FALogin 用户二步验证登录 173 func User2FALogin(c *gin.Context) { 174 var service user.Enable2FA 175 if err := c.ShouldBindJSON(&service); err == nil { 176 res := service.Login(c) 177 c.JSON(200, res) 178 } else { 179 c.JSON(200, ErrorResponse(err)) 180 } 181 } 182 183 // UserSendReset 发送密码重设邮件 184 func UserSendReset(c *gin.Context) { 185 var service user.UserResetEmailService 186 if err := c.ShouldBindJSON(&service); err == nil { 187 res := service.Reset(c) 188 c.JSON(200, res) 189 } else { 190 c.JSON(200, ErrorResponse(err)) 191 } 192 } 193 194 // UserReset 重设密码 195 func UserReset(c *gin.Context) { 196 var service user.UserResetService 197 if err := c.ShouldBindJSON(&service); err == nil { 198 res := service.Reset(c) 199 c.JSON(200, res) 200 } else { 201 c.JSON(200, ErrorResponse(err)) 202 } 203 } 204 205 // UserActivate 用户激活 206 func UserActivate(c *gin.Context) { 207 var service user.SettingService 208 if err := c.ShouldBindUri(&service); err == nil { 209 res := service.Activate(c) 210 c.JSON(200, res) 211 } else { 212 c.JSON(200, ErrorResponse(err)) 213 } 214 } 215 216 // UserSignOut 用户退出登录 217 func UserSignOut(c *gin.Context) { 218 util.DeleteSession(c, "user_id") 219 c.JSON(200, serializer.Response{}) 220 } 221 222 // UserMe 获取当前登录的用户 223 func UserMe(c *gin.Context) { 224 currUser := CurrentUser(c) 225 res := serializer.BuildUserResponse(*currUser) 226 c.JSON(200, res) 227 } 228 229 // UserStorage 获取用户的存储信息 230 func UserStorage(c *gin.Context) { 231 currUser := CurrentUser(c) 232 res := serializer.BuildUserStorageResponse(*currUser) 233 c.JSON(200, res) 234 } 235 236 // UserTasks 获取任务队列 237 func UserTasks(c *gin.Context) { 238 var service user.SettingListService 239 if err := c.ShouldBindQuery(&service); err == nil { 240 res := service.ListTasks(c, CurrentUser(c)) 241 c.JSON(200, res) 242 } else { 243 c.JSON(200, ErrorResponse(err)) 244 } 245 } 246 247 // UserSetting 获取用户设定 248 func UserSetting(c *gin.Context) { 249 var service user.SettingService 250 if err := c.ShouldBindUri(&service); err == nil { 251 res := service.Settings(c, CurrentUser(c)) 252 c.JSON(200, res) 253 } else { 254 c.JSON(200, ErrorResponse(err)) 255 } 256 } 257 258 // UseGravatar 设定头像使用全球通用 259 func UseGravatar(c *gin.Context) { 260 u := CurrentUser(c) 261 if err := u.Update(map[string]interface{}{"avatar": "gravatar"}); err != nil { 262 c.JSON(200, serializer.Err(serializer.CodeDBError, "无法更新头像", err)) 263 return 264 } 265 c.JSON(200, serializer.Response{}) 266 } 267 268 // UploadAvatar 从文件上传头像 269 func UploadAvatar(c *gin.Context) { 270 // 取得头像上传大小限制 271 maxSize := model.GetIntSetting("avatar_size", 2097152) 272 if c.Request.ContentLength == -1 || c.Request.ContentLength > int64(maxSize) { 273 request.BlackHole(c.Request.Body) 274 c.JSON(200, serializer.Err(serializer.CodeFileTooLarge, "", nil)) 275 return 276 } 277 278 // 取得上传的文件 279 file, err := c.FormFile("avatar") 280 if err != nil { 281 c.JSON(200, serializer.ParamErr("Failed to read avatar file data", err)) 282 return 283 } 284 285 // 初始化头像 286 r, err := file.Open() 287 if err != nil { 288 c.JSON(200, serializer.ParamErr("Failed to read avatar file data", err)) 289 return 290 } 291 avatar, err := thumb.NewThumbFromFile(r, file.Filename) 292 if err != nil { 293 c.JSON(200, serializer.ParamErr("Invalid image", err)) 294 return 295 } 296 297 // 创建头像 298 u := CurrentUser(c) 299 err = avatar.CreateAvatar(u.ID) 300 if err != nil { 301 c.JSON(200, serializer.Err(serializer.CodeIOFailed, "Failed to create avatar file", err)) 302 return 303 } 304 305 // 保存头像标记 306 if err := u.Update(map[string]interface{}{ 307 "avatar": "file", 308 }); err != nil { 309 c.JSON(200, serializer.DBErr("Failed to update avatar attribute", err)) 310 return 311 } 312 313 c.JSON(200, serializer.Response{}) 314 } 315 316 // GetUserAvatar 获取用户头像 317 func GetUserAvatar(c *gin.Context) { 318 var service user.AvatarService 319 if err := c.ShouldBindUri(&service); err == nil { 320 res := service.Get(c) 321 if res.Code == -301 { 322 // 重定向到gravatar 323 c.Redirect(301, res.Data.(string)) 324 } 325 } else { 326 c.JSON(200, ErrorResponse(err)) 327 } 328 } 329 330 // UpdateOption 更改用户设定 331 func UpdateOption(c *gin.Context) { 332 var service user.SettingUpdateService 333 if err := c.ShouldBindUri(&service); err == nil { 334 var ( 335 subService user.OptionsChangeHandler 336 subErr error 337 ) 338 339 switch service.Option { 340 case "nick": 341 subService = &user.ChangerNick{} 342 case "homepage": 343 subService = &user.HomePage{} 344 case "password": 345 subService = &user.PasswordChange{} 346 case "2fa": 347 subService = &user.Enable2FA{} 348 case "authn": 349 subService = &user.DeleteWebAuthn{} 350 case "theme": 351 subService = &user.ThemeChose{} 352 default: 353 subService = &user.ChangerNick{} 354 } 355 356 subErr = c.ShouldBindJSON(subService) 357 if subErr != nil { 358 c.JSON(200, ErrorResponse(subErr)) 359 return 360 } 361 362 res := subService.Update(c, CurrentUser(c)) 363 c.JSON(200, res) 364 365 } else { 366 c.JSON(200, ErrorResponse(err)) 367 } 368 } 369 370 // UserInit2FA 初始化二步验证 371 func UserInit2FA(c *gin.Context) { 372 var service user.SettingService 373 if err := c.ShouldBindUri(&service); err == nil { 374 res := service.Init2FA(c, CurrentUser(c)) 375 c.JSON(200, res) 376 } else { 377 c.JSON(200, ErrorResponse(err)) 378 } 379 } 380 381 // UserPrepareCopySession generates URL for copy session 382 func UserPrepareCopySession(c *gin.Context) { 383 var service user.CopySessionService 384 res := service.Prepare(c, CurrentUser(c)) 385 c.JSON(200, res) 386 387 } 388 389 // UserPerformCopySession copy to create new session or refresh current session 390 func UserPerformCopySession(c *gin.Context) { 391 var service user.CopySessionService 392 if err := c.ShouldBindUri(&service); err == nil { 393 res := service.Copy(c) 394 c.JSON(200, res) 395 } else { 396 c.JSON(200, ErrorResponse(err)) 397 } 398 }