84 lines
1.9 KiB
Go
84 lines
1.9 KiB
Go
package user
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
"math/rand"
|
|
|
|
"github.com/azukaar/cosmos-server/src/utils"
|
|
"github.com/pquerna/otp/totp"
|
|
)
|
|
|
|
func New2FA(w http.ResponseWriter, req *http.Request) {
|
|
if utils.LoggedInWeakOnly(w, req) != nil {
|
|
return
|
|
}
|
|
time.Sleep(time.Duration(rand.Float64()*2)*time.Second)
|
|
|
|
nickname := req.Header.Get("x-cosmos-user")
|
|
|
|
key, err := totp.Generate(totp.GenerateOpts{
|
|
Issuer: "Cosmos " + utils.GetMainConfig().HTTPConfig.Hostname,
|
|
AccountName: nickname,
|
|
})
|
|
|
|
if err != nil {
|
|
utils.Error("2FA: Cannot generate key", err)
|
|
utils.HTTPError(w, "2FA Error", http.StatusInternalServerError, "2FA001")
|
|
return
|
|
}
|
|
|
|
utils.Log("2FA: New key generated for " + nickname)
|
|
|
|
toSet := map[string]interface{}{
|
|
"MFAKey": key.Secret(),
|
|
"Was2FAVerified": false,
|
|
}
|
|
|
|
c, errCo := utils.GetCollection(utils.GetRootAppId(), "users")
|
|
if errCo != nil {
|
|
utils.Error("Database Connect", errCo)
|
|
utils.HTTPError(w, "Database", http.StatusInternalServerError, "DB001")
|
|
return
|
|
}
|
|
|
|
userInBase := utils.User{}
|
|
|
|
err = c.FindOne(nil, map[string]interface{}{
|
|
"Nickname": nickname,
|
|
}).Decode(&userInBase)
|
|
|
|
if err != nil {
|
|
utils.Error("UserGet: Error while getting user", err)
|
|
utils.HTTPError(w, "User Get Error", http.StatusInternalServerError, "UD001")
|
|
return
|
|
}
|
|
|
|
if(userInBase.MFAKey != "" && userInBase.Was2FAVerified) {
|
|
if utils.LoggedInOnly(w, req) != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
_, err = c.UpdateOne(nil, map[string]interface{}{
|
|
"Nickname": nickname,
|
|
}, map[string]interface{}{
|
|
"$set": toSet,
|
|
})
|
|
|
|
if err != nil {
|
|
utils.Error("2FA: Cannot update user", err)
|
|
utils.HTTPError(w, "2FA Error", http.StatusInternalServerError, "2FA002")
|
|
return
|
|
}
|
|
|
|
utils.Log("2FA: User " + nickname + " updated")
|
|
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"status": "OK",
|
|
"data": map[string]interface{}{
|
|
"key": key.URL(),
|
|
},
|
|
})
|
|
} |