add new user and role table in app (in progress)
All checks were successful
Build Quasar SPA and Go Backend for memberApp / build-spa (push) Successful in 2m12s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, , linux) (push) Successful in 5m8s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, .exe, windows) (push) Successful in 5m8s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm, 6, , linux) (push) Successful in 4m57s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm64, , linux) (push) Successful in 5m7s
All checks were successful
Build Quasar SPA and Go Backend for memberApp / build-spa (push) Successful in 2m12s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, , linux) (push) Successful in 5m8s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, .exe, windows) (push) Successful in 5m8s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm, 6, , linux) (push) Successful in 4m57s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm64, , linux) (push) Successful in 5m7s
This commit is contained in:
1
backend/bin/dist/allowOrigins.json
vendored
1
backend/bin/dist/allowOrigins.json
vendored
@@ -1 +0,0 @@
|
||||
["http://localhost:9000", "http://localhost:9500", "http://127.0.0.1:9500"]
|
@@ -8,19 +8,29 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var DBCreate string = `CREATE TABLE IF NOT EXISTS users (
|
||||
var CreateUserTable string = `CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
settings TEXT NOT NULL
|
||||
);`
|
||||
|
||||
var DBNewUser string = `INSERT INTO users (username, role, password, settings) VALUES (?, ?, ?, ?)`
|
||||
var DBQueryPassword string = `SELECT role, password, settings FROM users WHERE username = ?`
|
||||
var CreateRoleTable string = `CREATE TABLE IF NOT EXISTS roles (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
role TEXT NOT NULL,
|
||||
rights TEXT NOT NULL
|
||||
);`
|
||||
|
||||
var NewUser string = `INSERT INTO users (username, email, role, password, settings) VALUES (?, ?, ?, ?, ?)`
|
||||
var NewRole = `INSERT INTO roles (role, rights) VALUES (?, ?)`
|
||||
var DBQueryPassword string = `SELECT id, role, password, settings FROM users WHERE username = ?`
|
||||
var DBUserLookup string = `SELECT EXISTS(SELECT 1 FROM users WHERE username = ?)`
|
||||
var DBRoleLookup string = `SELECT EXISTS(SELECT 1 FROM roles WHERE role = ?)`
|
||||
var DBRemoveUser string = `DELETE FROM users WHERE username = $1`
|
||||
var DBUpdateSettings string = `UPDATE users SET settings = ? WHERE username = ?`
|
||||
var DBUpdateRole string = `UPDATE roles SET rights = ? WHERE role = ?`
|
||||
|
||||
func CheckDBError(c *gin.Context, username string, err error) bool {
|
||||
if err != nil {
|
||||
|
@@ -14,6 +14,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.tecamino.com/paadi/tecamino-dbm/cert"
|
||||
|
||||
dbApi "gitea.tecamino.com/paadi/memberDB/api"
|
||||
"gitea.tecamino.com/paadi/tecamino-logger/logging"
|
||||
"github.com/gin-contrib/cors"
|
||||
@@ -28,13 +30,16 @@ func main() {
|
||||
spa := flag.String("spa", "./dist/spa", "quasar spa files")
|
||||
workingDir := flag.String("workingDirectory", ".", "quasar spa files")
|
||||
ip := flag.String("ip", "0.0.0.0", "server listening ip")
|
||||
organization := flag.String("organization", "", "self signed ciertificate organization")
|
||||
port := flag.Uint("port", 9500, "server listening port")
|
||||
https := flag.Bool("https", false, "serves as https needs flag -cert and -chain")
|
||||
sslCert := flag.String("cert", "", "ssl certificate path")
|
||||
sslChain := flag.String("chain", "", "ssl chain path")
|
||||
debug := flag.Bool("debug", false, "log debug")
|
||||
flag.Parse()
|
||||
|
||||
//change working directory only if value is given
|
||||
if *workingDir != "." && *workingDir != "" {
|
||||
fmt.Println(1, *workingDir)
|
||||
os.Chdir(*workingDir)
|
||||
}
|
||||
|
||||
@@ -72,13 +77,18 @@ func main() {
|
||||
dbHandler := dbApi.NewAPIHandler()
|
||||
|
||||
//get local ip
|
||||
allowOrigins = append(allowOrigins, "http://localhost:9000", "http://localhost:9500", "http://127.0.0.1:9500")
|
||||
httpString := "http://"
|
||||
if *https {
|
||||
httpString = "https://"
|
||||
|
||||
}
|
||||
allowOrigins = append(allowOrigins, httpString+"localhost:9000", httpString+"localhost:9500", httpString+"127.0.0.1:9500")
|
||||
|
||||
localIP, err := utils.GetLocalIP()
|
||||
if err != nil {
|
||||
logger.Error("main", fmt.Sprintf("get local ip : %s", err.Error()))
|
||||
} else {
|
||||
allowOrigins = append(allowOrigins, fmt.Sprintf("http://%s:9000", localIP), fmt.Sprintf("http://%s:9500", localIP))
|
||||
allowOrigins = append(allowOrigins, fmt.Sprintf("%s%s:9000", httpString, localIP), fmt.Sprintf("%s%s:9500", httpString, localIP))
|
||||
}
|
||||
|
||||
s.Routes.Use(cors.New(cors.Config{
|
||||
@@ -102,18 +112,26 @@ func main() {
|
||||
//private
|
||||
auth := api.Group("/secure", user.AuthMiddleware())
|
||||
|
||||
auth.GET("/users", userManager.GetUserById)
|
||||
auth.GET("/members", dbHandler.GetMemberById)
|
||||
auth.GET("/roles", userManager.GetRoleById)
|
||||
|
||||
auth.POST("database/open", dbHandler.OpenDatabase)
|
||||
auth.POST("/members/add", dbHandler.AddNewMember)
|
||||
auth.POST("/members/edit", dbHandler.EditMember)
|
||||
auth.POST("/members/delete", dbHandler.DeleteMember)
|
||||
auth.POST("/members/import/csv", dbHandler.ImportCSV)
|
||||
auth.POST("/settings/update", userManager.UpdateSettings)
|
||||
auth.POST("/user/add", userManager.AddUser)
|
||||
auth.POST("/login/refresh", userManager.Refresh)
|
||||
|
||||
auth.DELETE("/user", userManager.RemoveUser)
|
||||
auth.POST("/settings/update", userManager.UpdateSettings)
|
||||
|
||||
auth.POST("/roles/add", userManager.AddRole)
|
||||
auth.POST("/roles/update", userManager.UpdateRole)
|
||||
auth.POST("/roles/delete", userManager.DeleteRole)
|
||||
|
||||
auth.POST("/users/add", userManager.AddUser)
|
||||
auth.POST("/users/delete", userManager.DeleteUser)
|
||||
|
||||
auth.POST("/login/refresh", userManager.Refresh)
|
||||
|
||||
// Serve static files
|
||||
s.Routes.StaticFS("/assets", gin.Dir(filepath.Join(*spa, "assets"), true))
|
||||
@@ -136,10 +154,29 @@ func main() {
|
||||
|
||||
go func() {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
if err := utils.OpenBrowser(fmt.Sprintf("http://localhost:%d", *port), logger); err != nil {
|
||||
if err := utils.OpenBrowser(fmt.Sprintf("%slocalhost:%d", httpString, *port), logger); err != nil {
|
||||
logger.Error("main", fmt.Sprintf("starting browser error : %s", err.Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
if *https {
|
||||
if *sslCert == "" {
|
||||
logger.Error("ssl certificate", "-cert flag not given for https server")
|
||||
log.Fatal("-cert flag not given for https server")
|
||||
}
|
||||
if *sslChain == "" {
|
||||
logger.Error("ssl key", "-chain flag not given for https server")
|
||||
log.Fatal("-chain flag not given for https server")
|
||||
}
|
||||
|
||||
// start https server
|
||||
logger.Info("main", fmt.Sprintf("https listen on ip: %s port: %d", *ip, *port))
|
||||
if err := s.ServeHttps(*ip, *port, cert.Cert{Organization: *organization, CertFile: *sslCert, KeyFile: *sslChain}); err != nil {
|
||||
logger.Error("main", "error https server "+err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// start http server
|
||||
logger.Info("main", fmt.Sprintf("http listen on ip: %s port: %d", *ip, *port))
|
||||
if err := s.ServeHttp(*ip, *port); err != nil {
|
||||
|
Binary file not shown.
8
backend/models/rights.go
Normal file
8
backend/models/rights.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package models
|
||||
|
||||
type Rights struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Read bool `json:"read,omitempty"`
|
||||
Write bool `json:"write,omitempty"`
|
||||
Delete bool `json:"delete,omitempty"`
|
||||
}
|
11
backend/models/role.go
Normal file
11
backend/models/role.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package models
|
||||
|
||||
type Role struct {
|
||||
Id int `json:"id"`
|
||||
Role string `json:"role"`
|
||||
Rights []Rights `json:"rights"`
|
||||
}
|
||||
|
||||
func (r *Role) IsValid() bool {
|
||||
return r.Role != ""
|
||||
}
|
@@ -1,7 +1,9 @@
|
||||
package models
|
||||
|
||||
type User struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"user"`
|
||||
Email string `json:"email"`
|
||||
Role string `json:"role"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Settings Settings `json:"settings"`
|
||||
|
@@ -29,10 +29,10 @@ func (s *Server) ServeHttp(ip string, port uint) error {
|
||||
}
|
||||
|
||||
// serve dbm as http
|
||||
func (s *Server) ServeHttps(port uint, cert cert.Cert) error {
|
||||
func (s *Server) ServeHttps(url string, port uint, cert cert.Cert) error {
|
||||
// generate self signed tls certificate
|
||||
if err := cert.GenerateSelfSignedCert(); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.Routes.RunTLS(fmt.Sprintf(":%d", port), cert.CertFile, cert.KeyFile)
|
||||
return s.Routes.RunTLS(fmt.Sprintf("%s:%d", url, port), cert.CertFile, cert.KeyFile)
|
||||
}
|
||||
|
Binary file not shown.
@@ -4,9 +4,7 @@ import (
|
||||
"backend/dbRequest"
|
||||
"backend/models"
|
||||
"backend/utils"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -21,101 +19,11 @@ var DOMAIN = "localhost"
|
||||
var ACCESS_TOKEN_TIME = 15 * time.Minute
|
||||
var REFRESH_TOKEN_TIME = 72 * time.Hour
|
||||
|
||||
func (um *UserManager) AddUser(c *gin.Context) {
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
user := models.User{}
|
||||
err = json.Unmarshal(body, &user)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !user.IsValid() {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("user empty"))
|
||||
return
|
||||
}
|
||||
|
||||
db, err := sql.Open(um.dbType, um.dbFile)
|
||||
if dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
var exists bool
|
||||
|
||||
if err := db.QueryRow(dbRequest.DBUserLookup, user.Name).Scan(&exists); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
if exists {
|
||||
c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(fmt.Sprintf("user '%s' exists already", user.Name)))
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := utils.HashPassword(user.Password)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
if _, err := db.Exec(dbRequest.DBNewUser, user.Role, user.Name, hash, "{}"); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": fmt.Sprintf("user '%s' successfully added", user.Name),
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UserManager) RemoveUser(c *gin.Context) {
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
user := models.User{}
|
||||
err = json.Unmarshal(body, &user)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !user.IsValid() {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("user empty"))
|
||||
return
|
||||
}
|
||||
|
||||
db, err := sql.Open(um.dbType, um.dbFile)
|
||||
if dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
var storedPassword string
|
||||
if err := db.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&storedPassword, &user.Role); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
if !utils.CheckPassword(user.Password, storedPassword) {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("wrong password"))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := db.Exec(dbRequest.DBRemoveUser, user.Name); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": fmt.Sprintf("user '%s' successfully removed", user.Name),
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UserManager) Login(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
@@ -134,14 +42,8 @@ func (um *UserManager) Login(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
db, err := sql.Open(um.dbType, um.dbFile)
|
||||
if dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
var storedPassword, settingsJsonString string
|
||||
if err := db.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&user.Role, &storedPassword, &settingsJsonString); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
if err := um.database.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&user.Id, &user.Role, &storedPassword, &settingsJsonString); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -162,6 +64,7 @@ func (um *UserManager) Login(c *gin.Context) {
|
||||
|
||||
// Create token
|
||||
accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"id": user.Id,
|
||||
"username": user.Name,
|
||||
"role": user.Role,
|
||||
"type": "access",
|
||||
@@ -169,6 +72,7 @@ func (um *UserManager) Login(c *gin.Context) {
|
||||
})
|
||||
|
||||
refreshToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"id": user.Id,
|
||||
"username": user.Name,
|
||||
"role": user.Role,
|
||||
"type": "refresh",
|
||||
@@ -194,9 +98,9 @@ func (um *UserManager) Login(c *gin.Context) {
|
||||
c.SetCookie("refresh_token", refreshString, int(time.Until(refreshTokenExp).Seconds()),
|
||||
"/", "", secure, true)
|
||||
|
||||
fmt.Println(22, user.Settings)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "login successful",
|
||||
"id": user.Id,
|
||||
"user": user.Name,
|
||||
"role": user.Role,
|
||||
"settings": user.Settings,
|
||||
@@ -225,11 +129,13 @@ func (um *UserManager) Refresh(c *gin.Context) {
|
||||
}
|
||||
|
||||
username := claims["username"].(string)
|
||||
id := claims["id"].(float64)
|
||||
role := claims["role"].(string)
|
||||
|
||||
// new access token
|
||||
accessExp := time.Now().Add(ACCESS_TOKEN_TIME)
|
||||
newAccess := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"id": id,
|
||||
"username": username,
|
||||
"role": role,
|
||||
"exp": accessExp.Unix(),
|
||||
@@ -259,6 +165,7 @@ func (um *UserManager) Me(c *gin.Context) {
|
||||
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"id": claims["id"],
|
||||
"user": claims["username"],
|
||||
"role": claims["role"],
|
||||
})
|
||||
|
@@ -2,15 +2,23 @@ package user
|
||||
|
||||
import (
|
||||
"backend/dbRequest"
|
||||
"backend/models"
|
||||
"backend/utils"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type UserManager struct {
|
||||
dbType string
|
||||
dbFile string
|
||||
database *sql.DB
|
||||
}
|
||||
|
||||
func NewUserManager(dir string) (*UserManager, error) {
|
||||
@@ -18,17 +26,17 @@ func NewUserManager(dir string) (*UserManager, error) {
|
||||
dir = "."
|
||||
}
|
||||
|
||||
var typ string = "sqlite"
|
||||
var file string = fmt.Sprintf("%s/user.db", dir)
|
||||
var err error
|
||||
var um UserManager
|
||||
file := fmt.Sprintf("%s/user.db", dir)
|
||||
|
||||
um.database, err = sql.Open("sqlite", file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(file); err != nil {
|
||||
db, err := sql.Open(typ, file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(dbRequest.DBCreate)
|
||||
_, err = um.database.Exec(dbRequest.CreateUserTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -37,13 +45,217 @@ func NewUserManager(dir string) (*UserManager, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = db.Exec(dbRequest.DBNewUser, "admin", "admin", hash, "{}")
|
||||
_, err = um.database.Exec(dbRequest.NewUser, "admin", "", "admin", hash, `{"databaseName":"members.dba","primaryColor":"#1976d2", "secondaryColor":"#26a69a"}`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &UserManager{
|
||||
dbType: typ,
|
||||
dbFile: file,
|
||||
}, nil
|
||||
return &um, nil
|
||||
}
|
||||
|
||||
func (um *UserManager) databaseOpened(c *gin.Context) bool {
|
||||
if um.database == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "no database opened",
|
||||
})
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (um *UserManager) AddUser(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
user := models.User{}
|
||||
err = json.Unmarshal(body, &user)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !user.IsValid() {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("user empty"))
|
||||
return
|
||||
}
|
||||
|
||||
var exists bool
|
||||
|
||||
if err := um.database.QueryRow(dbRequest.DBUserLookup, user.Name).Scan(&exists); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
if exists {
|
||||
c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(fmt.Sprintf("user '%s' exists already", user.Name)))
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := utils.HashPassword(user.Password)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !utils.IsValidEmail(user.Email) {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(errors.New("not valid email address")))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := um.database.Exec(dbRequest.NewUser, user.Name, user.Email, user.Role, hash, "{}"); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": fmt.Sprintf("user '%s' successfully added", user.Name),
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UserManager) GetUserById(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
var i int
|
||||
var err error
|
||||
|
||||
id := c.Query("id")
|
||||
if id != "" {
|
||||
i, err = strconv.Atoi(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
query := `SELECT id, username, email, role, settings FROM users`
|
||||
var args any
|
||||
if i > 0 {
|
||||
query = `
|
||||
SELECT id, username, email, role, settings FROM users
|
||||
WHERE id = ?
|
||||
`
|
||||
args = i
|
||||
}
|
||||
|
||||
rows, err := um.database.Query(query, args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var users []models.User
|
||||
|
||||
for rows.Next() {
|
||||
var id int
|
||||
var name, email, role, settingsString string
|
||||
if err = rows.Scan(&id, &name, &email, &role, &settingsString); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var settings models.Settings
|
||||
err := json.Unmarshal([]byte(settingsString), &settings)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
users = append(users, models.User{
|
||||
Id: id,
|
||||
Name: name,
|
||||
Email: email,
|
||||
Role: role,
|
||||
Settings: settings,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, users)
|
||||
}
|
||||
|
||||
func (um *UserManager) DeleteUser(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
queryId := c.Query("id")
|
||||
|
||||
if queryId == "" || queryId == "null" || queryId == "undefined" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "id query missing or wrong value: " + queryId,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var request struct {
|
||||
Ids []int `json:"ids"`
|
||||
}
|
||||
|
||||
err := c.BindJSON(&request)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if len(request.Ids) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "no ids given to be deleted",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var ownId string
|
||||
placeholders := make([]string, len(request.Ids))
|
||||
args := make([]any, len(request.Ids))
|
||||
for i, id := range request.Ids {
|
||||
if queryId == fmt.Sprint(id) {
|
||||
ownId = queryId
|
||||
continue
|
||||
}
|
||||
|
||||
placeholders[i] = "?"
|
||||
args[i] = id
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("DELETE FROM users WHERE id IN (%s)", strings.Join(placeholders, ","))
|
||||
|
||||
_, err = um.database.Exec(query, args...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if ownId != "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "can not delete logged in member id: " + queryId,
|
||||
"id": queryId,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "member(s) deleted",
|
||||
})
|
||||
}
|
||||
|
245
backend/user/roles.go
Normal file
245
backend/user/roles.go
Normal file
@@ -0,0 +1,245 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"backend/dbRequest"
|
||||
"backend/models"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func (um *UserManager) AddRole(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
role := models.Role{}
|
||||
err = json.Unmarshal(body, &role)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !role.IsValid() {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("user empty"))
|
||||
return
|
||||
}
|
||||
|
||||
var exists bool
|
||||
|
||||
if err := um.database.QueryRow(dbRequest.DBRoleLookup, role.Role).Scan(&exists); dbRequest.CheckDBError(c, role.Role, err) {
|
||||
return
|
||||
}
|
||||
|
||||
if exists {
|
||||
c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(fmt.Sprintf("role '%s' exists already", role.Role)))
|
||||
return
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(role.Rights)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := um.database.Exec(dbRequest.NewRole, role.Role, string(jsonBytes)); dbRequest.CheckDBError(c, role.Role, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": fmt.Sprintf("role '%s' successfully added", role.Role),
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UserManager) GetRoleById(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := um.database.Exec(dbRequest.CreateRoleTable); err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
var i int
|
||||
var err error
|
||||
|
||||
id := c.Query("id")
|
||||
if id != "" {
|
||||
i, err = strconv.Atoi(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
query := `SELECT id, role, rights FROM roles`
|
||||
var args any
|
||||
if i > 0 {
|
||||
query = `
|
||||
SELECT id, role, rights FROM users
|
||||
WHERE id = ?
|
||||
`
|
||||
args = i
|
||||
}
|
||||
|
||||
rows, err := um.database.Query(query, args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var roles []models.Role
|
||||
|
||||
for rows.Next() {
|
||||
var id int
|
||||
var role, rightsString string
|
||||
if err = rows.Scan(&id, &role, &rightsString); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var data struct {
|
||||
Rights []models.Rights `json:"rights"`
|
||||
}
|
||||
err := json.Unmarshal([]byte(rightsString), &data)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
roles = append(roles, models.Role{
|
||||
Id: id,
|
||||
Role: role,
|
||||
Rights: data.Rights,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, roles)
|
||||
}
|
||||
|
||||
func (um *UserManager) UpdateRole(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
role := models.Role{}
|
||||
err = json.Unmarshal(body, &role)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(role)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := um.database.Exec(dbRequest.DBUpdateRole, string(jsonBytes), role.Role); err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": fmt.Sprintf("role rights '%s' successfully updated", role.Role),
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UserManager) DeleteRole(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
queryRole := c.Query("role")
|
||||
|
||||
if queryRole == "" || queryRole == "null" || queryRole == "undefined" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "role query missing or wrong value: " + queryRole,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var request struct {
|
||||
Roles []string `json:"roles"`
|
||||
}
|
||||
|
||||
err := c.BindJSON(&request)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if len(request.Roles) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "no roles given to be deleted",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var ownRole string
|
||||
placeholders := make([]string, len(request.Roles))
|
||||
args := make([]any, len(request.Roles))
|
||||
for i, role := range request.Roles {
|
||||
if ownRole == role {
|
||||
ownRole = queryRole
|
||||
continue
|
||||
}
|
||||
|
||||
placeholders[i] = "?"
|
||||
args[i] = role
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("DELETE FROM roles WHERE role IN (%s)", strings.Join(placeholders, ","))
|
||||
|
||||
_, err = um.database.Exec(query, args...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if ownRole != "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "can not delete logged in role id: " + ownRole,
|
||||
"role": ownRole,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "role(s) deleted",
|
||||
})
|
||||
}
|
@@ -3,7 +3,6 @@ package user
|
||||
import (
|
||||
"backend/dbRequest"
|
||||
"backend/models"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -13,6 +12,10 @@ import (
|
||||
)
|
||||
|
||||
func (um *UserManager) UpdateSettings(c *gin.Context) {
|
||||
if !um.databaseOpened(c) {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
@@ -26,19 +29,13 @@ func (um *UserManager) UpdateSettings(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
db, err := sql.Open(um.dbType, um.dbFile)
|
||||
if dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
jsonBytes, err := json.Marshal(user.Settings)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := db.Exec(dbRequest.DBUpdateSettings, string(jsonBytes), user.Name); err != nil {
|
||||
if _, err := um.database.Exec(dbRequest.DBUpdateSettings, string(jsonBytes), user.Name); err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
"gitea.tecamino.com/paadi/tecamino-logger/logging"
|
||||
@@ -63,3 +64,8 @@ func FindAllFiles(rootDir, fileExtention string) (files []string, err error) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func IsValidEmail(email string) bool {
|
||||
re := regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
|
||||
return re.MatchString(email)
|
||||
}
|
||||
|
Reference in New Issue
Block a user