api_user.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. package admin
  2. import (
  3. "bytes"
  4. "encoding/base64"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "net/http"
  9. "net/url"
  10. "strconv"
  11. "strings"
  12. "text/template"
  13. "time"
  14. "github.com/bjdgyc/anylink/base"
  15. "github.com/bjdgyc/anylink/dbdata"
  16. "github.com/bjdgyc/anylink/sessdata"
  17. "github.com/skip2/go-qrcode"
  18. )
  19. func UserList(w http.ResponseWriter, r *http.Request) {
  20. _ = r.ParseForm()
  21. prefix := r.FormValue("prefix")
  22. pageS := r.FormValue("page")
  23. page, _ := strconv.Atoi(pageS)
  24. if page < 1 {
  25. page = 1
  26. }
  27. var (
  28. pageSize = dbdata.PageSize
  29. count int
  30. datas []dbdata.User
  31. err error
  32. )
  33. // 查询前缀匹配
  34. if len(prefix) > 0 {
  35. count = dbdata.CountPrefix("username", prefix, &dbdata.User{})
  36. err = dbdata.Prefix("username", prefix, &datas, pageSize, 1)
  37. } else {
  38. count = dbdata.CountAll(&dbdata.User{})
  39. err = dbdata.Find(&datas, pageSize, page)
  40. }
  41. if err != nil && !dbdata.CheckErrNotFound(err) {
  42. RespError(w, RespInternalErr, err)
  43. return
  44. }
  45. data := map[string]interface{}{
  46. "count": count,
  47. "page_size": pageSize,
  48. "datas": datas,
  49. }
  50. RespSucess(w, data)
  51. }
  52. func UserDetail(w http.ResponseWriter, r *http.Request) {
  53. _ = r.ParseForm()
  54. idS := r.FormValue("id")
  55. id, _ := strconv.Atoi(idS)
  56. if id < 1 {
  57. RespError(w, RespParamErr, "用户名错误")
  58. return
  59. }
  60. var user dbdata.User
  61. err := dbdata.One("Id", id, &user)
  62. if err != nil {
  63. RespError(w, RespInternalErr, err)
  64. return
  65. }
  66. RespSucess(w, user)
  67. }
  68. func UserSet(w http.ResponseWriter, r *http.Request) {
  69. _ = r.ParseForm()
  70. body, err := io.ReadAll(r.Body)
  71. if err != nil {
  72. RespError(w, RespInternalErr, err)
  73. return
  74. }
  75. defer r.Body.Close()
  76. data := &dbdata.User{}
  77. err = json.Unmarshal(body, data)
  78. if err != nil {
  79. RespError(w, RespInternalErr, err)
  80. return
  81. }
  82. err = dbdata.SetUser(data)
  83. if err != nil {
  84. RespError(w, RespInternalErr, err)
  85. return
  86. }
  87. // 发送邮件
  88. if data.SendEmail {
  89. err = userAccountMail(data)
  90. if err != nil {
  91. RespError(w, RespInternalErr, err)
  92. return
  93. }
  94. }
  95. //修改用户资料后执行过期用户检测
  96. sessdata.CloseUserLimittimeSession()
  97. RespSucess(w, nil)
  98. }
  99. func UserDel(w http.ResponseWriter, r *http.Request) {
  100. _ = r.ParseForm()
  101. idS := r.FormValue("id")
  102. id, _ := strconv.Atoi(idS)
  103. if id < 1 {
  104. RespError(w, RespParamErr, "用户id错误")
  105. return
  106. }
  107. user := dbdata.User{Id: id}
  108. err := dbdata.Del(&user)
  109. if err != nil {
  110. RespError(w, RespInternalErr, err)
  111. return
  112. }
  113. RespSucess(w, nil)
  114. }
  115. func UserOtpQr(w http.ResponseWriter, r *http.Request) {
  116. _ = r.ParseForm()
  117. b64S := r.FormValue("b64")
  118. idS := r.FormValue("id")
  119. id, _ := strconv.Atoi(idS)
  120. var b64 bool
  121. if b64S == "1" {
  122. b64 = true
  123. }
  124. data, err := userOtpQr(id, b64)
  125. if err != nil {
  126. base.Error(err)
  127. }
  128. io.WriteString(w, data)
  129. }
  130. func userOtpQr(uid int, b64 bool) (string, error) {
  131. var user dbdata.User
  132. err := dbdata.One("Id", uid, &user)
  133. if err != nil {
  134. return "", err
  135. }
  136. issuer := url.QueryEscape(base.Cfg.Issuer)
  137. qrstr := fmt.Sprintf("otpauth://totp/%s:%s?issuer=%s&secret=%s", issuer, user.Email, issuer, user.OtpSecret)
  138. qr, _ := qrcode.New(qrstr, qrcode.High)
  139. if b64 {
  140. data, err := qr.PNG(300)
  141. if err != nil {
  142. return "", err
  143. }
  144. s := base64.StdEncoding.EncodeToString(data)
  145. return s, nil
  146. }
  147. buf := bytes.NewBuffer(nil)
  148. err = qr.Write(300, buf)
  149. return buf.String(), err
  150. }
  151. // 在线用户
  152. func UserOnline(w http.ResponseWriter, r *http.Request) {
  153. datas := sessdata.OnlineSess()
  154. data := map[string]interface{}{
  155. "count": len(datas),
  156. "page_size": dbdata.PageSize,
  157. "datas": datas,
  158. }
  159. RespSucess(w, data)
  160. }
  161. func UserOffline(w http.ResponseWriter, r *http.Request) {
  162. _ = r.ParseForm()
  163. token := r.FormValue("token")
  164. sessdata.CloseSess(token, dbdata.UserLogoutAdmin)
  165. RespSucess(w, nil)
  166. }
  167. func UserReline(w http.ResponseWriter, r *http.Request) {
  168. _ = r.ParseForm()
  169. token := r.FormValue("token")
  170. sessdata.CloseCSess(token)
  171. RespSucess(w, nil)
  172. }
  173. type userAccountMailData struct {
  174. Issuer string
  175. LinkAddr string
  176. Group string
  177. Username string
  178. PinCode string
  179. OtpImg string
  180. OtpImgBase64 string
  181. }
  182. func userAccountMail(user *dbdata.User) error {
  183. // 平台通知
  184. htmlBody := `
  185. <!DOCTYPE html>
  186. <html lang="en">
  187. <head>
  188. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  189. <title>Hello AnyLink!</title>
  190. </head>
  191. <body>
  192. %s
  193. </body>
  194. </html>
  195. `
  196. dataOther := &dbdata.SettingOther{}
  197. err := dbdata.SettingGet(dataOther)
  198. if err != nil {
  199. base.Error(err)
  200. return err
  201. }
  202. htmlBody = fmt.Sprintf(htmlBody, dataOther.AccountMail)
  203. // fmt.Println(htmlBody)
  204. // token有效期3天
  205. expiresAt := time.Now().Unix() + 3600*24*3
  206. jwtData := map[string]interface{}{"id": user.Id}
  207. tokenString, err := SetJwtData(jwtData, expiresAt)
  208. if err != nil {
  209. return err
  210. }
  211. setting := &dbdata.SettingOther{}
  212. err = dbdata.SettingGet(setting)
  213. if err != nil {
  214. base.Error(err)
  215. return err
  216. }
  217. otpData, _ := userOtpQr(user.Id, true)
  218. data := userAccountMailData{
  219. LinkAddr: setting.LinkAddr,
  220. Group: strings.Join(user.Groups, ","),
  221. Username: user.Username,
  222. PinCode: user.PinCode,
  223. OtpImg: fmt.Sprintf("https://%s/otp_qr?id=%d&jwt=%s", setting.LinkAddr, user.Id, tokenString),
  224. OtpImgBase64: "data:image/png;base64," + otpData,
  225. }
  226. w := bytes.NewBufferString("")
  227. t, _ := template.New("auth_complete").Parse(htmlBody)
  228. err = t.Execute(w, data)
  229. if err != nil {
  230. return err
  231. }
  232. // fmt.Println(w.String())
  233. return SendMail(base.Cfg.Issuer+"平台通知", user.Email, w.String())
  234. }