user.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. package controller
  2. import (
  3. "encoding/json"
  4. "github.com/gin-contrib/sessions"
  5. "github.com/gin-gonic/gin"
  6. "github.com/google/uuid"
  7. "message-pusher/common"
  8. "message-pusher/model"
  9. "net/http"
  10. "strconv"
  11. "strings"
  12. )
  13. type LoginRequest struct {
  14. Username string `json:"username"`
  15. Password string `json:"password"`
  16. }
  17. func Login(c *gin.Context) {
  18. if !common.PasswordLoginEnabled {
  19. c.JSON(http.StatusOK, gin.H{
  20. "message": "管理员关闭了密码登录",
  21. "success": false,
  22. })
  23. return
  24. }
  25. var loginRequest LoginRequest
  26. err := json.NewDecoder(c.Request.Body).Decode(&loginRequest)
  27. if err != nil {
  28. c.JSON(http.StatusOK, gin.H{
  29. "message": "无效的参数",
  30. "success": false,
  31. })
  32. return
  33. }
  34. username := loginRequest.Username
  35. password := loginRequest.Password
  36. if username == "" || password == "" {
  37. c.JSON(http.StatusOK, gin.H{
  38. "message": "无效的参数",
  39. "success": false,
  40. })
  41. return
  42. }
  43. user := model.User{
  44. Username: username,
  45. Password: password,
  46. }
  47. err = user.ValidateAndFill()
  48. if err != nil {
  49. c.JSON(http.StatusOK, gin.H{
  50. "message": err.Error(),
  51. "success": false,
  52. })
  53. return
  54. }
  55. setupLogin(&user, c)
  56. }
  57. // setup session & cookies and then return user info
  58. func setupLogin(user *model.User, c *gin.Context) {
  59. session := sessions.Default(c)
  60. session.Set("id", user.Id)
  61. session.Set("username", user.Username)
  62. session.Set("role", user.Role)
  63. session.Set("status", user.Status)
  64. err := session.Save()
  65. if err != nil {
  66. c.JSON(http.StatusOK, gin.H{
  67. "message": "无法保存会话信息,请重试",
  68. "success": false,
  69. })
  70. return
  71. }
  72. user.Password = ""
  73. user.Token = ""
  74. c.JSON(http.StatusOK, gin.H{
  75. "message": "",
  76. "success": true,
  77. "data": user,
  78. })
  79. }
  80. func Logout(c *gin.Context) {
  81. session := sessions.Default(c)
  82. session.Clear()
  83. err := session.Save()
  84. if err != nil {
  85. c.JSON(http.StatusOK, gin.H{
  86. "message": err.Error(),
  87. "success": false,
  88. })
  89. return
  90. }
  91. c.JSON(http.StatusOK, gin.H{
  92. "message": "",
  93. "success": true,
  94. })
  95. }
  96. func Register(c *gin.Context) {
  97. if !common.PasswordRegisterEnabled {
  98. c.JSON(http.StatusOK, gin.H{
  99. "message": "管理员关闭了新用户注册",
  100. "success": false,
  101. })
  102. return
  103. }
  104. var user model.User
  105. err := json.NewDecoder(c.Request.Body).Decode(&user)
  106. if err != nil {
  107. c.JSON(http.StatusOK, gin.H{
  108. "success": false,
  109. "message": "无效的参数",
  110. })
  111. return
  112. }
  113. if err := common.Validate.Struct(&user); err != nil {
  114. c.JSON(http.StatusOK, gin.H{
  115. "success": false,
  116. "message": "输入不合法 " + err.Error(),
  117. })
  118. return
  119. }
  120. if common.EmailVerificationEnabled {
  121. if user.Email == "" || user.VerificationCode == "" {
  122. c.JSON(http.StatusOK, gin.H{
  123. "success": false,
  124. "message": "管理员开启了邮箱验证,请输入邮箱地址和验证码",
  125. })
  126. return
  127. }
  128. if !common.VerifyCodeWithKey(user.Email, user.VerificationCode, common.EmailVerificationPurpose) {
  129. c.JSON(http.StatusOK, gin.H{
  130. "success": false,
  131. "message": "验证码错误!",
  132. })
  133. return
  134. }
  135. }
  136. cleanUser := model.User{
  137. Username: user.Username,
  138. Password: user.Password,
  139. DisplayName: user.Username,
  140. }
  141. if common.EmailVerificationEnabled {
  142. cleanUser.Email = user.Email
  143. }
  144. if err := cleanUser.Insert(); err != nil {
  145. c.JSON(http.StatusOK, gin.H{
  146. "success": false,
  147. "message": err.Error(),
  148. })
  149. return
  150. }
  151. c.JSON(http.StatusOK, gin.H{
  152. "success": true,
  153. "message": "",
  154. })
  155. return
  156. }
  157. func GetAllUsers(c *gin.Context) {
  158. users, err := model.GetAllUsers()
  159. if err != nil {
  160. c.JSON(http.StatusOK, gin.H{
  161. "success": false,
  162. "message": err.Error(),
  163. })
  164. return
  165. }
  166. c.JSON(http.StatusOK, gin.H{
  167. "success": true,
  168. "message": "",
  169. "data": users,
  170. })
  171. return
  172. }
  173. func SearchUsers(c *gin.Context) {
  174. keyword := c.Query("keyword")
  175. users, err := model.SearchUsers(keyword)
  176. if err != nil {
  177. c.JSON(http.StatusOK, gin.H{
  178. "success": false,
  179. "message": err.Error(),
  180. })
  181. return
  182. }
  183. c.JSON(http.StatusOK, gin.H{
  184. "success": true,
  185. "message": "",
  186. "data": users,
  187. })
  188. return
  189. }
  190. func GetUser(c *gin.Context) {
  191. id, err := strconv.Atoi(c.Param("id"))
  192. if err != nil {
  193. c.JSON(http.StatusOK, gin.H{
  194. "success": false,
  195. "message": err.Error(),
  196. })
  197. return
  198. }
  199. user, err := model.GetUserById(id, false)
  200. if err != nil {
  201. c.JSON(http.StatusOK, gin.H{
  202. "success": false,
  203. "message": err.Error(),
  204. })
  205. return
  206. }
  207. myRole := c.GetInt("role")
  208. if myRole <= user.Role {
  209. c.JSON(http.StatusOK, gin.H{
  210. "success": false,
  211. "message": "无权获取同级或更高等级用户的信息",
  212. })
  213. return
  214. }
  215. c.JSON(http.StatusOK, gin.H{
  216. "success": true,
  217. "message": "",
  218. "data": user,
  219. })
  220. return
  221. }
  222. func GenerateToken(c *gin.Context) {
  223. id := c.GetInt("id")
  224. user, err := model.GetUserById(id, true)
  225. if err != nil {
  226. c.JSON(http.StatusOK, gin.H{
  227. "success": false,
  228. "message": err.Error(),
  229. })
  230. return
  231. }
  232. user.Token = uuid.New().String()
  233. user.Token = strings.Replace(user.Token, "-", "", -1)
  234. if model.DB.Where("token = ?", user.Token).First(user).RowsAffected != 0 {
  235. c.JSON(http.StatusOK, gin.H{
  236. "success": false,
  237. "message": "请重试,系统生成的 UUID 竟然重复了!",
  238. })
  239. return
  240. }
  241. if err := user.Update(false); err != nil {
  242. c.JSON(http.StatusOK, gin.H{
  243. "success": false,
  244. "message": err.Error(),
  245. })
  246. return
  247. }
  248. c.JSON(http.StatusOK, gin.H{
  249. "success": true,
  250. "message": "",
  251. "data": user.Token,
  252. })
  253. return
  254. }
  255. func GetSelf(c *gin.Context) {
  256. id := c.GetInt("id")
  257. user, err := model.GetUserById(id, false)
  258. if err != nil {
  259. c.JSON(http.StatusOK, gin.H{
  260. "success": false,
  261. "message": err.Error(),
  262. })
  263. return
  264. }
  265. c.JSON(http.StatusOK, gin.H{
  266. "success": true,
  267. "message": "",
  268. "data": user,
  269. })
  270. return
  271. }
  272. func UpdateUser(c *gin.Context) {
  273. var updatedUser model.User
  274. err := json.NewDecoder(c.Request.Body).Decode(&updatedUser)
  275. if err != nil || updatedUser.Id == 0 {
  276. c.JSON(http.StatusOK, gin.H{
  277. "success": false,
  278. "message": "无效的参数",
  279. })
  280. return
  281. }
  282. if updatedUser.Password == "" {
  283. updatedUser.Password = "$I_LOVE_U" // make Validator happy :)
  284. }
  285. if err := common.Validate.Struct(&updatedUser); err != nil {
  286. c.JSON(http.StatusOK, gin.H{
  287. "success": false,
  288. "message": "输入不合法 " + err.Error(),
  289. })
  290. return
  291. }
  292. originUser, err := model.GetUserById(updatedUser.Id, false)
  293. if err != nil {
  294. c.JSON(http.StatusOK, gin.H{
  295. "success": false,
  296. "message": err.Error(),
  297. })
  298. return
  299. }
  300. myRole := c.GetInt("role")
  301. if myRole <= originUser.Role {
  302. c.JSON(http.StatusOK, gin.H{
  303. "success": false,
  304. "message": "无权更新同权限等级或更高权限等级的用户信息",
  305. })
  306. return
  307. }
  308. if myRole <= updatedUser.Role {
  309. c.JSON(http.StatusOK, gin.H{
  310. "success": false,
  311. "message": "无权将其他用户权限等级提升到大于等于自己的权限等级",
  312. })
  313. return
  314. }
  315. if updatedUser.Password == "$I_LOVE_U" {
  316. updatedUser.Password = "" // rollback to what it should be
  317. }
  318. updatePassword := updatedUser.Password != ""
  319. if err := updatedUser.Update(updatePassword); err != nil {
  320. c.JSON(http.StatusOK, gin.H{
  321. "success": false,
  322. "message": err.Error(),
  323. })
  324. return
  325. }
  326. c.JSON(http.StatusOK, gin.H{
  327. "success": true,
  328. "message": "",
  329. })
  330. return
  331. }
  332. func UpdateSelf(c *gin.Context) {
  333. var user model.User
  334. err := json.NewDecoder(c.Request.Body).Decode(&user)
  335. if err != nil {
  336. c.JSON(http.StatusOK, gin.H{
  337. "success": false,
  338. "message": "无效的参数",
  339. })
  340. return
  341. }
  342. if user.Password == "" {
  343. user.Password = "$I_LOVE_U" // make Validator happy :)
  344. }
  345. if err := common.Validate.Struct(&user); err != nil {
  346. c.JSON(http.StatusOK, gin.H{
  347. "success": false,
  348. "message": "输入不合法 " + err.Error(),
  349. })
  350. return
  351. }
  352. cleanUser := model.User{
  353. Id: c.GetInt("id"),
  354. Username: user.Username,
  355. Password: user.Password,
  356. DisplayName: user.DisplayName,
  357. Token: user.Token,
  358. }
  359. if cleanUser.Token == "" {
  360. cleanUser.Token = " " // this is because gorm will ignore zero value
  361. }
  362. if user.Password == "$I_LOVE_U" {
  363. user.Password = "" // rollback to what it should be
  364. cleanUser.Password = ""
  365. }
  366. updatePassword := user.Password != ""
  367. if err := cleanUser.Update(updatePassword); err != nil {
  368. c.JSON(http.StatusOK, gin.H{
  369. "success": false,
  370. "message": err.Error(),
  371. })
  372. return
  373. }
  374. c.JSON(http.StatusOK, gin.H{
  375. "success": true,
  376. "message": "",
  377. })
  378. return
  379. }
  380. func DeleteUser(c *gin.Context) {
  381. id, err := strconv.Atoi(c.Param("id"))
  382. if err != nil {
  383. c.JSON(http.StatusOK, gin.H{
  384. "success": false,
  385. "message": err.Error(),
  386. })
  387. return
  388. }
  389. originUser, err := model.GetUserById(id, false)
  390. if err != nil {
  391. c.JSON(http.StatusOK, gin.H{
  392. "success": false,
  393. "message": err.Error(),
  394. })
  395. return
  396. }
  397. myRole := c.GetInt("role")
  398. if myRole <= originUser.Role {
  399. c.JSON(http.StatusOK, gin.H{
  400. "success": false,
  401. "message": "无权删除同权限等级或更高权限等级的用户",
  402. })
  403. return
  404. }
  405. err = model.DeleteUserById(id)
  406. if err != nil {
  407. c.JSON(http.StatusOK, gin.H{
  408. "success": true,
  409. "message": "",
  410. })
  411. return
  412. }
  413. }
  414. func DeleteSelf(c *gin.Context) {
  415. id := c.GetInt("id")
  416. err := model.DeleteUserById(id)
  417. if err != nil {
  418. c.JSON(http.StatusOK, gin.H{
  419. "success": false,
  420. "message": err.Error(),
  421. })
  422. return
  423. }
  424. c.JSON(http.StatusOK, gin.H{
  425. "success": true,
  426. "message": "",
  427. })
  428. return
  429. }
  430. // CreateUser Only admin user can call this, so we can trust it
  431. func CreateUser(c *gin.Context) {
  432. var user model.User
  433. err := json.NewDecoder(c.Request.Body).Decode(&user)
  434. if err != nil || user.Username == "" || user.Password == "" {
  435. c.JSON(http.StatusOK, gin.H{
  436. "success": false,
  437. "message": "无效的参数",
  438. })
  439. return
  440. }
  441. if user.DisplayName == "" {
  442. user.DisplayName = user.Username
  443. }
  444. myRole := c.GetInt("role")
  445. if user.Role >= myRole {
  446. c.JSON(http.StatusOK, gin.H{
  447. "success": false,
  448. "message": "无法创建权限大于等于自己的用户",
  449. })
  450. return
  451. }
  452. if err := user.Insert(); err != nil {
  453. c.JSON(http.StatusOK, gin.H{
  454. "success": false,
  455. "message": err.Error(),
  456. })
  457. return
  458. }
  459. c.JSON(http.StatusOK, gin.H{
  460. "success": true,
  461. "message": "",
  462. })
  463. return
  464. }
  465. type ManageRequest struct {
  466. Username string `json:"username"`
  467. Action string `json:"action"`
  468. }
  469. // ManageUser Only admin user can do this
  470. func ManageUser(c *gin.Context) {
  471. var req ManageRequest
  472. err := json.NewDecoder(c.Request.Body).Decode(&req)
  473. if err != nil {
  474. c.JSON(http.StatusOK, gin.H{
  475. "success": false,
  476. "message": "无效的参数",
  477. })
  478. return
  479. }
  480. user := model.User{
  481. Username: req.Username,
  482. }
  483. // Fill attributes
  484. model.DB.Where(&user).First(&user)
  485. if user.Id == 0 {
  486. c.JSON(http.StatusOK, gin.H{
  487. "success": false,
  488. "message": "用户不存在",
  489. })
  490. return
  491. }
  492. myRole := c.GetInt("role")
  493. if myRole <= user.Role {
  494. c.JSON(http.StatusOK, gin.H{
  495. "success": false,
  496. "message": "无权更新同权限等级或更高权限等级的用户信息",
  497. })
  498. return
  499. }
  500. switch req.Action {
  501. case "disable":
  502. user.Status = common.UserStatusDisabled
  503. case "enable":
  504. user.Status = common.UserStatusEnabled
  505. case "delete":
  506. if err := user.Delete(); err != nil {
  507. c.JSON(http.StatusOK, gin.H{
  508. "success": false,
  509. "message": err.Error(),
  510. })
  511. return
  512. }
  513. case "promote":
  514. if myRole != common.RoleRootUser {
  515. c.JSON(http.StatusOK, gin.H{
  516. "success": false,
  517. "message": "普通管理员用户无法提升其他用户为管理员",
  518. })
  519. return
  520. }
  521. user.Role = common.RoleAdminUser
  522. case "demote":
  523. user.Role = common.RoleCommonUser
  524. }
  525. if err := user.Update(false); err != nil {
  526. c.JSON(http.StatusOK, gin.H{
  527. "success": false,
  528. "message": err.Error(),
  529. })
  530. return
  531. }
  532. c.JSON(http.StatusOK, gin.H{
  533. "success": true,
  534. "message": "",
  535. })
  536. return
  537. }
  538. func EmailBind(c *gin.Context) {
  539. email := c.Query("email")
  540. code := c.Query("code")
  541. if !common.VerifyCodeWithKey(email, code, common.EmailVerificationPurpose) {
  542. c.JSON(http.StatusOK, gin.H{
  543. "success": false,
  544. "message": "验证码错误!",
  545. })
  546. return
  547. }
  548. id := c.GetInt("id")
  549. user := model.User{
  550. Id: id,
  551. }
  552. user.FillUserById()
  553. user.Email = email
  554. // no need to check if this email already taken, because we have used verification code to check it
  555. err := user.Update(false)
  556. if err != nil {
  557. c.JSON(http.StatusOK, gin.H{
  558. "success": false,
  559. "message": err.Error(),
  560. })
  561. return
  562. }
  563. c.JSON(http.StatusOK, gin.H{
  564. "success": true,
  565. "message": "",
  566. })
  567. return
  568. }