user.go 23 KB

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