servcvgen/handlers_user.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)
}