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  }