first commit

This commit is contained in:
2021-11-02 11:25:21 +01:00
commit 0c861770a8
2162 changed files with 178285 additions and 0 deletions

107
controller/config.go Normal file
View File

@ -0,0 +1,107 @@
package controller
import (
"arno/skeletor/config"
"arno/skeletor/entity"
"arno/skeletor/repository"
"arno/skeletor/service"
"arno/skeletor/tool"
"net/http"
"github.com/martini-contrib/sessions"
"github.com/martini-contrib/render"
)
func ConfigList(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
var configs []entity.Config
mapconfigs := make(map[string]entity.Config)
mydb.Find(&configs)
for _, config := range configs {
mapconfigs[config.Id] = config
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": true,
"usecontainer": true,
"configs": mapconfigs,
}
r.HTML(200, "config/list", rendermap)
}
func ConfigRefresh(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
myconfig.Refresh(mydb)
r.Redirect(myconfig.AppRoutes["configlist"])
}
func ConfigUpdate(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, id string) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
var config entity.Config
result := mydb.First(&config, "id = ?", id)
if result.RowsAffected == 0 {
r.Redirect(myconfig.AppRoutes["configlist"])
}
if req.Method == http.MethodPost {
req.ParseForm()
value := req.Form.Get("value")
if value != config.Defaultvalue {
config.Value = value
} else {
config.Value = ""
}
mydb.Save(&config)
r.Redirect(myconfig.AppRoutes["configrefresh"])
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": true,
"usecontainer": true,
"config": config,
}
r.HTML(200, "config/edit", rendermap)
}
func ConfigDelete(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, id string) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
var config entity.Config
result := mydb.First(&config, "id = ?", id)
if result.RowsAffected == 0 {
r.Redirect(myconfig.AppRoutes["configlist"])
}
config.Value = config.Defaultvalue
mydb.Save(&config)
r.Redirect(myconfig.AppRoutes["configrefresh"])
}
func GetConfig(ctn *service.Container, id string) string {
mydb := repository.Must(ctn)
var myconfig entity.Config
mydb.First(&myconfig, "id = ?", id)
if myconfig.Value == "" {
return myconfig.Defaultvalue
} else {
return myconfig.Value
}
}

39
controller/home.go Normal file
View File

@ -0,0 +1,39 @@
package controller
import (
"arno/skeletor/config"
"arno/skeletor/service"
"arno/skeletor/tool"
"net/http"
"github.com/martini-contrib/render"
"github.com/martini-contrib/sessions"
)
func Home(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": false,
"usecontainer": true,
}
r.HTML(200, "home/home", rendermap)
}
func HomeConfig(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": true,
"usecontainer": true,
}
r.HTML(200, "home/home", rendermap)
}

130
controller/security.go Normal file
View File

@ -0,0 +1,130 @@
package controller
import (
"arno/skeletor/config"
"arno/skeletor/entity"
"arno/skeletor/repository"
"arno/skeletor/service"
"arno/skeletor/tool"
"net/http"
"strconv"
"github.com/martini-contrib/render"
"github.com/martini-contrib/sessions"
)
func SecurityFirewall(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, level int) int {
myconfig := config.Must(ctn)
tmp := session.Get("Login")
login := ""
if tmp != nil {
login = tmp.(string)
}
tmp = session.Get("Role")
role := 100
if tmp != nil {
rolestr := tmp.(string)
role, _ = strconv.Atoi(rolestr)
}
// Si l'application est privé et que l'utilisateur n'est pas connecté on indique une redirection vers la mire de login
if myconfig.AppPrivate && login == "" {
return 2
}
// Si l'utilisateur n'a pas le niveau requis pour visualiser la page
if role > level {
// Si l'application est public et que le niveau requis est au minimum un niveau user on indique une redirection vers la mire de login
// Sinon on redirige vers la page d'accueil
if login == "" && level <= 50 {
return 2
} else {
return 1
}
}
return 0
}
func SecurityRedirect(ctn *service.Container, req *http.Request, r render.Render, isperm int) {
myconfig := config.Must(ctn)
// Si redirection vers page d'accueil
if isperm == 1 {
r.Redirect(myconfig.AppRoutes["home"])
}
// Si redirection vers mire de login
if isperm == 2 {
r.Redirect(myconfig.AppRoutes["securitylogin"] + "?redirect=" + req.URL.Path)
}
}
func SecurityLogin(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
redirect, isredirect := req.URL.Query()["redirect"]
var user entity.User
var myerr string
session.Clear()
if req.Method == http.MethodPost {
req.ParseForm()
login := req.Form.Get("login")
password := req.Form.Get("password")
// On recherche l'utilisateur
result := mydb.First(&user, "login = ?", login)
if result.RowsAffected == 0 {
myerr = "No User"
} else {
salt := user.Salt
if password != tool.Decrypt(salt, user.Password) {
myerr = "Erreur de connexion"
}
}
if myerr == "" {
RefreshSession(session, user)
if isredirect {
r.Redirect(redirect[0])
} else {
r.Redirect(myconfig.AppRoutes["home"])
}
}
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": false,
"usesidebar": false,
"usecontainer": true,
"error": myerr,
}
r.HTML(200, "security/login", rendermap)
}
func SecurityLogout(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
session.Clear()
r.Redirect(myconfig.AppRoutes["home"])
}
func RefreshSession(session sessions.Session, user entity.User) {
session.Set("Userid", strconv.FormatUint(uint64(user.Id), 10))
session.Set("Login", user.Login)
session.Set("Firstname", user.Firstname)
session.Set("Lastname", user.Lastname)
session.Set("Email", user.Email)
session.Set("Avatar", user.Avatar)
session.Set("Role", strconv.Itoa(user.Role))
session.Set("Apikey", user.Apikey)
}

217
controller/upload.go Normal file
View File

@ -0,0 +1,217 @@
package controller
import (
"arno/skeletor/config"
"arno/skeletor/service"
"arno/skeletor/tool"
"image/gif"
"image/jpeg"
"image/png"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"github.com/nfnt/resize"
"github.com/google/uuid"
"github.com/martini-contrib/sessions"
"github.com/martini-contrib/render"
)
func Upload(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, typeupload string, id string) {
myconfig := config.Must(ctn)
isonefile := true
iscallback := true
iscropped := false
path := setPath(ctn, "http", typeupload, id)
redirect := ""
acceptedFiles := ""
if typeupload == "logo" {
acceptedFiles = ".jpg,.jpeg,.gif,.png,.svg"
}
if typeupload == "avatar" {
iscropped = true
}
if iscropped {
iscallback = false
redirect = myconfig.AppRoutes["uploadcrop"] + typeupload + "/" + id
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": false,
"usesidebar": false,
"usecontainer": true,
"typeupload": typeupload,
"id": id,
"path": path,
"acceptedFiles": acceptedFiles,
"isonefile": isonefile,
"iscallback": iscallback,
"iscropped": iscropped,
"redirect": redirect,
}
r.HTML(200, "upload/upload", rendermap)
}
func Uploaded(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, typeupload string, id string) {
file, header, _ := req.FormFile("file")
defer file.Close()
isrename := true
isresize := false
resizeheight := uint(1200)
if typeupload == "logo" {
isresize = true
resizeheight = uint(120)
}
filename := saveFile(ctn, file, header, typeupload, id, isrename, isresize, resizeheight)
newmap := map[string]interface{}{"file": filename}
r.JSON(200, newmap)
}
func UploadCrop(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, typeupload string, id string) {
myconfig := config.Must(ctn)
pathfile, _ := req.URL.Query()["pathfile"]
filename, _ := req.URL.Query()["filename"]
path := setPath(ctn, "http", typeupload, id)
iscallback := false
redirect := ""
if typeupload == "avatar" {
iscallback = true
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": false,
"usesidebar": false,
"usecontainer": true,
"typeupload": typeupload,
"id": id,
"path": path,
"submitroute": myconfig.AppRoutes["uploadcropped"] + typeupload + "/" + id,
"filename": filename[0],
"pathfile": pathfile[0],
"iscallback": iscallback,
"redirect": redirect,
}
r.HTML(200, "upload/crop", rendermap)
}
func UploadCropped(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, typeupload string, id string) {
file, header, _ := req.FormFile("file")
defer file.Close()
isrename := false
isresize := false
resizeheight := uint(1200)
if typeupload == "avatar" {
isresize = true
resizeheight = uint(120)
}
filename := saveFile(ctn, file, header, typeupload, id, isrename, isresize, resizeheight)
newmap := map[string]interface{}{"file": filename}
r.JSON(200, newmap)
}
func saveFile(ctn *service.Container, file multipart.File, handle *multipart.FileHeader, typeupload string, id string, isrename bool, isresize bool, resizeheight uint) string {
data, _ := ioutil.ReadAll(file)
filename := handle.Filename
if isrename {
filename = uuid.New().String()
}
mineType := handle.Header.Get("Content-Type")
if isrename {
if mineType == "image/jpeg" {
filename = filename + ".jpg"
}
if mineType == "image/png" {
filename = filename + ".png"
}
if mineType == "image/gif" {
filename = filename + ".gif"
}
if mineType == "image/svg+xml" {
filename = filename + ".svg"
}
}
path := setPath(ctn, "os", typeupload, id) + filename
ioutil.WriteFile(path, data, 0666)
if isresize {
resizeFile(mineType, path, resizeheight)
}
return filename
}
func setPath(ctn *service.Container, mode string, typeupload string, id string) string {
myconfig := config.Must(ctn)
racine := ""
if mode == "http" {
racine = myconfig.AppWeburl
} else {
racine = "./public"
}
path := racine + "/uploads/" + typeupload + "/"
return path
}
func resizeFile(mineType string, path string, resizeheight uint) {
file, _ := os.Open(path)
if mineType == "image/jpeg" {
img, _ := jpeg.Decode(file)
file.Close()
m := resize.Resize(0, resizeheight, img, resize.Lanczos3)
out, _ := os.Create(path)
defer out.Close()
jpeg.Encode(out, m, nil)
}
if mineType == "image/png" {
img, _ := png.Decode(file)
file.Close()
m := resize.Resize(0, resizeheight, img, resize.Lanczos3)
out, _ := os.Create(path)
defer out.Close()
png.Encode(out, m)
}
if mineType == "image/gif" {
img, _ := gif.Decode(file)
file.Close()
m := resize.Resize(0, resizeheight, img, resize.Lanczos3)
out, _ := os.Create(path)
defer out.Close()
gif.Encode(out, m, nil)
}
if mineType == "image/svg+xml" {
// No resize for svg image
}
}

216
controller/user.go Normal file
View File

@ -0,0 +1,216 @@
package controller
import (
"arno/skeletor/config"
"arno/skeletor/entity"
"arno/skeletor/repository"
"arno/skeletor/service"
"arno/skeletor/tool"
"net/http"
"strconv"
"github.com/google/uuid"
"github.com/martini-contrib/render"
"github.com/martini-contrib/sessions"
)
func UserList(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
var users []entity.User
mydb.Find(&users)
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": true,
"usecontainer": true,
"users": users,
}
r.HTML(200, "user/list", rendermap)
}
func UserSubmit(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
var user entity.User
var myerr string
var isvalid bool
user.Avatar = "noavatar.png"
user.Apikey = uuid.New().String()
user.Role = 50
if req.Method == http.MethodPost {
myerr, isvalid = UserValidate(req)
if isvalid {
req.ParseForm()
// Encrypter le password
salt := []byte("example key 1234")
password := tool.Encrypt(salt, req.Form.Get("password"))
user.Login = req.Form.Get("login")
user.Password = password
user.Salt = salt
user.Role, _ = strconv.Atoi(req.Form.Get("role"))
user.Avatar = req.Form.Get("avatar")
user.Firstname = req.Form.Get("firstname")
user.Lastname = req.Form.Get("lastname")
user.Email = req.Form.Get("email")
user.Apikey = req.Form.Get("apikey")
err := mydb.Create(&user).Error
if err == nil {
r.Redirect(myconfig.AppRoutes["userlist"])
} else {
myerr = "Cet utilisateur existe déjà avec soit ce login / cet email / cette apikey<br>" + err.Error()
}
}
// Si erreur on reinit le password à vide
user.Password = ""
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": true,
"usecontainer": true,
"mode": "submit",
"user": user,
"error": myerr,
}
r.HTML(200, "user/edit", rendermap)
}
func UserUpdate(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, id string, from string) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
var user entity.User
var myerr string
var isvalid bool
result := mydb.First(&user, "id = ?", id)
if result.RowsAffected == 0 {
r.Redirect(myconfig.AppRoutes["userlist"])
}
if req.Method == http.MethodPost {
myerr, isvalid = UserValidate(req)
if isvalid {
req.ParseForm()
// Encrypter le password
if req.Form.Get("password") != "" {
salt := []byte("example key 1234")
password := tool.Encrypt(salt, req.Form.Get("password"))
user.Password = password
user.Salt = salt
}
user.Firstname = req.Form.Get("firstname")
user.Lastname = req.Form.Get("lastname")
user.Email = req.Form.Get("email")
user.Apikey = req.Form.Get("apikey")
user.Avatar = req.Form.Get("avatar")
if from == "update" {
user.Role, _ = strconv.Atoi(req.Form.Get("role"))
}
err := mydb.Save(&user).Error
if err == nil {
userid := session.Get("Userid").(string)
if strconv.FormatUint(uint64(user.Id), 10) == userid {
RefreshSession(session, user)
}
if from == "update" {
r.Redirect(myconfig.AppRoutes["userlist"])
} else {
r.Redirect(myconfig.AppRoutes["home"])
}
} else {
myerr = "Cet utilisateur existe déjà avec soit cet email / cette apikey" + err.Error()
}
}
}
usesidebar := true
if from == "profil" {
usesidebar = false
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": usesidebar,
"usecontainer": true,
"mode": from,
"user": user,
"error": myerr,
}
r.HTML(200, "user/edit", rendermap)
}
func UserDelete(ctn *service.Container, session sessions.Session, req *http.Request, r render.Render, id string) {
myconfig := config.Must(ctn)
mydb := repository.Must(ctn)
var user entity.User
result := mydb.First(&user, "id = ?", id)
if result.RowsAffected == 0 {
r.Redirect(myconfig.AppRoutes["userlist"])
}
var myerr string
err := mydb.Delete(&user).Error
if err == nil {
r.Redirect(myconfig.AppRoutes["userlist"])
} else {
myerr = "Problème à la suppression de l'enregistrement<br>" + err.Error()
}
rendermap := map[string]interface{}{
"conf": myconfig,
"session": tool.Rendersession(session),
"useheader": true,
"usesidebar": true,
"usecontainer": true,
"mode": "update",
"user": user,
"error": myerr,
}
r.HTML(200, "user/edit", rendermap)
}
func UserValidate(req *http.Request) (string, bool) {
req.ParseForm()
if len(req.Form.Get("login")) < 5 {
myerr := "Votre Login doit comporter au minimum 5 caractères"
return myerr, false
}
if req.Form.Get("password") != "" {
if !tool.IsPasswordValid(req.Form.Get("password")) {
myerr := "Mot de passe invalide<br><li>Minium 7 caractères</li><li>Minimum une majuscule</li><li>Minimum une minuscule</li><li>Minimum un chiffre</li><li>Minimum un caractère spécial</li>"
return myerr, false
}
}
return "", true
}