package main import ( "bytes" b64 "encoding/base64" "encoding/json" "fmt" "net/http" "strings" "github.com/gin-gonic/gin" utils "github.com/jesusperez/datautils" "gopkg.in/yaml.v2" ) func send_invitation_handle(c *gin.Context, rtenv *RouteEnv) { role := rtenv.Cfg.AdminRole user,res := user_has_role(nil,c,rtenv,role) if !res { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"}) return } var sendData PostInvitation err := c.BindJSON(&sendData) if err != nil { fmt.Printf("err: %+v\n", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save info"}) return } if len(sendData.Data.Email) == 0 { c.JSON(http.StatusNotAcceptable, gin.H{"error": "no data found"}) return } 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["newuser"].Path) if ! utils.ExistsPath(tplPath) { tplPath = fmt.Sprintf("%s/%s",rtenv.Cfg.TplsMailPath,rtenv.Cfg.TplsMail["newuser"].Path) if ! utils.ExistsPath(tplPath) { c.JSON(http.StatusNotAcceptable, gin.H{"error": "no template found"}) return } } target := rtenv.Cfg.MailFrom bodyData := sendData if len(sendData.Data.Expire) > 0 { bodyData.Data.Expire = fmt.Sprintf("Expire: %s",sendData.Data.Expire) } request := Mail{ Sender: target, To: []string{sendData.Data.Email}, Cc: []string{}, Bcc: []string{}, Subject: fmt.Sprintf("Invitation "), Body: bytes.Buffer{}, } err = email(rtenv.Cfg, "text", tplPath, "", "", request,bodyData) if err == nil { fmt.Printf("Invitation send from (%s): %s\n",user.UserName, target) logRoute(c,rtenv,"send_inivitation",fmt.Sprintf("get %s: %s",user.UserName,target), fmt.Sprintf("get %s: %s",user.UserName,target)) c.JSON(http.StatusOK, sendData) } else { fmt.Printf("Error send invitation from (%s) %s: %v\n", user.UserName, target, err) logRoute(c,rtenv,"send_invitation",fmt.Sprintf("get %s: read error %v ",user.UserName,err), fmt.Sprintf("get %s: %s",user.UserName,target)) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to send invitation"}) } } func get_invitation_handle(c *gin.Context, rtenv *RouteEnv) { id := c.Params.ByName(rtenv.Cfg.Routes["invitation"].Param) usrsInvitations,err := getUsersInvitations(rtenv.Cfg.InvitationsPath,true) if err != nil { logRoute(c,rtenv,"users",fmt.Sprintf("get /invitation error %v",err),fmt.Sprintf("get invitation %s",id)) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to get invitation %s",id)}) return } if val, ok := usrsInvitations[id]; ok { invitation, valid, needSync := checkUserInvitation(id, usrsInvitations[id], 1) if (needSync) { allInvitations, err := loadUsersInvitations(rtenv.Cfg.InvitationsPath) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to validate invitation %s",id)}) return } allInvitations[id]=invitation strdata, yamlerr := yaml.Marshal(allInvitations) if yamlerr != nil { fmt.Printf("Error parse invitations yaml %s: %v",rtenv.Cfg.InvitationsPath,yamlerr) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to sync invitations %s",id)}) return } if res := utils.WriteData(string(strdata),rtenv.Cfg.InvitationsPath) ; res != nil { logRoute(c,rtenv,"post_users",fmt.Sprintf("Error write invitations: %s",id), fmt.Sprintf("error: %+v",res)) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to sync invitation %s",id)}) return } } if !valid { logRoute(c,rtenv,"users",fmt.Sprintf("get /invitation error %v",err),fmt.Sprintf("get invitation not valid %s",id)) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to validate invitation %s",id)}) return } tkn := "" if rtenv.Cfg.UseAuthz { data := &User{ UserName: val.Email, UUID: id, Data: "Invitation", FirstName: "", LastName: "", } tkn,err = makeTokenString(rtenv,data) if err != nil { fmt.Printf("tkn err: %+v\n", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to auth"}) return } } logRoute(c,rtenv,"users",fmt.Sprintf("get /invitation %s",id),fmt.Sprintf("get invitation %s (%s) %s",val.Email,val.Role,val.Data)) data := NewUserData{ Email: val.Email, Role: val.Role, Data: val.Data } strdata,err := json.Marshal(data) if err == nil { c.JSON(http.StatusOK, gin.H{"data": b64.StdEncoding.EncodeToString(strdata),"auth": tkn}) return } else { c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to confirm invitation %s",id)}) return } } else { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invitation not found"}) } } func get_users_handle(c *gin.Context, rtenv *RouteEnv) { idusr := rtenv.AuthMiddleware.IdentityHandler(c) user, okusr := idusr.(*User) if !okusr || len(user.UserName) == 0 { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"}) return } role := rtenv.Cfg.AdminRole if _,res := user_has_role(user,c,rtenv,role); !res { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"}) return } usersData := &UsersData { UsersData: "", ModelsData: "", Invitations: "", AuthzModel: "", AuthzPolicy: "", } if utils.ExistsPath(rtenv.Cfg.UsersPath) { data,err := loadPath(rtenv.Cfg.UsersPath) if err != nil { logRoute(c,rtenv,"config",fmt.Sprintf("get /users error %v",err),fmt.Sprintf("get userspath %s (%s)",user.UserName,role)) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load users data"}) return } usersData.UsersData = b64.StdEncoding.EncodeToString(data) } if utils.ExistsPath(rtenv.Cfg.UsersModelsPath) { data,err := loadPath(rtenv.Cfg.UsersModelsPath) if err != nil { logRoute(c,rtenv,"config",fmt.Sprintf("get /users error %v",err),fmt.Sprintf("get usersmodels %s (%s)",user.UserName,role)) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load users models"}) return } usersData.ModelsData = b64.StdEncoding.EncodeToString(data) } if utils.ExistsPath(rtenv.Cfg.InvitationsPath) { data,err := loadPath(rtenv.Cfg.InvitationsPath) if err != nil { logRoute(c,rtenv,"config",fmt.Sprintf("get /users error %v",err),fmt.Sprintf("get invitations %s (%s)",user.UserName,role)) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load users invitations"}) return } usersData.Invitations = b64.StdEncoding.EncodeToString(data) } if rtenv.Cfg.UseAuthz { if utils.ExistsPath(rtenv.Cfg.AuthzModel) { data,err := loadPath(rtenv.Cfg.AuthzModel) if err != nil { logRoute(c,rtenv,"config",fmt.Sprintf("get /users error %v",err),fmt.Sprintf("get authzmodels %s (%s)",user.UserName,role)) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load authz models"}) return } usersData.AuthzModel = b64.StdEncoding.EncodeToString(data) } if utils.ExistsPath(rtenv.Cfg.AuthzPolicy) { data,err := loadPath(rtenv.Cfg.AuthzPolicy) if err != nil { logRoute(c,rtenv,"config",fmt.Sprintf("get /users error %v",err),fmt.Sprintf("get authzpolizy %s (%s)",user.UserName,role)) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load authz policy"}) return } usersData.AuthzPolicy = b64.StdEncoding.EncodeToString(data) } } logRoute(c,rtenv,"config","get /users",fmt.Sprintf("get users %s (%s)",user.UserName,role)) c.JSON(http.StatusOK, gin.H{"data": usersData}) } func save_users_data(saveInfo SaveDataInfo,c *gin.Context,rtenv *RouteEnv) bool { path := fmt.Sprintf("%s%s",saveInfo.Prfx, saveInfo.Path) data,err := b64.StdEncoding.DecodeString(saveInfo.Data) if err != nil { fmt.Printf("Error save %s: %v",path,err) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save %s",saveInfo.Title)}) return false } var accounts map[string]Account err = yaml.Unmarshal([]byte(data), &accounts) if err != nil { fmt.Printf("Error parse yaml %s: %v",path,err) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save %s",saveInfo.Title)}) return false } prfx := rtenv.Cfg.PasswdEnc var allUsers = map[string]Account{} for key, item := range accounts { if strings.HasPrefix(item.Passwd,"enc:") { txtPasswd := strings.Replace(item.Passwd,prfx,"",-1) passwd,err := encrypt(txtPasswd, string(CRYPTKEY)) if err == nil { item.Passwd = passwd allUsers[key] = item } } else { allUsers[key] = item } } strdata, yamlerr := yaml.Marshal(allUsers) if yamlerr != nil { fmt.Printf("Error parse yaml %s: %v",path,yamlerr) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save %s",saveInfo.Title)}) return false } if res := utils.WriteData(string(strdata),path) ; res != nil { logRoute(c,rtenv,"post_users",fmt.Sprintf("Error post %s: %s",saveInfo.Title,saveInfo.Id), fmt.Sprintf("error: %+v",res)) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save %s",saveInfo.Title)}) return false } return true } func save_file_data(saveInfo SaveDataInfo,c *gin.Context,rtenv *RouteEnv) bool { path := fmt.Sprintf("%s%s",saveInfo.Prfx, saveInfo.Path) data,err := b64.StdEncoding.DecodeString(saveInfo.Data) if err != nil { fmt.Printf("Error save %s: %v",path,err) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save %s",saveInfo.Title)}) return false } if res := utils.WriteData(string(data),path) ; res != nil { logRoute(c,rtenv,"post_users",fmt.Sprintf("Error post %s: %s",saveInfo.Title,saveInfo.Id), fmt.Sprintf("error: %+v",res)) c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to save %s",saveInfo.Title)}) return false } return true } func post_users_handle(c *gin.Context, rtenv *RouteEnv) { var postdata UsersDataPost role := rtenv.Cfg.AdminRole err := c.BindJSON(&postdata) if err != nil { fmt.Printf("err: %+v\n", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save users"}) return } if len(postdata.Id) == 0 { c.JSON(http.StatusNotAcceptable, gin.H{"info": "error users"}) return } hasRole,_ := rtenv.Enforcer.HasRoleForUser(postdata.Id,role) // fmt.Printf("post users: %s (%s) %+v\n",postdata.Id, role, hasRole) if !hasRole { logRoute(c,rtenv,"post_users",fmt.Sprintf("post %s: has no role",postdata.Id), fmt.Sprintf("post %s",postdata.Id)) c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"}) return } savedList := "" if len(postdata.Data.UsersData) > 0 { saveInfo := SaveDataInfo{ Title: "users", Data: postdata.Data.UsersData, Id: postdata.Id, Path: rtenv.Cfg.UsersPath, Prfx: "new_", } if !save_users_data(saveInfo,c,rtenv) { return } savedList = "usersData" } if len(postdata.Data.ModelsData) > 0 { saveInfo := SaveDataInfo{ Title: "users models", Data: postdata.Data.ModelsData, Id: postdata.Id, Path: rtenv.Cfg.UsersModelsPath, Prfx: "new_", } if !save_file_data(saveInfo,c,rtenv) { return } savedList = fmt.Sprintf("%s,modelsData",savedList) } if len(postdata.Data.Invitations) > 0 { saveInfo := SaveDataInfo{ Title: "users invitations", Data: postdata.Data.Invitations, Id: postdata.Id, Path: rtenv.Cfg.InvitationsPath, Prfx: "new_", } if !save_file_data(saveInfo,c,rtenv) { return } savedList = fmt.Sprintf("%s,invitations",savedList) } if rtenv.Cfg.UseAuthz { if len(postdata.Data.AuthzModel) > 0 { saveInfo := SaveDataInfo{ Title: "users authz models", Data: postdata.Data.AuthzModel, Id: postdata.Id, Path: rtenv.Cfg.AuthzModel, Prfx: "new_", } if !save_file_data(saveInfo,c,rtenv) { return } savedList = fmt.Sprintf("%s,authzModels",savedList) } if len(postdata.Data.AuthzPolicy) > 0 { saveInfo := SaveDataInfo{ Title: "users authz policy", Data: postdata.Data.AuthzPolicy, Id: postdata.Id, Path: rtenv.Cfg.AuthzPolicy, Prfx: "new_", } if !save_file_data(saveInfo,c,rtenv) { return } savedList = fmt.Sprintf("%s,authzPolicy",savedList) } } logRoute(c,rtenv,"post_users",fmt.Sprintf("post %s: users",postdata.Id), fmt.Sprintf("post %s: %s",postdata.Id,savedList)) c.JSON(http.StatusOK, gin.H{"status": "ok"}) }