user.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. package controller
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "net/url"
  7. "one-api/common"
  8. "one-api/dto"
  9. "one-api/logger"
  10. "one-api/model"
  11. "one-api/setting"
  12. "strconv"
  13. "strings"
  14. "sync"
  15. "one-api/constant"
  16. "github.com/gin-contrib/sessions"
  17. "github.com/gin-gonic/gin"
  18. )
  19. type LoginRequest struct {
  20. Username string `json:"username"`
  21. Password string `json:"password"`
  22. }
  23. func Login(c *gin.Context) {
  24. if !common.PasswordLoginEnabled {
  25. c.JSON(http.StatusOK, gin.H{
  26. "message": "管理员关闭了密码登录",
  27. "success": false,
  28. })
  29. return
  30. }
  31. var loginRequest LoginRequest
  32. err := json.NewDecoder(c.Request.Body).Decode(&loginRequest)
  33. if err != nil {
  34. c.JSON(http.StatusOK, gin.H{
  35. "message": "无效的参数",
  36. "success": false,
  37. })
  38. return
  39. }
  40. username := loginRequest.Username
  41. password := loginRequest.Password
  42. if username == "" || password == "" {
  43. c.JSON(http.StatusOK, gin.H{
  44. "message": "无效的参数",
  45. "success": false,
  46. })
  47. return
  48. }
  49. user := model.User{
  50. Username: username,
  51. Password: password,
  52. }
  53. err = user.ValidateAndFill()
  54. if err != nil {
  55. c.JSON(http.StatusOK, gin.H{
  56. "message": err.Error(),
  57. "success": false,
  58. })
  59. return
  60. }
  61. // 检查是否启用2FA
  62. if model.IsTwoFAEnabled(user.Id) {
  63. // 设置pending session,等待2FA验证
  64. session := sessions.Default(c)
  65. session.Set("pending_username", user.Username)
  66. session.Set("pending_user_id", user.Id)
  67. err := session.Save()
  68. if err != nil {
  69. c.JSON(http.StatusOK, gin.H{
  70. "message": "无法保存会话信息,请重试",
  71. "success": false,
  72. })
  73. return
  74. }
  75. c.JSON(http.StatusOK, gin.H{
  76. "message": "请输入两步验证码",
  77. "success": true,
  78. "data": map[string]interface{}{
  79. "require_2fa": true,
  80. },
  81. })
  82. return
  83. }
  84. setupLogin(&user, c)
  85. }
  86. // setup session & cookies and then return user info
  87. func setupLogin(user *model.User, c *gin.Context) {
  88. session := sessions.Default(c)
  89. session.Set("id", user.Id)
  90. session.Set("username", user.Username)
  91. session.Set("role", user.Role)
  92. session.Set("status", user.Status)
  93. session.Set("group", user.Group)
  94. err := session.Save()
  95. if err != nil {
  96. c.JSON(http.StatusOK, gin.H{
  97. "message": "无法保存会话信息,请重试",
  98. "success": false,
  99. })
  100. return
  101. }
  102. cleanUser := model.User{
  103. Id: user.Id,
  104. Username: user.Username,
  105. DisplayName: user.DisplayName,
  106. Role: user.Role,
  107. Status: user.Status,
  108. Group: user.Group,
  109. }
  110. c.JSON(http.StatusOK, gin.H{
  111. "message": "",
  112. "success": true,
  113. "data": cleanUser,
  114. })
  115. }
  116. func Logout(c *gin.Context) {
  117. session := sessions.Default(c)
  118. session.Clear()
  119. err := session.Save()
  120. if err != nil {
  121. c.JSON(http.StatusOK, gin.H{
  122. "message": err.Error(),
  123. "success": false,
  124. })
  125. return
  126. }
  127. c.JSON(http.StatusOK, gin.H{
  128. "message": "",
  129. "success": true,
  130. })
  131. }
  132. func Register(c *gin.Context) {
  133. if !common.RegisterEnabled {
  134. c.JSON(http.StatusOK, gin.H{
  135. "message": "管理员关闭了新用户注册",
  136. "success": false,
  137. })
  138. return
  139. }
  140. if !common.PasswordRegisterEnabled {
  141. c.JSON(http.StatusOK, gin.H{
  142. "message": "管理员关闭了通过密码进行注册,请使用第三方账户验证的形式进行注册",
  143. "success": false,
  144. })
  145. return
  146. }
  147. var user model.User
  148. err := json.NewDecoder(c.Request.Body).Decode(&user)
  149. if err != nil {
  150. c.JSON(http.StatusOK, gin.H{
  151. "success": false,
  152. "message": "无效的参数",
  153. })
  154. return
  155. }
  156. if err := common.Validate.Struct(&user); err != nil {
  157. c.JSON(http.StatusOK, gin.H{
  158. "success": false,
  159. "message": "输入不合法 " + err.Error(),
  160. })
  161. return
  162. }
  163. if common.EmailVerificationEnabled {
  164. if user.Email == "" || user.VerificationCode == "" {
  165. c.JSON(http.StatusOK, gin.H{
  166. "success": false,
  167. "message": "管理员开启了邮箱验证,请输入邮箱地址和验证码",
  168. })
  169. return
  170. }
  171. if !common.VerifyCodeWithKey(user.Email, user.VerificationCode, common.EmailVerificationPurpose) {
  172. c.JSON(http.StatusOK, gin.H{
  173. "success": false,
  174. "message": "验证码错误或已过期",
  175. })
  176. return
  177. }
  178. }
  179. exist, err := model.CheckUserExistOrDeleted(user.Username, user.Email)
  180. if err != nil {
  181. c.JSON(http.StatusOK, gin.H{
  182. "success": false,
  183. "message": "数据库错误,请稍后重试",
  184. })
  185. common.SysLog(fmt.Sprintf("CheckUserExistOrDeleted error: %v", err))
  186. return
  187. }
  188. if exist {
  189. c.JSON(http.StatusOK, gin.H{
  190. "success": false,
  191. "message": "用户名已存在,或已注销",
  192. })
  193. return
  194. }
  195. affCode := user.AffCode // this code is the inviter's code, not the user's own code
  196. inviterId, _ := model.GetUserIdByAffCode(affCode)
  197. cleanUser := model.User{
  198. Username: user.Username,
  199. Password: user.Password,
  200. DisplayName: user.Username,
  201. InviterId: inviterId,
  202. }
  203. if common.EmailVerificationEnabled {
  204. cleanUser.Email = user.Email
  205. }
  206. if err := cleanUser.Insert(inviterId); err != nil {
  207. common.ApiError(c, err)
  208. return
  209. }
  210. // 获取插入后的用户ID
  211. var insertedUser model.User
  212. if err := model.DB.Where("username = ?", cleanUser.Username).First(&insertedUser).Error; err != nil {
  213. c.JSON(http.StatusOK, gin.H{
  214. "success": false,
  215. "message": "用户注册失败或用户ID获取失败",
  216. })
  217. return
  218. }
  219. // 生成默认令牌
  220. if constant.GenerateDefaultToken {
  221. key, err := common.GenerateKey()
  222. if err != nil {
  223. c.JSON(http.StatusOK, gin.H{
  224. "success": false,
  225. "message": "生成默认令牌失败",
  226. })
  227. common.SysLog("failed to generate token key: " + err.Error())
  228. return
  229. }
  230. // 生成默认令牌
  231. token := model.Token{
  232. UserId: insertedUser.Id, // 使用插入后的用户ID
  233. Name: cleanUser.Username + "的初始令牌",
  234. Key: key,
  235. CreatedTime: common.GetTimestamp(),
  236. AccessedTime: common.GetTimestamp(),
  237. ExpiredTime: -1, // 永不过期
  238. RemainQuota: 500000, // 示例额度
  239. UnlimitedQuota: true,
  240. ModelLimitsEnabled: false,
  241. }
  242. if setting.DefaultUseAutoGroup {
  243. token.Group = "auto"
  244. }
  245. if err := token.Insert(); err != nil {
  246. c.JSON(http.StatusOK, gin.H{
  247. "success": false,
  248. "message": "创建默认令牌失败",
  249. })
  250. return
  251. }
  252. }
  253. c.JSON(http.StatusOK, gin.H{
  254. "success": true,
  255. "message": "",
  256. })
  257. return
  258. }
  259. func GetAllUsers(c *gin.Context) {
  260. pageInfo := common.GetPageQuery(c)
  261. users, total, err := model.GetAllUsers(pageInfo)
  262. if err != nil {
  263. common.ApiError(c, err)
  264. return
  265. }
  266. pageInfo.SetTotal(int(total))
  267. pageInfo.SetItems(users)
  268. common.ApiSuccess(c, pageInfo)
  269. return
  270. }
  271. func SearchUsers(c *gin.Context) {
  272. keyword := c.Query("keyword")
  273. group := c.Query("group")
  274. pageInfo := common.GetPageQuery(c)
  275. users, total, err := model.SearchUsers(keyword, group, pageInfo.GetStartIdx(), pageInfo.GetPageSize())
  276. if err != nil {
  277. common.ApiError(c, err)
  278. return
  279. }
  280. pageInfo.SetTotal(int(total))
  281. pageInfo.SetItems(users)
  282. common.ApiSuccess(c, pageInfo)
  283. return
  284. }
  285. func GetUser(c *gin.Context) {
  286. id, err := strconv.Atoi(c.Param("id"))
  287. if err != nil {
  288. common.ApiError(c, err)
  289. return
  290. }
  291. user, err := model.GetUserById(id, false)
  292. if err != nil {
  293. common.ApiError(c, err)
  294. return
  295. }
  296. myRole := c.GetInt("role")
  297. if myRole <= user.Role && myRole != common.RoleRootUser {
  298. c.JSON(http.StatusOK, gin.H{
  299. "success": false,
  300. "message": "无权获取同级或更高等级用户的信息",
  301. })
  302. return
  303. }
  304. c.JSON(http.StatusOK, gin.H{
  305. "success": true,
  306. "message": "",
  307. "data": user,
  308. })
  309. return
  310. }
  311. func GenerateAccessToken(c *gin.Context) {
  312. id := c.GetInt("id")
  313. user, err := model.GetUserById(id, true)
  314. if err != nil {
  315. common.ApiError(c, err)
  316. return
  317. }
  318. // get rand int 28-32
  319. randI := common.GetRandomInt(4)
  320. key, err := common.GenerateRandomKey(29 + randI)
  321. if err != nil {
  322. c.JSON(http.StatusOK, gin.H{
  323. "success": false,
  324. "message": "生成失败",
  325. })
  326. common.SysLog("failed to generate key: " + err.Error())
  327. return
  328. }
  329. user.SetAccessToken(key)
  330. if model.DB.Where("access_token = ?", user.AccessToken).First(user).RowsAffected != 0 {
  331. c.JSON(http.StatusOK, gin.H{
  332. "success": false,
  333. "message": "请重试,系统生成的 UUID 竟然重复了!",
  334. })
  335. return
  336. }
  337. if err := user.Update(false); err != nil {
  338. common.ApiError(c, err)
  339. return
  340. }
  341. c.JSON(http.StatusOK, gin.H{
  342. "success": true,
  343. "message": "",
  344. "data": user.AccessToken,
  345. })
  346. return
  347. }
  348. type TransferAffQuotaRequest struct {
  349. Quota int `json:"quota" binding:"required"`
  350. }
  351. func TransferAffQuota(c *gin.Context) {
  352. id := c.GetInt("id")
  353. user, err := model.GetUserById(id, true)
  354. if err != nil {
  355. common.ApiError(c, err)
  356. return
  357. }
  358. tran := TransferAffQuotaRequest{}
  359. if err := c.ShouldBindJSON(&tran); err != nil {
  360. common.ApiError(c, err)
  361. return
  362. }
  363. err = user.TransferAffQuotaToQuota(tran.Quota)
  364. if err != nil {
  365. c.JSON(http.StatusOK, gin.H{
  366. "success": false,
  367. "message": "划转失败 " + err.Error(),
  368. })
  369. return
  370. }
  371. c.JSON(http.StatusOK, gin.H{
  372. "success": true,
  373. "message": "划转成功",
  374. })
  375. }
  376. func GetAffCode(c *gin.Context) {
  377. id := c.GetInt("id")
  378. user, err := model.GetUserById(id, true)
  379. if err != nil {
  380. common.ApiError(c, err)
  381. return
  382. }
  383. if user.AffCode == "" {
  384. user.AffCode = common.GetRandomString(4)
  385. if err := user.Update(false); err != nil {
  386. c.JSON(http.StatusOK, gin.H{
  387. "success": false,
  388. "message": err.Error(),
  389. })
  390. return
  391. }
  392. }
  393. c.JSON(http.StatusOK, gin.H{
  394. "success": true,
  395. "message": "",
  396. "data": user.AffCode,
  397. })
  398. return
  399. }
  400. func GetSelf(c *gin.Context) {
  401. id := c.GetInt("id")
  402. user, err := model.GetUserById(id, false)
  403. if err != nil {
  404. common.ApiError(c, err)
  405. return
  406. }
  407. // Hide admin remarks: set to empty to trigger omitempty tag, ensuring the remark field is not included in JSON returned to regular users
  408. user.Remark = ""
  409. c.JSON(http.StatusOK, gin.H{
  410. "success": true,
  411. "message": "",
  412. "data": user,
  413. })
  414. return
  415. }
  416. func GetUserModels(c *gin.Context) {
  417. id, err := strconv.Atoi(c.Param("id"))
  418. if err != nil {
  419. id = c.GetInt("id")
  420. }
  421. user, err := model.GetUserCache(id)
  422. if err != nil {
  423. common.ApiError(c, err)
  424. return
  425. }
  426. groups := setting.GetUserUsableGroups(user.Group)
  427. var models []string
  428. for group := range groups {
  429. for _, g := range model.GetGroupEnabledModels(group) {
  430. if !common.StringsContains(models, g) {
  431. models = append(models, g)
  432. }
  433. }
  434. }
  435. c.JSON(http.StatusOK, gin.H{
  436. "success": true,
  437. "message": "",
  438. "data": models,
  439. })
  440. return
  441. }
  442. func UpdateUser(c *gin.Context) {
  443. var updatedUser model.User
  444. err := json.NewDecoder(c.Request.Body).Decode(&updatedUser)
  445. if err != nil || updatedUser.Id == 0 {
  446. c.JSON(http.StatusOK, gin.H{
  447. "success": false,
  448. "message": "无效的参数",
  449. })
  450. return
  451. }
  452. if updatedUser.Password == "" {
  453. updatedUser.Password = "$I_LOVE_U" // make Validator happy :)
  454. }
  455. if err := common.Validate.Struct(&updatedUser); err != nil {
  456. c.JSON(http.StatusOK, gin.H{
  457. "success": false,
  458. "message": "输入不合法 " + err.Error(),
  459. })
  460. return
  461. }
  462. originUser, err := model.GetUserById(updatedUser.Id, false)
  463. if err != nil {
  464. common.ApiError(c, err)
  465. return
  466. }
  467. myRole := c.GetInt("role")
  468. if myRole <= originUser.Role && myRole != common.RoleRootUser {
  469. c.JSON(http.StatusOK, gin.H{
  470. "success": false,
  471. "message": "无权更新同权限等级或更高权限等级的用户信息",
  472. })
  473. return
  474. }
  475. if myRole <= updatedUser.Role && myRole != common.RoleRootUser {
  476. c.JSON(http.StatusOK, gin.H{
  477. "success": false,
  478. "message": "无权将其他用户权限等级提升到大于等于自己的权限等级",
  479. })
  480. return
  481. }
  482. if updatedUser.Password == "$I_LOVE_U" {
  483. updatedUser.Password = "" // rollback to what it should be
  484. }
  485. updatePassword := updatedUser.Password != ""
  486. if err := updatedUser.Edit(updatePassword); err != nil {
  487. common.ApiError(c, err)
  488. return
  489. }
  490. if originUser.Quota != updatedUser.Quota {
  491. model.RecordLog(originUser.Id, model.LogTypeManage, fmt.Sprintf("管理员将用户额度从 %s修改为 %s", logger.LogQuota(originUser.Quota), logger.LogQuota(updatedUser.Quota)))
  492. }
  493. c.JSON(http.StatusOK, gin.H{
  494. "success": true,
  495. "message": "",
  496. })
  497. return
  498. }
  499. func UpdateSelf(c *gin.Context) {
  500. var user model.User
  501. err := json.NewDecoder(c.Request.Body).Decode(&user)
  502. if err != nil {
  503. c.JSON(http.StatusOK, gin.H{
  504. "success": false,
  505. "message": "无效的参数",
  506. })
  507. return
  508. }
  509. if user.Password == "" {
  510. user.Password = "$I_LOVE_U" // make Validator happy :)
  511. }
  512. if err := common.Validate.Struct(&user); err != nil {
  513. c.JSON(http.StatusOK, gin.H{
  514. "success": false,
  515. "message": "输入不合法 " + err.Error(),
  516. })
  517. return
  518. }
  519. cleanUser := model.User{
  520. Id: c.GetInt("id"),
  521. Username: user.Username,
  522. Password: user.Password,
  523. DisplayName: user.DisplayName,
  524. }
  525. if user.Password == "$I_LOVE_U" {
  526. user.Password = "" // rollback to what it should be
  527. cleanUser.Password = ""
  528. }
  529. updatePassword, err := checkUpdatePassword(user.OriginalPassword, user.Password, cleanUser.Id)
  530. if err != nil {
  531. common.ApiError(c, err)
  532. return
  533. }
  534. if err := cleanUser.Update(updatePassword); err != nil {
  535. common.ApiError(c, err)
  536. return
  537. }
  538. c.JSON(http.StatusOK, gin.H{
  539. "success": true,
  540. "message": "",
  541. })
  542. return
  543. }
  544. func checkUpdatePassword(originalPassword string, newPassword string, userId int) (updatePassword bool, err error) {
  545. var currentUser *model.User
  546. currentUser, err = model.GetUserById(userId, true)
  547. if err != nil {
  548. return
  549. }
  550. if !common.ValidatePasswordAndHash(originalPassword, currentUser.Password) {
  551. err = fmt.Errorf("原密码错误")
  552. return
  553. }
  554. if newPassword == "" {
  555. return
  556. }
  557. updatePassword = true
  558. return
  559. }
  560. func DeleteUser(c *gin.Context) {
  561. id, err := strconv.Atoi(c.Param("id"))
  562. if err != nil {
  563. common.ApiError(c, err)
  564. return
  565. }
  566. originUser, err := model.GetUserById(id, false)
  567. if err != nil {
  568. common.ApiError(c, err)
  569. return
  570. }
  571. myRole := c.GetInt("role")
  572. if myRole <= originUser.Role {
  573. c.JSON(http.StatusOK, gin.H{
  574. "success": false,
  575. "message": "无权删除同权限等级或更高权限等级的用户",
  576. })
  577. return
  578. }
  579. err = model.HardDeleteUserById(id)
  580. if err != nil {
  581. c.JSON(http.StatusOK, gin.H{
  582. "success": true,
  583. "message": "",
  584. })
  585. return
  586. }
  587. }
  588. func DeleteSelf(c *gin.Context) {
  589. id := c.GetInt("id")
  590. user, _ := model.GetUserById(id, false)
  591. if user.Role == common.RoleRootUser {
  592. c.JSON(http.StatusOK, gin.H{
  593. "success": false,
  594. "message": "不能删除超级管理员账户",
  595. })
  596. return
  597. }
  598. err := model.DeleteUserById(id)
  599. if err != nil {
  600. common.ApiError(c, err)
  601. return
  602. }
  603. c.JSON(http.StatusOK, gin.H{
  604. "success": true,
  605. "message": "",
  606. })
  607. return
  608. }
  609. func CreateUser(c *gin.Context) {
  610. var user model.User
  611. err := json.NewDecoder(c.Request.Body).Decode(&user)
  612. user.Username = strings.TrimSpace(user.Username)
  613. if err != nil || user.Username == "" || user.Password == "" {
  614. c.JSON(http.StatusOK, gin.H{
  615. "success": false,
  616. "message": "无效的参数",
  617. })
  618. return
  619. }
  620. if err := common.Validate.Struct(&user); err != nil {
  621. c.JSON(http.StatusOK, gin.H{
  622. "success": false,
  623. "message": "输入不合法 " + err.Error(),
  624. })
  625. return
  626. }
  627. if user.DisplayName == "" {
  628. user.DisplayName = user.Username
  629. }
  630. myRole := c.GetInt("role")
  631. if user.Role >= myRole {
  632. c.JSON(http.StatusOK, gin.H{
  633. "success": false,
  634. "message": "无法创建权限大于等于自己的用户",
  635. })
  636. return
  637. }
  638. // Even for admin users, we cannot fully trust them!
  639. cleanUser := model.User{
  640. Username: user.Username,
  641. Password: user.Password,
  642. DisplayName: user.DisplayName,
  643. }
  644. if err := cleanUser.Insert(0); err != nil {
  645. common.ApiError(c, err)
  646. return
  647. }
  648. c.JSON(http.StatusOK, gin.H{
  649. "success": true,
  650. "message": "",
  651. })
  652. return
  653. }
  654. type ManageRequest struct {
  655. Id int `json:"id"`
  656. Action string `json:"action"`
  657. }
  658. // ManageUser Only admin user can do this
  659. func ManageUser(c *gin.Context) {
  660. var req ManageRequest
  661. err := json.NewDecoder(c.Request.Body).Decode(&req)
  662. if err != nil {
  663. c.JSON(http.StatusOK, gin.H{
  664. "success": false,
  665. "message": "无效的参数",
  666. })
  667. return
  668. }
  669. user := model.User{
  670. Id: req.Id,
  671. }
  672. // Fill attributes
  673. model.DB.Unscoped().Where(&user).First(&user)
  674. if user.Id == 0 {
  675. c.JSON(http.StatusOK, gin.H{
  676. "success": false,
  677. "message": "用户不存在",
  678. })
  679. return
  680. }
  681. myRole := c.GetInt("role")
  682. if myRole <= user.Role && myRole != common.RoleRootUser {
  683. c.JSON(http.StatusOK, gin.H{
  684. "success": false,
  685. "message": "无权更新同权限等级或更高权限等级的用户信息",
  686. })
  687. return
  688. }
  689. switch req.Action {
  690. case "disable":
  691. user.Status = common.UserStatusDisabled
  692. if user.Role == common.RoleRootUser {
  693. c.JSON(http.StatusOK, gin.H{
  694. "success": false,
  695. "message": "无法禁用超级管理员用户",
  696. })
  697. return
  698. }
  699. case "enable":
  700. user.Status = common.UserStatusEnabled
  701. case "delete":
  702. if user.Role == common.RoleRootUser {
  703. c.JSON(http.StatusOK, gin.H{
  704. "success": false,
  705. "message": "无法删除超级管理员用户",
  706. })
  707. return
  708. }
  709. if err := user.Delete(); err != nil {
  710. c.JSON(http.StatusOK, gin.H{
  711. "success": false,
  712. "message": err.Error(),
  713. })
  714. return
  715. }
  716. case "promote":
  717. if myRole != common.RoleRootUser {
  718. c.JSON(http.StatusOK, gin.H{
  719. "success": false,
  720. "message": "普通管理员用户无法提升其他用户为管理员",
  721. })
  722. return
  723. }
  724. if user.Role >= common.RoleAdminUser {
  725. c.JSON(http.StatusOK, gin.H{
  726. "success": false,
  727. "message": "该用户已经是管理员",
  728. })
  729. return
  730. }
  731. user.Role = common.RoleAdminUser
  732. case "demote":
  733. if user.Role == common.RoleRootUser {
  734. c.JSON(http.StatusOK, gin.H{
  735. "success": false,
  736. "message": "无法降级超级管理员用户",
  737. })
  738. return
  739. }
  740. if user.Role == common.RoleCommonUser {
  741. c.JSON(http.StatusOK, gin.H{
  742. "success": false,
  743. "message": "该用户已经是普通用户",
  744. })
  745. return
  746. }
  747. user.Role = common.RoleCommonUser
  748. }
  749. if err := user.Update(false); err != nil {
  750. common.ApiError(c, err)
  751. return
  752. }
  753. clearUser := model.User{
  754. Role: user.Role,
  755. Status: user.Status,
  756. }
  757. c.JSON(http.StatusOK, gin.H{
  758. "success": true,
  759. "message": "",
  760. "data": clearUser,
  761. })
  762. return
  763. }
  764. func EmailBind(c *gin.Context) {
  765. email := c.Query("email")
  766. code := c.Query("code")
  767. if !common.VerifyCodeWithKey(email, code, common.EmailVerificationPurpose) {
  768. c.JSON(http.StatusOK, gin.H{
  769. "success": false,
  770. "message": "验证码错误或已过期",
  771. })
  772. return
  773. }
  774. session := sessions.Default(c)
  775. id := session.Get("id")
  776. user := model.User{
  777. Id: id.(int),
  778. }
  779. err := user.FillUserById()
  780. if err != nil {
  781. common.ApiError(c, err)
  782. return
  783. }
  784. user.Email = email
  785. // no need to check if this email already taken, because we have used verification code to check it
  786. err = user.Update(false)
  787. if err != nil {
  788. common.ApiError(c, err)
  789. return
  790. }
  791. c.JSON(http.StatusOK, gin.H{
  792. "success": true,
  793. "message": "",
  794. })
  795. return
  796. }
  797. type topUpRequest struct {
  798. Key string `json:"key"`
  799. }
  800. var topUpLock = sync.Mutex{}
  801. func TopUp(c *gin.Context) {
  802. topUpLock.Lock()
  803. defer topUpLock.Unlock()
  804. req := topUpRequest{}
  805. err := c.ShouldBindJSON(&req)
  806. if err != nil {
  807. common.ApiError(c, err)
  808. return
  809. }
  810. id := c.GetInt("id")
  811. quota, err := model.Redeem(req.Key, id)
  812. if err != nil {
  813. common.ApiError(c, err)
  814. return
  815. }
  816. c.JSON(http.StatusOK, gin.H{
  817. "success": true,
  818. "message": "",
  819. "data": quota,
  820. })
  821. return
  822. }
  823. type UpdateUserSettingRequest struct {
  824. QuotaWarningType string `json:"notify_type"`
  825. QuotaWarningThreshold float64 `json:"quota_warning_threshold"`
  826. WebhookUrl string `json:"webhook_url,omitempty"`
  827. WebhookSecret string `json:"webhook_secret,omitempty"`
  828. NotificationEmail string `json:"notification_email,omitempty"`
  829. AcceptUnsetModelRatioModel bool `json:"accept_unset_model_ratio_model"`
  830. RecordIpLog bool `json:"record_ip_log"`
  831. }
  832. func UpdateUserSetting(c *gin.Context) {
  833. var req UpdateUserSettingRequest
  834. if err := c.ShouldBindJSON(&req); err != nil {
  835. c.JSON(http.StatusOK, gin.H{
  836. "success": false,
  837. "message": "无效的参数",
  838. })
  839. return
  840. }
  841. // 验证预警类型
  842. if req.QuotaWarningType != dto.NotifyTypeEmail && req.QuotaWarningType != dto.NotifyTypeWebhook {
  843. c.JSON(http.StatusOK, gin.H{
  844. "success": false,
  845. "message": "无效的预警类型",
  846. })
  847. return
  848. }
  849. // 验证预警阈值
  850. if req.QuotaWarningThreshold <= 0 {
  851. c.JSON(http.StatusOK, gin.H{
  852. "success": false,
  853. "message": "预警阈值必须大于0",
  854. })
  855. return
  856. }
  857. // 如果是webhook类型,验证webhook地址
  858. if req.QuotaWarningType == dto.NotifyTypeWebhook {
  859. if req.WebhookUrl == "" {
  860. c.JSON(http.StatusOK, gin.H{
  861. "success": false,
  862. "message": "Webhook地址不能为空",
  863. })
  864. return
  865. }
  866. // 验证URL格式
  867. if _, err := url.ParseRequestURI(req.WebhookUrl); err != nil {
  868. c.JSON(http.StatusOK, gin.H{
  869. "success": false,
  870. "message": "无效的Webhook地址",
  871. })
  872. return
  873. }
  874. }
  875. // 如果是邮件类型,验证邮箱地址
  876. if req.QuotaWarningType == dto.NotifyTypeEmail && req.NotificationEmail != "" {
  877. // 验证邮箱格式
  878. if !strings.Contains(req.NotificationEmail, "@") {
  879. c.JSON(http.StatusOK, gin.H{
  880. "success": false,
  881. "message": "无效的邮箱地址",
  882. })
  883. return
  884. }
  885. }
  886. userId := c.GetInt("id")
  887. user, err := model.GetUserById(userId, true)
  888. if err != nil {
  889. common.ApiError(c, err)
  890. return
  891. }
  892. // 构建设置
  893. settings := dto.UserSetting{
  894. NotifyType: req.QuotaWarningType,
  895. QuotaWarningThreshold: req.QuotaWarningThreshold,
  896. AcceptUnsetRatioModel: req.AcceptUnsetModelRatioModel,
  897. RecordIpLog: req.RecordIpLog,
  898. }
  899. // 如果是webhook类型,添加webhook相关设置
  900. if req.QuotaWarningType == dto.NotifyTypeWebhook {
  901. settings.WebhookUrl = req.WebhookUrl
  902. if req.WebhookSecret != "" {
  903. settings.WebhookSecret = req.WebhookSecret
  904. }
  905. }
  906. // 如果提供了通知邮箱,添加到设置中
  907. if req.QuotaWarningType == dto.NotifyTypeEmail && req.NotificationEmail != "" {
  908. settings.NotificationEmail = req.NotificationEmail
  909. }
  910. // 更新用户设置
  911. user.SetSetting(settings)
  912. if err := user.Update(false); err != nil {
  913. c.JSON(http.StatusOK, gin.H{
  914. "success": false,
  915. "message": "更新设置失败: " + err.Error(),
  916. })
  917. return
  918. }
  919. c.JSON(http.StatusOK, gin.H{
  920. "success": true,
  921. "message": "设置已更新",
  922. })
  923. }