11package user
22
33import (
4- "bytes"
5- "crypto/sha1"
6- "encoding/base64"
7- "encoding/hex"
84 "fmt"
5+ "net/http"
6+ "strings"
7+ "time"
8+
99 "github.com/0xJacky/Nginx-UI/api"
1010 "github.com/0xJacky/Nginx-UI/internal/crypto"
11+ "github.com/0xJacky/Nginx-UI/model"
1112 "github.com/0xJacky/Nginx-UI/query"
1213 "github.com/0xJacky/Nginx-UI/settings"
1314 "github.com/gin-gonic/gin"
1415 "github.com/pquerna/otp"
1516 "github.com/pquerna/otp/totp"
1617 "github.com/uozi-tech/cosy"
17- "image/jpeg"
18- "net/http"
19- "strings"
2018)
2119
2220func GenerateTOTP (c * gin.Context ) {
@@ -38,27 +36,9 @@ func GenerateTOTP(c *gin.Context) {
3836 return
3937 }
4038
41- qrCode , err := otpKey .Image (512 , 512 )
42- if err != nil {
43- api .ErrHandler (c , err )
44- return
45- }
46-
47- // Encode the image to a buffer
48- var buf []byte
49- buffer := bytes .NewBuffer (buf )
50- err = jpeg .Encode (buffer , qrCode , nil )
51- if err != nil {
52- fmt .Println ("Error encoding image:" , err )
53- return
54- }
55-
56- // Convert the buffer to a base64 string
57- base64Str := "data:image/jpeg;base64," + base64 .StdEncoding .EncodeToString (buffer .Bytes ())
58-
5939 c .JSON (http .StatusOK , gin.H {
60- "secret" : otpKey .Secret (),
61- "qr_code " : base64Str ,
40+ "secret" : otpKey .Secret (),
41+ "url " : otpKey . URL () ,
6242 })
6343}
6444
@@ -78,22 +58,22 @@ func EnrollTOTP(c *gin.Context) {
7858 return
7959 }
8060
81- var json struct {
61+ var twoFA struct {
8262 Secret string `json:"secret" binding:"required"`
8363 Passcode string `json:"passcode" binding:"required"`
8464 }
85- if ! cosy .BindAndValid (c , & json ) {
65+ if ! cosy .BindAndValid (c , & twoFA ) {
8666 return
8767 }
8868
89- if ok := totp .Validate (json .Passcode , json .Secret ); ! ok {
69+ if ok := totp .Validate (twoFA .Passcode , twoFA .Secret ); ! ok {
9070 c .JSON (http .StatusNotAcceptable , gin.H {
9171 "message" : "Invalid passcode" ,
9272 })
9373 return
9474 }
9575
96- ciphertext , err := crypto .AesEncrypt ([]byte (json .Secret ))
76+ ciphertext , err := crypto .AesEncrypt ([]byte (twoFA .Secret ))
9777 if err != nil {
9878 api .ErrHandler (c , err )
9979 return
@@ -106,37 +86,25 @@ func EnrollTOTP(c *gin.Context) {
10686 return
10787 }
10888
109- recoveryCode := sha1 .Sum (ciphertext )
89+ t := time .Now ().Unix ()
90+ recoveryCodes := model.RecoveryCodes {Codes : generateRecoveryCodes (16 ), LastViewed : & t }
91+ cUser .RecoveryCodes = recoveryCodes
92+ _ , err = u .Where (u .ID .Eq (cUser .ID )).Updates (cUser )
93+ if err != nil {
94+ api .ErrHandler (c , err )
95+ return
96+ }
11097
111- c .JSON (http .StatusOK , gin. H {
112- "message" : "ok" ,
113- "recovery_code" : hex . EncodeToString ( recoveryCode [:]) ,
98+ c .JSON (http .StatusOK , RecoveryCodesResponse {
99+ Message : "ok" ,
100+ RecoveryCodes : recoveryCodes ,
114101 })
115102}
116103
117104func ResetOTP (c * gin.Context ) {
118- var json struct {
119- RecoveryCode string `json:"recovery_code"`
120- }
121- if ! cosy .BindAndValid (c , & json ) {
122- return
123- }
124- recoverCode , err := hex .DecodeString (json .RecoveryCode )
125- if err != nil {
126- api .ErrHandler (c , err )
127- return
128- }
129105 cUser := api .CurrentUser (c )
130- k := sha1 .Sum (cUser .OTPSecret )
131- if ! bytes .Equal (k [:], recoverCode ) {
132- c .JSON (http .StatusBadRequest , gin.H {
133- "message" : "Invalid recovery code" ,
134- })
135- return
136- }
137-
138106 u := query .User
139- _ , err = u .Where (u .ID .Eq (cUser .ID )).UpdateSimple (u .OTPSecret .Null ())
107+ _ , err : = u .Where (u .ID .Eq (cUser .ID )).UpdateSimple (u .OTPSecret . Null (), u . RecoveryCodes .Null ())
140108 if err != nil {
141109 api .ErrHandler (c , err )
142110 return
0 commit comments