new package dbHandler accesscontrol memeberdb and login with rights
All checks were successful
Build Quasar SPA and Go Backend for memberApp / build-spa (push) Successful in 2m20s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, .exe, windows) (push) Successful in 5m27s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, , linux) (push) Successful in 5m32s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm, 6, , linux) (push) Successful in 5m28s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm64, , linux) (push) Successful in 5m29s
All checks were successful
Build Quasar SPA and Go Backend for memberApp / build-spa (push) Successful in 2m20s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, .exe, windows) (push) Successful in 5m27s
Build Quasar SPA and Go Backend for memberApp / build-backend (amd64, , linux) (push) Successful in 5m32s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm, 6, , linux) (push) Successful in 5m28s
Build Quasar SPA and Go Backend for memberApp / build-backend (arm64, , linux) (push) Successful in 5m29s
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -1,45 +0,0 @@
|
||||
package dbRequest
|
||||
|
||||
import (
|
||||
"backend/models"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
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 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 {
|
||||
if err.Error() == "sql: no rows in result set" {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse(fmt.Sprintf("no user '%s' found", username)))
|
||||
return true
|
||||
}
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -3,29 +3,34 @@ module backend
|
||||
go 1.24.5
|
||||
|
||||
require (
|
||||
gitea.tecamino.com/paadi/memberDB v1.0.1
|
||||
gitea.tecamino.com/paadi/access-handler v1.0.12
|
||||
gitea.tecamino.com/paadi/memberDB v1.0.4
|
||||
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1
|
||||
gitea.tecamino.com/paadi/tecamino-logger v0.2.1
|
||||
github.com/gin-contrib/cors v1.7.6
|
||||
github.com/gin-gonic/gin v1.11.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
golang.org/x/crypto v0.40.0
|
||||
modernc.org/sqlite v1.39.0
|
||||
golang.org/x/crypto v0.43.0
|
||||
)
|
||||
|
||||
require (
|
||||
gitea.tecamino.com/paadi/dbHandler v1.0.4 // indirect
|
||||
github.com/bytedance/sonic v1.14.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/glebarez/sqlite v1.11.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
@@ -45,15 +50,17 @@ require (
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/arch v0.20.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/tools v0.34.0 // indirect
|
||||
golang.org/x/mod v0.28.0 // indirect
|
||||
golang.org/x/net v0.45.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/tools v0.37.0 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gorm.io/gorm v1.31.0 // indirect
|
||||
modernc.org/libc v1.66.3 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
modernc.org/sqlite v1.39.0 // indirect
|
||||
)
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
gitea.tecamino.com/paadi/memberDB v1.0.1 h1:hNnnoCeFRBEOQ+QmizF9nzvrQ8bNed8YrDln5jeRy2Y=
|
||||
gitea.tecamino.com/paadi/memberDB v1.0.1/go.mod h1:4tgbjrSZ2FZeJL68R2TFHPH34+aGxx5wtZxRmu6nZv4=
|
||||
gitea.tecamino.com/paadi/access-handler v1.0.12 h1:lSmW0YrBJJvCqCg0ukTJHlFUNwd7q6hFYtNd2rfztrE=
|
||||
gitea.tecamino.com/paadi/access-handler v1.0.12/go.mod h1:w71lpnuu5MgAWG3oiI9vsY2dWi4njF/iPrM/xV/dbBQ=
|
||||
gitea.tecamino.com/paadi/dbHandler v1.0.4 h1:ctnaec0GDdtw3gRQdUISVDYLJ9x+vt50VW41OemfhD4=
|
||||
gitea.tecamino.com/paadi/dbHandler v1.0.4/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw=
|
||||
gitea.tecamino.com/paadi/memberDB v1.0.4 h1:2H7obSoMq4dW+VN8PsDOv1UK75hCtlF+NymU5NBGuw4=
|
||||
gitea.tecamino.com/paadi/memberDB v1.0.4/go.mod h1:iLm7nunVRzqJK8CV4PJVuWIhgPlQjNIaeOkmtfK5fMg=
|
||||
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1 h1:vAq7mwUxlxJuLzCQSDMrZCwo8ky5usWi9Qz+UP+WnkI=
|
||||
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1/go.mod h1:+tmf1rjPaKEoNeUcr1vdtoFIFweNG3aUGevDAl3NMBk=
|
||||
gitea.tecamino.com/paadi/tecamino-logger v0.2.1 h1:sQTBKYPdzn9mmWX2JXZBtGBvNQH7cuXIwsl4TD0aMgE=
|
||||
@@ -23,6 +27,10 @@ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
||||
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
||||
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
@@ -35,8 +43,8 @@ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -44,6 +52,10 @@ github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17k
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
@@ -94,23 +106,23 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
|
||||
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -119,6 +131,8 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
|
||||
gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM=
|
||||
modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"backend/models"
|
||||
"backend/server"
|
||||
"backend/user"
|
||||
"backend/utils"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -14,9 +13,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
AccessHandler "gitea.tecamino.com/paadi/access-handler"
|
||||
dbApi "gitea.tecamino.com/paadi/memberDB/api"
|
||||
"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"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -59,14 +59,14 @@ func main() {
|
||||
TerminalOut: true,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("main new logger", err.Error())
|
||||
logger.Error("main new logger", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
//new login manager
|
||||
userManager, err := user.NewUserManager(".")
|
||||
accessHandler, err := AccessHandler.NewAccessHandler(".", logger)
|
||||
if err != nil {
|
||||
logger.Error("main login manager", err.Error())
|
||||
logger.Error("main login manager", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -74,7 +74,11 @@ func main() {
|
||||
s := server.NewServer()
|
||||
|
||||
// initiate Database handler
|
||||
dbHandler := dbApi.NewAPIHandler()
|
||||
dbHandler, err := dbApi.NewAPIHandler(logger)
|
||||
if err != nil {
|
||||
logger.Error("main login manager", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
//get local ip
|
||||
httpString := "http://"
|
||||
@@ -82,17 +86,18 @@ func main() {
|
||||
httpString = "https://"
|
||||
|
||||
}
|
||||
allowOrigins = append(allowOrigins, httpString+"localhost:9000", httpString+"localhost:9500", httpString+"127.0.0.1:9500")
|
||||
allowOrigins = append(allowOrigins, httpString+"localhost:9000", httpString+"localhost:9500", httpString+"127.0.0.1:9500", httpString+"0.0.0.0:9500")
|
||||
|
||||
localIP, err := utils.GetLocalIP()
|
||||
if err != nil {
|
||||
logger.Error("main", fmt.Sprintf("get local ip : %s", err.Error()))
|
||||
logger.Error("main", fmt.Sprintf("get local ip : %s", err))
|
||||
} else {
|
||||
allowOrigins = append(allowOrigins, fmt.Sprintf("%s%s:9000", httpString, localIP), fmt.Sprintf("%s%s:9500", httpString, localIP))
|
||||
}
|
||||
|
||||
s.Routes.Use(cors.New(cors.Config{
|
||||
AllowOrigins: allowOrigins,
|
||||
AllowOrigins: allowOrigins,
|
||||
//AllowOrigins: []string{"*"},
|
||||
AllowMethods: []string{"POST", "GET", "DELETE", "OPTIONS"},
|
||||
AllowHeaders: []string{"Origin", "Content-Type"},
|
||||
ExposeHeaders: []string{"Content-Length"},
|
||||
@@ -100,21 +105,25 @@ func main() {
|
||||
MaxAge: 12 * time.Hour,
|
||||
}))
|
||||
|
||||
//set logger for AuthMiddleware
|
||||
accessHandler.SetMiddlewareLogger(s.Routes)
|
||||
api := s.Routes.Group("/api")
|
||||
//set routes
|
||||
|
||||
//public
|
||||
api.GET("/logout", userManager.Logout)
|
||||
api.GET("/login/me", userManager.Me)
|
||||
api.GET("/logout", accessHandler.Logout)
|
||||
api.GET("/login/me", accessHandler.Me)
|
||||
|
||||
api.POST("/login", userManager.Login)
|
||||
api.POST("/login", accessHandler.Login)
|
||||
|
||||
//private
|
||||
auth := api.Group("/secure", user.AuthMiddleware())
|
||||
auth := api.Group("", accessHandler.AuthMiddleware())
|
||||
|
||||
auth.GET("/users", userManager.GetUserById)
|
||||
auth.GET("/members", dbHandler.GetMemberById)
|
||||
auth.GET("/roles", userManager.GetRoleById)
|
||||
role := auth.Group("", accessHandler.AuthorizeRole("/api"))
|
||||
role.GET("/members", dbHandler.GetMember)
|
||||
|
||||
auth.GET("/users", accessHandler.GetUser)
|
||||
auth.GET("/roles", accessHandler.GetRole)
|
||||
|
||||
auth.POST("database/open", dbHandler.OpenDatabase)
|
||||
auth.POST("/members/add", dbHandler.AddNewMember)
|
||||
@@ -122,23 +131,22 @@ func main() {
|
||||
auth.POST("/members/delete", dbHandler.DeleteMember)
|
||||
auth.POST("/members/import/csv", dbHandler.ImportCSV)
|
||||
|
||||
auth.POST("/settings/update", userManager.UpdateSettings)
|
||||
auth.POST("/roles/add", accessHandler.AddRole)
|
||||
auth.POST("/roles/update", accessHandler.UpdateRole)
|
||||
auth.POST("/roles/delete", accessHandler.DeleteRole)
|
||||
|
||||
auth.POST("/roles/add", userManager.AddRole)
|
||||
auth.POST("/roles/update", userManager.UpdateRole)
|
||||
auth.POST("/roles/delete", userManager.DeleteRole)
|
||||
auth.POST("/users/add", accessHandler.AddUser)
|
||||
auth.POST("/users/update", accessHandler.UpdateUser)
|
||||
auth.POST("/users/delete", accessHandler.DeleteUser)
|
||||
|
||||
auth.POST("/users/add", userManager.AddUser)
|
||||
auth.POST("/users/delete", userManager.DeleteUser)
|
||||
|
||||
auth.POST("/login/refresh", userManager.Refresh)
|
||||
api.POST("/login/refresh", accessHandler.Refresh)
|
||||
|
||||
// Serve static files
|
||||
s.Routes.StaticFS("/assets", gin.Dir(filepath.Join(*spa, "assets"), true))
|
||||
s.Routes.NoRoute(func(c *gin.Context) {
|
||||
// Disallow fallback for /api paths
|
||||
if strings.HasPrefix(c.Request.URL.Path, "/api") {
|
||||
c.JSON(http.StatusNotFound, models.NewJsonErrorMessageResponse("API endpoint not found"))
|
||||
c.JSON(http.StatusNotFound, models.NewJsonMessageResponse("API endpoint not found"))
|
||||
return
|
||||
}
|
||||
// Try to serve file from SPA directory
|
||||
@@ -155,7 +163,7 @@ func main() {
|
||||
go func() {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
if err := utils.OpenBrowser(fmt.Sprintf("%slocalhost:%d", httpString, *port), logger); err != nil {
|
||||
logger.Error("main", fmt.Sprintf("starting browser error : %s", err.Error()))
|
||||
logger.Error("main", fmt.Sprintf("starting browser error : %s", err))
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
Binary file not shown.
@@ -5,16 +5,14 @@ type JsonResponse struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func NewJsonErrorMessageResponse(msg string) JsonResponse {
|
||||
func NewJsonMessageResponse(msg string) JsonResponse {
|
||||
return JsonResponse{
|
||||
Error: true,
|
||||
Message: msg,
|
||||
}
|
||||
}
|
||||
|
||||
func NewJsonErrorResponse(err error) JsonResponse {
|
||||
return JsonResponse{
|
||||
Error: true,
|
||||
Message: err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
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"`
|
||||
}
|
||||
// type Rights struct {
|
||||
// Name string `json:"name"`
|
||||
// Rights int `json:"rights"`
|
||||
// }
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package models
|
||||
|
||||
type Role struct {
|
||||
Id int `json:"id"`
|
||||
Role string `json:"role"`
|
||||
Rights []Rights `json:"rights"`
|
||||
}
|
||||
// type Role struct {
|
||||
// Id int `json:"id"`
|
||||
// Role string `json:"role"`
|
||||
// Rights []Rights `json:"rights"`
|
||||
// }
|
||||
|
||||
func (r *Role) IsValid() bool {
|
||||
return r.Role != ""
|
||||
}
|
||||
// func (r *Role) IsValid() bool {
|
||||
// return r.Role != ""
|
||||
// }
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package models
|
||||
|
||||
type Settings struct {
|
||||
PrimaryColor string `json:"primaryColor,omitempty"`
|
||||
SecondaryColor string `json:"secondaryColor,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
DatabaseName string `json:"databaseName,omitempty"`
|
||||
DatabaseToken string `json:"databaseToken,omitempty"`
|
||||
}
|
||||
// type Settings struct {
|
||||
// PrimaryColor string `json:"primaryColor,omitempty"`
|
||||
// PrimaryColorText string `json:"primaryColorText,omitempty"`
|
||||
// SecondaryColor string `json:"secondaryColor,omitempty"`
|
||||
// SecondaryColorText string `json:"secondaryColorText,omitempty"`
|
||||
// Icon string `json:"icon,omitempty"`
|
||||
// DatabaseName string `json:"databaseName,omitempty"`
|
||||
// DatabaseToken string `json:"databaseToken,omitempty"`
|
||||
// }
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
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"`
|
||||
}
|
||||
// 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"`
|
||||
// }
|
||||
|
||||
func (u *User) IsValid() bool {
|
||||
return u.Name != ""
|
||||
}
|
||||
// func (u *User) IsValid() bool {
|
||||
// return u.Name != ""
|
||||
// }
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
func AuthMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// Read access token from cookie
|
||||
cookie, err := c.Cookie("access_token")
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "not logged in"})
|
||||
return
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(cookie, func(t *jwt.Token) (any, error) {
|
||||
return JWT_SECRET, nil
|
||||
})
|
||||
if err != nil || !token.Valid {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "invalid token"})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func AuthorizeRole(roles ...string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
userRole := c.GetString("role")
|
||||
for _, role := range roles {
|
||||
if userRole == role {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "Forbidden"})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"backend/dbRequest"
|
||||
"backend/models"
|
||||
"backend/utils"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
var JWT_SECRET = []byte("4h5Jza1Fn_zuzu&417%8nH*UH100+55-")
|
||||
var DOMAIN = "localhost"
|
||||
var ACCESS_TOKEN_TIME = 15 * time.Minute
|
||||
var REFRESH_TOKEN_TIME = 72 * time.Hour
|
||||
|
||||
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))
|
||||
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 storedPassword, settingsJsonString string
|
||||
if err := um.database.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&user.Id, &user.Role, &storedPassword, &settingsJsonString); dbRequest.CheckDBError(c, user.Name, err) {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(settingsJsonString), &user.Settings)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if !utils.CheckPassword(user.Password, storedPassword) {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("wrong password"))
|
||||
return
|
||||
}
|
||||
|
||||
// ---- Create JWT tokens ----
|
||||
accessTokenExp := time.Now().Add(ACCESS_TOKEN_TIME)
|
||||
refreshTokenExp := time.Now().Add(REFRESH_TOKEN_TIME)
|
||||
|
||||
// Create token
|
||||
accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"id": user.Id,
|
||||
"username": user.Name,
|
||||
"role": user.Role,
|
||||
"type": "access",
|
||||
"exp": accessTokenExp.Unix(),
|
||||
})
|
||||
|
||||
refreshToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"id": user.Id,
|
||||
"username": user.Name,
|
||||
"role": user.Role,
|
||||
"type": "refresh",
|
||||
"exp": refreshTokenExp.Unix(),
|
||||
})
|
||||
|
||||
accessString, err := accessToken.SignedString(JWT_SECRET)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, models.NewJsonErrorMessageResponse("could not create access token"))
|
||||
return
|
||||
}
|
||||
|
||||
refreshString, err := refreshToken.SignedString(JWT_SECRET)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, models.NewJsonErrorMessageResponse("could not create refresh token"))
|
||||
return
|
||||
}
|
||||
|
||||
// ---- Set secure cookies ----
|
||||
secure := gin.Mode() == gin.ReleaseMode
|
||||
c.SetCookie("access_token", accessString, int(time.Until(accessTokenExp).Seconds()),
|
||||
"/", "", secure, true) // Path=/, Secure=true (only HTTPS), HttpOnly=true
|
||||
c.SetCookie("refresh_token", refreshString, int(time.Until(refreshTokenExp).Seconds()),
|
||||
"/", "", secure, true)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "login successful",
|
||||
"id": user.Id,
|
||||
"user": user.Name,
|
||||
"role": user.Role,
|
||||
"settings": user.Settings,
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UserManager) Refresh(c *gin.Context) {
|
||||
refreshCookie, err := c.Cookie("refresh_token")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"message": "no refresh token"})
|
||||
return
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(refreshCookie, func(token *jwt.Token) (any, error) {
|
||||
return JWT_SECRET, nil
|
||||
})
|
||||
if err != nil || !token.Valid {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"message": "invalid refresh token"})
|
||||
return
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok || claims["type"] != "refresh" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"message": "invalid token type"})
|
||||
return
|
||||
}
|
||||
|
||||
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(),
|
||||
})
|
||||
accessString, _ := newAccess.SignedString(JWT_SECRET)
|
||||
|
||||
c.SetCookie("access_token", accessString, int(time.Until(accessExp).Seconds()), "/", DOMAIN, gin.Mode() == gin.ReleaseMode, true)
|
||||
c.JSON(http.StatusOK, gin.H{"message": "token refreshed"})
|
||||
}
|
||||
|
||||
func (um *UserManager) Me(c *gin.Context) {
|
||||
// Read access token from cookie
|
||||
cookie, err := c.Cookie("access_token")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"message": "not logged in"})
|
||||
return
|
||||
}
|
||||
|
||||
// Verify token
|
||||
token, err := jwt.Parse(cookie, func(t *jwt.Token) (any, error) {
|
||||
return JWT_SECRET, nil
|
||||
})
|
||||
if err != nil || !token.Valid {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"message": "invalid token"})
|
||||
return
|
||||
}
|
||||
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"id": claims["id"],
|
||||
"user": claims["username"],
|
||||
"role": claims["role"],
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UserManager) Logout(c *gin.Context) {
|
||||
secure := gin.Mode() == gin.ReleaseMode
|
||||
|
||||
c.SetCookie("access_token", "", -1, "/", DOMAIN, secure, true)
|
||||
c.SetCookie("refresh_token", "", -1, "/", DOMAIN, secure, true)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "logged out"})
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
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 {
|
||||
database *sql.DB
|
||||
}
|
||||
|
||||
func NewUserManager(dir string) (*UserManager, error) {
|
||||
if dir == "" {
|
||||
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 {
|
||||
_, err = um.database.Exec(dbRequest.CreateUserTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash, err := utils.HashPassword("tecamino@2025")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = um.database.Exec(dbRequest.NewUser, "admin", "", "admin", hash, `{"databaseName":"members.dba","primaryColor":"#1976d2", "secondaryColor":"#26a69a"}`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
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",
|
||||
})
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
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",
|
||||
})
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"backend/dbRequest"
|
||||
"backend/models"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
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))
|
||||
return
|
||||
}
|
||||
|
||||
user := models.User{}
|
||||
err = json.Unmarshal(body, &user)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(user.Settings)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := um.database.Exec(dbRequest.DBUpdateSettings, string(jsonBytes), user.Name); err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": fmt.Sprintf("user settings '%s' successfully updated", user.Name),
|
||||
})
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
"gitea.tecamino.com/paadi/tecamino-logger/logging"
|
||||
@@ -64,8 +63,3 @@ 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