239 lines
7.9 KiB
Go
239 lines
7.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
b64 "encoding/base64"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
|
|
cvdata "github.com/jesusperez/cvdata"
|
|
utils "github.com/jesusperez/datautils"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
func create_password(val string) (string,error) {
|
|
txtVal,err := b64.StdEncoding.DecodeString(val)
|
|
if err != nil {
|
|
return "",err
|
|
}
|
|
pswd,err := encrypt(string(txtVal), string(CRYPTKEY))
|
|
if err != nil {
|
|
return "",err
|
|
}
|
|
return pswd,nil
|
|
}
|
|
func write_accounts(newAccounts map[string]Account,rtenv *RouteEnv) error {
|
|
strdata, err := yaml.Marshal(newAccounts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if res := utils.WriteData(string(strdata),rtenv.Cfg.UsersPath) ; res != nil {
|
|
return res
|
|
}
|
|
acc,err := loadUsersAccounts(rtenv.Cfg.UsersPath)
|
|
if err != nil {
|
|
return err
|
|
} else {
|
|
rtenv.Users = acc
|
|
}
|
|
return nil
|
|
}
|
|
func get_recoveryaccess_handle(c *gin.Context, rtenv *RouteEnv) {
|
|
// fmt.Printf("context: %+v\n", c)
|
|
target := c.Params.ByName(rtenv.Cfg.Routes["recoveryaccess"].Param)
|
|
if target == "-" {
|
|
target = "main"
|
|
}
|
|
var user Account
|
|
if val, ok := rtenv.Users.Accounts[target]; ok {
|
|
user = val
|
|
} else {
|
|
fmt.Printf("Error Recovery access for (%s) %s\n", user.Id, target)
|
|
logRoute(c,rtenv,"Recovery access send_invitation",fmt.Sprintf("get %s: read error",user.Id), fmt.Sprintf("get %s: %s",user.Id,target))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed recovery request"})
|
|
return
|
|
}
|
|
uuid := uuid.NewString()
|
|
uuid = strings.Replace(uuid,"-","",-1)
|
|
appDB[uuid]=AppData{
|
|
Data: user,
|
|
Expire: time.Now().Add(5*time.Minute).Format(time.RFC3339),
|
|
}
|
|
reqData := UsersRecover{
|
|
Id: uuid,
|
|
Data: user,
|
|
}
|
|
accept_langs := strings.Split(c.Request.Header.Get("Accept-Language"),";")
|
|
langs := strings.Split(accept_langs[0], ",")
|
|
tplPath := fmt.Sprintf("%s/%s_%s",rtenv.Cfg.TplsMailPath,langs[0],rtenv.Cfg.TplsMail["recovery"].Path)
|
|
if ! utils.ExistsPath(tplPath) {
|
|
tplPath = fmt.Sprintf("%s/%s",rtenv.Cfg.TplsMailPath,rtenv.Cfg.TplsMail["recovery"].Path)
|
|
if ! utils.ExistsPath(tplPath) {
|
|
c.JSON(http.StatusNotAcceptable, gin.H{"error": "no template found"})
|
|
return
|
|
}
|
|
}
|
|
request := Mail{
|
|
Sender: rtenv.Cfg.MailFrom,
|
|
To: []string{user.Email},
|
|
Cc: []string{},
|
|
Bcc: []string{},
|
|
Subject: fmt.Sprintf("Recovery access"),
|
|
Body: bytes.Buffer{},
|
|
}
|
|
err := email(rtenv.Cfg, "text", tplPath, "", "", request,reqData)
|
|
if err == nil {
|
|
fmt.Printf("Recovery access for (%s): %s\n",user.Id, target)
|
|
logRoute(c,rtenv,"Recovery access",fmt.Sprintf("get %s: %s",user.Id,target), fmt.Sprintf("get %s: %s",user.Id,target))
|
|
c.JSON(http.StatusOK, gin.H{"received": "ok"})
|
|
} else {
|
|
fmt.Printf("Error Recovery access for (%s) %s: %v\n", user.Id, target, err)
|
|
logRoute(c,rtenv,"Recovery access send_invitation",fmt.Sprintf("get %s: read error %v ",user.Id,err), fmt.Sprintf("get %s: %s",user.Id,target))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed recovery request"})
|
|
}
|
|
}
|
|
func post_recoveryaccess_handle(c *gin.Context, rtenv *RouteEnv) {
|
|
var postdata UsersRecoveryPost
|
|
err := c.BindJSON(&postdata)
|
|
if err != nil {
|
|
fmt.Printf("err: %+v\n", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed recovery user"})
|
|
return
|
|
}
|
|
if len(postdata.Id) == 0 {
|
|
c.JSON(http.StatusNotAcceptable, gin.H{"info": "error recovery user"})
|
|
return
|
|
}
|
|
valid := false
|
|
var user Account
|
|
if data, ok := appDB[postdata.Id]; ok {
|
|
user = data.Data.(Account)
|
|
res,err := time.Parse(time.RFC3339,data.Expire)
|
|
if err == nil {
|
|
if res.After(time.Now()) {
|
|
valid = true
|
|
}
|
|
}
|
|
}
|
|
if !valid {
|
|
fmt.Printf("Error Recovery access for %s\n", user.Id)
|
|
logRoute(c,rtenv,"Recovery access send_invitation",fmt.Sprintf("get %s: read error %v ",user.Id,err), fmt.Sprintf("get %s",user.Id))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed recovery request"})
|
|
return
|
|
}
|
|
accounts,err := loadUsersData(rtenv.Cfg.UsersPath)
|
|
if err != nil {
|
|
fmt.Printf("err: %+v\n", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed recovery user"})
|
|
return
|
|
}
|
|
if account, ok := accounts[user.Id]; ok {
|
|
newAccounts := accounts
|
|
pswd,err := create_password(postdata.Val)
|
|
if err != nil {
|
|
fmt.Printf("Error data: %v",err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed user data %s",user.Id)})
|
|
}
|
|
account.Passwd = pswd
|
|
newAccounts[user.Id] = account
|
|
errwrite := write_accounts(newAccounts,rtenv)
|
|
if err != nil {
|
|
logRoute(c,rtenv,"post_recoveryaccess",fmt.Sprintf("Error post save recoveryaccess %s",user.Id), fmt.Sprintf("error: %+v",errwrite))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save user data")})
|
|
return
|
|
}
|
|
delete(appDB,postdata.Id)
|
|
logRoute(c,rtenv,"post_recoveryaccess",fmt.Sprintf("post %s: users",postdata.Id), fmt.Sprintf("post recovery access: %s",user.Id))
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
} else {
|
|
fmt.Printf("err: %+v\n", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed recovery user"})
|
|
return
|
|
}
|
|
}
|
|
func post_newuser_handle(c *gin.Context, rtenv *RouteEnv) {
|
|
var postdata NewUserData
|
|
err := c.BindJSON(&postdata)
|
|
if err != nil {
|
|
fmt.Printf("err: %+v\n", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save info"})
|
|
return
|
|
}
|
|
fmt.Printf("postdata: %+v\n", postdata)
|
|
if len(postdata.Username) == 0 || len(postdata.Passwd) == 0 {
|
|
c.JSON(http.StatusNotAcceptable, gin.H{"info": "error info"})
|
|
return
|
|
}
|
|
pswd, err := create_password(postdata.Passwd)
|
|
if err != nil {
|
|
fmt.Printf("Error data: %v",err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed user data %s",postdata.Username)})
|
|
}
|
|
newUser := Account{
|
|
Username: postdata.Username,
|
|
Email: postdata.Email,
|
|
Passwd: pswd,
|
|
Data: postdata.Username,
|
|
Web: true,
|
|
Id: postdata.Username,
|
|
}
|
|
newAccounts,err := loadUsersData(rtenv.Cfg.UsersPath)
|
|
if err != nil {
|
|
fmt.Printf("err: %+v\n", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed recovery user"})
|
|
return
|
|
}
|
|
newAccounts[postdata.Username] = newUser
|
|
errwrite := write_accounts(newAccounts,rtenv)
|
|
if err != nil {
|
|
logRoute(c,rtenv,"post_newuser",fmt.Sprintf("Error post save newuser %s",postdata.Username), fmt.Sprintf("error: %+v",errwrite))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save user data")})
|
|
return
|
|
}
|
|
logRoute(c,rtenv,"post_newuser",fmt.Sprintf("post newuser: %s",postdata.Username), fmt.Sprintf("post newuser: %s",postdata.Username))
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
// c.IndentedJSON(http.StatusCreated, cvdata)
|
|
}
|
|
|
|
func post_usermodel_handle(c *gin.Context, rtenv *RouteEnv) {
|
|
var cvpost cvdata.CVPostData
|
|
role := rtenv.Cfg.AdminRole
|
|
err := c.BindJSON(&cvpost)
|
|
if err != nil {
|
|
fmt.Printf("err: %+v\n", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save info"})
|
|
return
|
|
}
|
|
if cvpost.U == "" || len(cvpost.Data) == 0 {
|
|
c.JSON(http.StatusNotAcceptable, gin.H{"info": "error info"})
|
|
return
|
|
}
|
|
// roles,_ := enforcer.GetRolesForUser(user)
|
|
hasRole,_ := rtenv.Enforcer.HasRoleForUser(cvpost.U, role)
|
|
fmt.Printf("%s (%s) %+v\n",cvpost.U, role, hasRole)
|
|
if !hasRole {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"})
|
|
return
|
|
}
|
|
keys,res := cvpost.Data.Write(rtenv.Cfg)
|
|
if res != nil {
|
|
logRoute(c,rtenv,"post_newuser",fmt.Sprintf("Error post %s: %s",cvpost.U,keys), fmt.Sprintf("error: %+v",res))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save info"})
|
|
return
|
|
}
|
|
if rtenv.Cfg.GenDist {
|
|
errModel := createRootModels(rtenv.Cfg)
|
|
if errModel != nil {
|
|
fmt.Printf("Error createRootModels: %v\n",errModel)
|
|
}
|
|
}
|
|
logRoute(c,rtenv,"post_newuser",fmt.Sprintf("post %s: %s",cvpost.U,keys), fmt.Sprintf("post %s: %s",cvpost.U,keys))
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
// c.IndentedJSON(http.StatusCreated, cvdata)
|
|
}
|
|
|