Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11b9c61113 | ||
|
|
fe194754b1 | ||
|
|
4a469d1fd4 | ||
|
|
dd5d7afdff | ||
|
|
a02a7e1646 | ||
|
|
b85caeadbd | ||
|
|
b3e58805fc | ||
|
|
2223b96432 | ||
|
|
21388b63fb | ||
|
|
86a4ef798a | ||
|
|
442afcb44c | ||
|
|
8b8d99e162 | ||
|
|
103a07b7ac | ||
|
|
a20a21d251 | ||
|
|
ee7ce526f3 | ||
|
|
a938f41e94 | ||
|
|
1d09705adb | ||
|
|
4ee558b340 | ||
|
|
ad44a65087 | ||
|
|
e3870de7d5 | ||
|
|
25f965cd72 | ||
|
|
25f744b26c | ||
|
|
ec77c8a488 | ||
|
|
80675ed328 | ||
|
|
1568ee2482 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.db
|
||||||
|
*.log
|
||||||
18
api/api.go
18
api/api.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitea.tecamino.com/paadi/tecamino-logger/logging"
|
||||||
"github.com/gin-contrib/cors"
|
"github.com/gin-contrib/cors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@@ -14,7 +15,7 @@ type API struct {
|
|||||||
router *gin.Engine
|
router *gin.Engine
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPI(host string, port int) *API {
|
func NewAPI(host string, port int, logger *logging.Logger) (*API, error) {
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.Use(cors.New(cors.Config{
|
r.Use(cors.New(cors.Config{
|
||||||
//AllowOrigins: []string{"http://localhost:9000"}, // frontend origin
|
//AllowOrigins: []string{"http://localhost:9000"}, // frontend origin
|
||||||
@@ -26,18 +27,21 @@ func NewAPI(host string, port int) *API {
|
|||||||
MaxAge: 12 * time.Hour,
|
MaxAge: 12 * time.Hour,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
apiHandler := NewAPIHandler()
|
apiHandler, err := NewAPIHandler(logger)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
v1 := r.Group("v1")
|
v1 := r.Group("v1")
|
||||||
v1.GET("/events", apiHandler.GetEventById)
|
v1.GET("/events", apiHandler.GetEvent)
|
||||||
v1.GET("/events/new", apiHandler.StartNewEvent)
|
v1.GET("/events/new", apiHandler.StartNewEvent)
|
||||||
v1.GET("/events/delete", apiHandler.DeleteEvent)
|
v1.GET("/events/delete", apiHandler.DeleteEvent)
|
||||||
v1.GET("/members", apiHandler.GetMemberById)
|
v1.GET("/members", apiHandler.GetMember)
|
||||||
v1.GET("/responsible", apiHandler.GetResponsibleById)
|
v1.GET("/responsible", apiHandler.GetResponsible)
|
||||||
|
|
||||||
v1.POST("/database/open", apiHandler.OpenDatabase)
|
v1.POST("/database/open", apiHandler.OpenDatabase)
|
||||||
v1.POST("/members/add", apiHandler.AddNewMember)
|
v1.POST("/members/add", apiHandler.AddNewMember)
|
||||||
v1.POST("/members/edit", apiHandler.EditMember)
|
v1.POST("/members/edit", apiHandler.UpdateMember)
|
||||||
v1.POST("/members/delete", apiHandler.DeleteMember)
|
v1.POST("/members/delete", apiHandler.DeleteMember)
|
||||||
v1.POST("/members/import/csv", apiHandler.ImportCSV)
|
v1.POST("/members/import/csv", apiHandler.ImportCSV)
|
||||||
|
|
||||||
@@ -50,7 +54,7 @@ func NewAPI(host string, port int) *API {
|
|||||||
return &API{host: host,
|
return &API{host: host,
|
||||||
port: port,
|
port: port,
|
||||||
router: r,
|
router: r,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) Run() error {
|
func (api *API) Run() error {
|
||||||
|
|||||||
@@ -1,20 +1,38 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"gitea.tecamino.com/paadi/memberDB/handlers"
|
"gitea.tecamino.com/paadi/memberDB/handlers"
|
||||||
"gitea.tecamino.com/paadi/memberDB/models"
|
"gitea.tecamino.com/paadi/memberDB/models"
|
||||||
|
"gitea.tecamino.com/paadi/tecamino-logger/logging"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type APIHandler struct {
|
type APIHandler struct {
|
||||||
DbHandler *handlers.DatabaseHandler
|
DbHandler *handlers.DatabaseHandler
|
||||||
|
//dataHandler *dbHandler.DBHandler
|
||||||
|
logger *logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPIHandler() *APIHandler {
|
func NewAPIHandler(logger *logging.Logger) (aH *APIHandler, err error) {
|
||||||
return &APIHandler{}
|
if logger == nil {
|
||||||
|
logger, err = logging.NewLogger("memberDb.log", logging.DefaultConfig())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Debug("NewAPIHandler", "initialize new api handler")
|
||||||
|
aH = &APIHandler{logger: logger}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIHandler) DBHandlerIsInitialized() bool {
|
||||||
|
return a.DbHandler != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) OpenDatabase(c *gin.Context) {
|
func (a *APIHandler) OpenDatabase(c *gin.Context) {
|
||||||
@@ -28,63 +46,64 @@ func (a *APIHandler) OpenDatabase(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if database.Path == "" {
|
if database.Path == "" {
|
||||||
|
a.logger.Debug("OpenDatabase", "set default database path")
|
||||||
database.SetDefaultPath()
|
database.SetDefaultPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
if database.Token == "" {
|
if database.Token == "" {
|
||||||
|
a.logger.Debug("OpenDatabase", "set default token")
|
||||||
database.SetDefaultToken()
|
database.SetDefaultToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
a.DbHandler, err = handlers.NewDatabaseHandler(database.Path, database.Create)
|
if _, err := os.Stat(database.Path); err != nil && !database.Create {
|
||||||
|
a.logger.Error("OpenDatabase", fmt.Sprintf("%s not found", database.Path))
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"message": fmt.Sprintf("%s not found", database.Path),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dbName := filepath.Base(database.Path)
|
||||||
|
folderpath := filepath.Dir(database.Path)
|
||||||
|
|
||||||
|
a.DbHandler, err = handlers.NewDatabaseHandler(dbName, folderpath, a.logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("OpenDatabase", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.DbHandler.CreateNewMemberTable(); err != nil {
|
if err := a.DbHandler.SetTimezone(os.Getenv("TIMEZONE")); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("OpenDatabase", err)
|
||||||
"message": err.Error(),
|
}
|
||||||
})
|
|
||||||
|
if err := a.DbHandler.AddNewTable(&models.Member{}); err != nil {
|
||||||
|
a.logger.Error("OpenDatabase", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.DbHandler.CreateNewEventTable(); err != nil {
|
if err := a.DbHandler.AddNewTable(&models.Event{}); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("OpenDatabase", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.DbHandler.CreateNewResponsibleTable(); err != nil {
|
if err := a.DbHandler.AddNewTable(&models.Responsible{}); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("OpenDatabase", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := a.DbHandler.AddNewTable(&models.Group{}); err != nil {
|
||||||
|
a.logger.Error("OpenDatabase", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
a.DbHandler.SetToken(database.Token)
|
a.DbHandler.SetToken(database.Token)
|
||||||
|
|
||||||
_, err = a.DbHandler.GetMember(0)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "database opened",
|
"message": "database opened",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// databaseOpened is a helper function to first check wheter database is open for requests
|
|
||||||
func (a *APIHandler) databaseOpened(c *gin.Context) bool {
|
|
||||||
if a.DbHandler == nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
|
||||||
"message": "no database opened",
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,32 +9,36 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (a *APIHandler) StartNewEvent(c *gin.Context) {
|
func (a *APIHandler) StartNewEvent(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("StartNewEvent", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
name := c.Query("name")
|
var event models.Event
|
||||||
if name == "" {
|
err := c.BindJSON(&event)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
if err != nil {
|
||||||
"message": "missing query 'name'",
|
a.logger.Error("StartNewEvent", err)
|
||||||
})
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.DbHandler.StartNewEvent(name); err != nil {
|
if err := a.DbHandler.StartNewEvent(&event); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("StartNewEvent", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "New Event added " + name,
|
"message": "New Event added " + event.Name,
|
||||||
|
"data": event,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) GetEventById(c *gin.Context) {
|
func (a *APIHandler) GetEvent(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("GetEvent", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,43 +49,75 @@ func (a *APIHandler) GetEventById(c *gin.Context) {
|
|||||||
if id != "" {
|
if id != "" {
|
||||||
i, err = strconv.Atoi(id)
|
i, err = strconv.Atoi(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("GetEvent", err)
|
||||||
"message": err.Error(),
|
|
||||||
})
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
events, err := a.DbHandler.GetEvent(i)
|
events, err := a.DbHandler.GetEvent(uint(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("GetEvent", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusBadRequest, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, events)
|
c.JSON(http.StatusOK, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) DeleteEvent(c *gin.Context) {
|
func (a *APIHandler) UpdateEvent(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("UpdateEvent", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var events []models.Event
|
||||||
|
err := c.BindJSON(&events)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("UpdateEvent", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, event := range events {
|
||||||
|
err = a.DbHandler.UpdateEvent(event.Id, event)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("UpdateEvent", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"message": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"message": "event(s) updated",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIHandler) DeleteEvent(c *gin.Context) {
|
||||||
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("DeleteEvent", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var request struct {
|
var request struct {
|
||||||
Ids []int `json:"ids"`
|
Ids []uint `json:"ids"`
|
||||||
}
|
}
|
||||||
err = c.BindJSON(&request)
|
err = c.BindJSON(&request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("DeleteEvent", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusBadRequest, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.DbHandler.DeleteEvent(request.Ids...)
|
err = a.DbHandler.DeleteEvent(request.Ids...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("DeleteEvent", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -93,22 +129,25 @@ func (a *APIHandler) DeleteEvent(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) AddNewAttendees(c *gin.Context) {
|
func (a *APIHandler) AddNewAttendees(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("AddNewAttendees", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var event models.Event
|
var event models.Event
|
||||||
err := c.BindJSON(&event)
|
err := c.BindJSON(&event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("AddNewAttendees", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.DbHandler.AddAttendeesToEvent(event)
|
err = a.DbHandler.AddAttendeesToEvent(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("AddNewAttendees", err)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -120,23 +159,26 @@ func (a *APIHandler) AddNewAttendees(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) DeleteAttendee(c *gin.Context) {
|
func (a *APIHandler) DeleteAttendee(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("DeleteAttendee", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var event models.Event
|
var event models.Event
|
||||||
err = c.BindJSON(&event)
|
err = c.BindJSON(&event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("DeleteAttendee", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.DbHandler.DeleteAttendeesFromEvent(event)
|
err = a.DbHandler.DeleteAttendeesFromEvent(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("DeleteAttendee", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
128
api/groupHandler.go
Normal file
128
api/groupHandler.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"gitea.tecamino.com/paadi/memberDB/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *APIHandler) NewGroup(c *gin.Context) {
|
||||||
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("StartNewEvent", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var group models.Group
|
||||||
|
err := c.BindJSON(&group)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("NewGroup", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := a.DbHandler.NewGroup(&group); err != nil {
|
||||||
|
a.logger.Error("NewGroup", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"message": "New group added " + group.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIHandler) GetGroup(c *gin.Context) {
|
||||||
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("GetGroup", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var i int
|
||||||
|
var err error
|
||||||
|
|
||||||
|
id := c.Query("id")
|
||||||
|
if id != "" {
|
||||||
|
i, err = strconv.Atoi(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("GetGroup", err)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groups, err := a.DbHandler.GetGroup(uint(i))
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("GetGroup", err)
|
||||||
|
c.JSON(http.StatusBadRequest, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIHandler) UpdateGroup(c *gin.Context) {
|
||||||
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("UpdateGroup", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var groups []models.Group
|
||||||
|
err := c.BindJSON(&groups)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("UpdateGroup", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, event := range groups {
|
||||||
|
err = a.DbHandler.UpdateGroup(event.Id, event)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("UpdateGroup", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"message": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"message": "group(s) updated",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIHandler) DeleteGroup(c *gin.Context) {
|
||||||
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("DeleteGroup", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var request struct {
|
||||||
|
Ids []uint `json:"ids"`
|
||||||
|
}
|
||||||
|
err = c.BindJSON(&request)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("DeleteGroup", err)
|
||||||
|
c.JSON(http.StatusBadRequest, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.DbHandler.DeleteGroup(request.Ids...)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("DeleteGroup", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"message": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"message": "group deleted",
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -16,16 +16,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (a *APIHandler) AddNewMember(c *gin.Context) {
|
func (a *APIHandler) AddNewMember(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("AddNewMember", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var member models.Member
|
var member models.Member
|
||||||
err := c.BindJSON(&member)
|
err := c.BindJSON(&member)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("AddNewMember", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,10 +37,9 @@ func (a *APIHandler) AddNewMember(c *gin.Context) {
|
|||||||
if member.LastName == "" {
|
if member.LastName == "" {
|
||||||
text += "lastName "
|
text += "lastName "
|
||||||
}
|
}
|
||||||
if member.Birthday == "" {
|
|
||||||
text += "birthday "
|
|
||||||
}
|
|
||||||
if text != "" {
|
if text != "" {
|
||||||
|
a.logger.Error("AddNewMember", text+"can not be empty")
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": text + "can not be empty",
|
"message": text + "can not be empty",
|
||||||
})
|
})
|
||||||
@@ -48,6 +48,7 @@ func (a *APIHandler) AddNewMember(c *gin.Context) {
|
|||||||
|
|
||||||
err = a.DbHandler.AddNewMember(member)
|
err = a.DbHandler.AddNewMember(member)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("AddNewMember", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -59,8 +60,10 @@ func (a *APIHandler) AddNewMember(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) GetMemberById(c *gin.Context) {
|
func (a *APIHandler) GetMember(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("GetMember", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,15 +74,15 @@ func (a *APIHandler) GetMemberById(c *gin.Context) {
|
|||||||
if id != "" {
|
if id != "" {
|
||||||
i, err = strconv.Atoi(id)
|
i, err = strconv.Atoi(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("GetMember", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
members, err := a.DbHandler.GetMember(i)
|
members, err := a.DbHandler.GetMember(uint(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("GetMember", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -88,88 +91,80 @@ func (a *APIHandler) GetMemberById(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, members)
|
c.JSON(http.StatusOK, members)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) EditMember(c *gin.Context) {
|
func (a *APIHandler) UpdateMember(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("EditMember", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var i int
|
var members []models.Member
|
||||||
var err error
|
err := c.BindJSON(&members)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error("EditMember", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
id := c.Query("id")
|
for _, member := range members {
|
||||||
if id != "" {
|
err = a.DbHandler.UpdateMember(member.Id, member)
|
||||||
i, err = strconv.Atoi(id)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("EditMember", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
|
||||||
"message": "query parameter 'id' missing",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var member models.Member
|
|
||||||
err = c.BindJSON(&member)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = a.DbHandler.UpdateMember(i, member)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "member updated",
|
"message": "member(s) updated",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) DeleteMember(c *gin.Context) {
|
func (a *APIHandler) DeleteMember(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("DeleteMember", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var request struct {
|
var request struct {
|
||||||
Ids []int `json:"ids"`
|
Ids []uint `json:"ids"`
|
||||||
}
|
}
|
||||||
err = c.BindJSON(&request)
|
err = c.BindJSON(&request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("DeleteMember", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.DbHandler.DeleteMember(request.Ids...)
|
err = a.DbHandler.DeleteMember(request.Ids...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("DeleteMember", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "member deleted",
|
"message": "member(s) deleted",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) ImportCSV(c *gin.Context) {
|
func (a *APIHandler) ImportCSV(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("ImportCSV", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
fileHeader, err := c.FormFile("file")
|
fileHeader, err := c.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("ImportCSV", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -188,7 +183,8 @@ func (a *APIHandler) ImportCSV(c *gin.Context) {
|
|||||||
|
|
||||||
rowIndexI, err := strconv.Atoi(rowIndex)
|
rowIndexI, err := strconv.Atoi(rowIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("ImportCSV", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -196,6 +192,7 @@ func (a *APIHandler) ImportCSV(c *gin.Context) {
|
|||||||
|
|
||||||
file, err := fileHeader.Open()
|
file, err := fileHeader.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("ImportCSV", err)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to open uploaded file"})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to open uploaded file"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -206,6 +203,7 @@ func (a *APIHandler) ImportCSV(c *gin.Context) {
|
|||||||
buf := make([]byte, sniffSize)
|
buf := make([]byte, sniffSize)
|
||||||
n, err := file.Read(buf)
|
n, err := file.Read(buf)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
|
a.logger.Error("ImportCSV", err)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -214,12 +212,14 @@ func (a *APIHandler) ImportCSV(c *gin.Context) {
|
|||||||
detector := chardet.NewTextDetector()
|
detector := chardet.NewTextDetector()
|
||||||
result, err := detector.DetectBest(buf[:n])
|
result, err := detector.DetectBest(buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("ImportCSV", err)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to detect encoding"})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to detect encoding"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = file.Seek(0, io.SeekStart)
|
_, err = file.Seek(0, io.SeekStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("ImportCSV", err)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to rewind file"})
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to rewind file"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -234,6 +234,7 @@ func (a *APIHandler) ImportCSV(c *gin.Context) {
|
|||||||
case "ISO-8859-1":
|
case "ISO-8859-1":
|
||||||
reader = transform.NewReader(file, charmap.ISO8859_1.NewDecoder())
|
reader = transform.NewReader(file, charmap.ISO8859_1.NewDecoder())
|
||||||
default:
|
default:
|
||||||
|
a.logger.Error("ImportCSV", "Unsupported encoding: "+result.Charset)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"message": "Unsupported encoding: " + result.Charset})
|
c.JSON(http.StatusBadRequest, gin.H{"message": "Unsupported encoding: " + result.Charset})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -243,6 +244,7 @@ func (a *APIHandler) ImportCSV(c *gin.Context) {
|
|||||||
|
|
||||||
records, err := csvReader.ReadAll()
|
records, err := csvReader.ReadAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("ImportCSV", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse CSV"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse CSV"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -298,6 +300,7 @@ func (a *APIHandler) ImportCSV(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if message != "" {
|
if message != "" {
|
||||||
|
a.logger.Error("ImportCSV", message)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": message,
|
"message": message,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,20 +10,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (a *APIHandler) AddNewResponsible(c *gin.Context) {
|
func (a *APIHandler) AddNewResponsible(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("AddNewResponsible", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var responsible models.Person
|
var responsibles []models.Responsible
|
||||||
err := c.BindJSON(&responsible)
|
err := c.BindJSON(&responsibles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("AddNewResponsible", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.DbHandler.AddNewResponsible(responsible)
|
err = a.DbHandler.AddNewResponsible(responsibles...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
@@ -32,15 +33,16 @@ func (a *APIHandler) AddNewResponsible(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "responsible added",
|
"message": "responsible(s) added",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) GetResponsibleById(c *gin.Context) {
|
func (a *APIHandler) GetResponsible(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("GetResponsible", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var i int
|
var i int
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -48,15 +50,15 @@ func (a *APIHandler) GetResponsibleById(c *gin.Context) {
|
|||||||
if id != "" {
|
if id != "" {
|
||||||
i, err = strconv.Atoi(id)
|
i, err = strconv.Atoi(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("GetResponsible", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
members, err := a.DbHandler.GetResponsible(i)
|
members, err := a.DbHandler.GetResponsible(uint(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("GetResponsible", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -66,24 +68,26 @@ func (a *APIHandler) GetResponsibleById(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIHandler) DeleteResponsible(c *gin.Context) {
|
func (a *APIHandler) DeleteResponsible(c *gin.Context) {
|
||||||
if !a.databaseOpened(c) {
|
if !a.DBHandlerIsInitialized() {
|
||||||
|
a.logger.Error("DeleteResponsible", "database handler is not initialized")
|
||||||
|
c.JSON(http.StatusInternalServerError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var request struct {
|
var request struct {
|
||||||
Ids []int `json:"ids"`
|
Ids []uint `json:"ids"`
|
||||||
}
|
}
|
||||||
err = c.BindJSON(&request)
|
err = c.BindJSON(&request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
a.logger.Error("DeleteResponsible", err)
|
||||||
"message": err.Error(),
|
c.JSON(http.StatusBadRequest, nil)
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.DbHandler.DeleteResponsible(request.Ids...)
|
err = a.DbHandler.DeleteResponsible(request.Ids...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.logger.Error("DeleteResponsible", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
|
|||||||
Binary file not shown.
27
go.mod
27
go.mod
@@ -3,11 +3,13 @@ module gitea.tecamino.com/paadi/memberDB
|
|||||||
go 1.24.5
|
go 1.24.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
gitea.tecamino.com/paadi/dbHandler v1.1.6
|
||||||
|
gitea.tecamino.com/paadi/tecamino-logger v0.2.1
|
||||||
github.com/gin-contrib/cors v1.7.6
|
github.com/gin-contrib/cors v1.7.6
|
||||||
github.com/gin-gonic/gin v1.11.0
|
github.com/gin-gonic/gin v1.11.0
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0
|
||||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
||||||
golang.org/x/text v0.27.0
|
golang.org/x/text v0.30.0
|
||||||
modernc.org/sqlite v1.39.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -17,12 +19,16 @@ require (
|
|||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||||
github.com/gin-contrib/sse v1.1.0 // 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/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||||
github.com/google/uuid v1.6.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/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
@@ -37,16 +43,21 @@ require (
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/arch v0.20.0 // indirect
|
golang.org/x/arch v0.20.0 // indirect
|
||||||
golang.org/x/crypto v0.40.0 // indirect
|
golang.org/x/crypto v0.43.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||||
golang.org/x/mod v0.25.0 // indirect
|
golang.org/x/mod v0.28.0 // indirect
|
||||||
golang.org/x/net v0.42.0 // indirect
|
golang.org/x/net v0.45.0 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/sync v0.17.0 // indirect
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
golang.org/x/sys v0.37.0 // indirect
|
||||||
golang.org/x/tools v0.34.0 // indirect
|
golang.org/x/tools v0.37.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.9 // 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/libc v1.66.3 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/memory v1.11.0 // indirect
|
||||||
|
modernc.org/sqlite v1.39.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
50
go.sum
50
go.sum
@@ -1,3 +1,7 @@
|
|||||||
|
gitea.tecamino.com/paadi/dbHandler v1.1.6 h1:Mz7ioUmozXx22oV3P7GHsvQn/2QKOjkNyzdptvqbaN8=
|
||||||
|
gitea.tecamino.com/paadi/dbHandler v1.1.6/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw=
|
||||||
|
gitea.tecamino.com/paadi/tecamino-logger v0.2.1 h1:sQTBKYPdzn9mmWX2JXZBtGBvNQH7cuXIwsl4TD0aMgE=
|
||||||
|
gitea.tecamino.com/paadi/tecamino-logger v0.2.1/go.mod h1:FkzRTldUBBOd/iy2upycArDftSZ5trbsX5Ira5OzJgM=
|
||||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||||
@@ -17,6 +21,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-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 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
||||||
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
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 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
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=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
@@ -36,6 +44,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/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 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
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 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
@@ -76,33 +88,43 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
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 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
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.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
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 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/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.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
|
||||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
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 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
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=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM=
|
||||||
modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||||
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
|
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
|
||||||
|
|||||||
@@ -3,52 +3,46 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"database/sql"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"time"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
_ "modernc.org/sqlite"
|
"gitea.tecamino.com/paadi/dbHandler"
|
||||||
|
"gitea.tecamino.com/paadi/tecamino-logger/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DatabaseHandler struct {
|
type DatabaseHandler struct {
|
||||||
database *sql.DB
|
database *dbHandler.DBHandler
|
||||||
token []byte
|
timeLocation *time.Location
|
||||||
|
token []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDatabaseHandler(file string, create bool) (*DatabaseHandler, error) {
|
func NewDatabaseHandler(name, path string, logger *logging.Logger) (*DatabaseHandler, error) {
|
||||||
if create {
|
|
||||||
// createOrOpenDB creates or opens a SQLite database at the given path.
|
|
||||||
// Create the directory if it doesn't exist
|
|
||||||
dir := filepath.Dir(file)
|
|
||||||
|
|
||||||
err := os.MkdirAll(dir, os.ModePerm)
|
database, err := dbHandler.NewDBHandler(name, path, logger)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create directory: %w", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if _, err := os.Stat(file); err != nil {
|
|
||||||
return nil, fmt.Errorf("%s not found", file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the database (creates it if it doesn't exist)
|
|
||||||
db, err := sql.Open("sqlite", file)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open database: %w", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return &DatabaseHandler{database: database}, nil
|
||||||
// Test the connection
|
|
||||||
if err = db.Ping(); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to connect to database: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DatabaseHandler{database: db}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *DatabaseHandler) SetToken(token string) {
|
func (dH *DatabaseHandler) SetTimezone(timezone string) (err error) {
|
||||||
dh.token = []byte(token)
|
if timezone == "" {
|
||||||
|
timezone = "Local"
|
||||||
|
}
|
||||||
|
dH.timeLocation, err = time.LoadLocation(timezone)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dH *DatabaseHandler) DatabaseOpened() bool {
|
||||||
|
return dH.database != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dH *DatabaseHandler) AddNewTable(model any) error {
|
||||||
|
return dH.database.AddNewTable(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dH *DatabaseHandler) AddNewColum(model any) error {
|
||||||
|
return dH.database.AddNewColum(model)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *DatabaseHandler) hashField(field string) string {
|
func (dh *DatabaseHandler) hashField(field string) string {
|
||||||
@@ -56,3 +50,7 @@ func (dh *DatabaseHandler) hashField(field string) string {
|
|||||||
h.Write([]byte(field))
|
h.Write([]byte(field))
|
||||||
return hex.EncodeToString(h.Sum(nil))
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dh *DatabaseHandler) SetToken(token string) {
|
||||||
|
dh.token = []byte(token)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,170 +1,97 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"slices"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"gitea.tecamino.com/paadi/memberDB/models"
|
"gitea.tecamino.com/paadi/memberDB/models"
|
||||||
|
"gitea.tecamino.com/paadi/memberDB/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (dh *DatabaseHandler) CreateNewEventTable() error {
|
func (dh *DatabaseHandler) StartNewEvent(event *models.Event) error {
|
||||||
createTableSQL := `
|
if !dh.DatabaseOpened() {
|
||||||
CREATE TABLE IF NOT EXISTS events (
|
return errors.New("database not opened")
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
date TEXT UNIQUE NOT NULL,
|
|
||||||
attendees TEXT NOT NULL,
|
|
||||||
count INTEGER NOT NULL
|
|
||||||
);`
|
|
||||||
|
|
||||||
_, err := dh.database.Exec(createTableSQL)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create table: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dh *DatabaseHandler) StartNewEvent(name string) error {
|
|
||||||
_, err := dh.database.Exec("INSERT INTO events (name, date, attendees, count) VALUES (?, ?, ?, ?)", name, time.Now().Format("2006-01-02 15:04:05"), "[]", 0)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dh *DatabaseHandler) GetEvent(id int) (attendees []models.Event, err error) {
|
|
||||||
var args any
|
|
||||||
query := `SELECT id, name, date, attendees, count FROM events`
|
|
||||||
|
|
||||||
if id > 0 {
|
|
||||||
query += ` WHERE id = ?`
|
|
||||||
args = id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := dh.database.Query(query, args)
|
if dh.database.Exists(&models.Event{}, "", "name", event.Name, false) {
|
||||||
|
return errors.New("event with name: " + event.Name + " exists already")
|
||||||
|
}
|
||||||
|
|
||||||
|
event.Date = utils.GetCurrentTime(dh.timeLocation)
|
||||||
|
event.Day = utils.GetCurrentDay(dh.timeLocation)
|
||||||
|
return dh.database.AddNewColum(&event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dh *DatabaseHandler) GetEvent(id uint) (event []models.Event, err error) {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return event, errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dh.database.GetById(&event, "Attendees", id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
return
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var id, count int
|
|
||||||
var name, date, attendance string
|
|
||||||
if err = rows.Scan(&id, &name, &date, &attendance, &count); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var a []models.Person
|
|
||||||
|
|
||||||
if err := json.Unmarshal([]byte(attendance), &a); err != nil {
|
|
||||||
return attendees, err
|
|
||||||
}
|
|
||||||
|
|
||||||
attendees = append(attendees, models.Event{
|
|
||||||
Id: id,
|
|
||||||
Name: name,
|
|
||||||
Date: date,
|
|
||||||
Attendees: a,
|
|
||||||
Count: count,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return attendees, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *DatabaseHandler) DeleteEvent(ids ...int) error {
|
func (dh *DatabaseHandler) UpdateEvent(id int, event models.Event) (err error) {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
return dh.database.UpdateValuesById(&event, "", uint(event.Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dh *DatabaseHandler) DeleteEvent(ids ...uint) error {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
return errors.New("no ids given to be deleted")
|
return errors.New("no ids given to be deleted")
|
||||||
}
|
}
|
||||||
|
|
||||||
placeholders := make([]string, len(ids))
|
return dh.database.DeleteById(&models.Event{}, "", ids...)
|
||||||
args := make([]any, len(ids))
|
|
||||||
for i, id := range ids {
|
|
||||||
placeholders[i] = "?"
|
|
||||||
args[i] = id
|
|
||||||
}
|
|
||||||
query := fmt.Sprintf("DELETE FROM events WHERE id IN (%s)", strings.Join(placeholders, ","))
|
|
||||||
|
|
||||||
_, err := dh.database.Exec(query, args...)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *DatabaseHandler) AddAttendeesToEvent(event models.Event) error {
|
func (dh *DatabaseHandler) AddAttendeesToEvent(newEvent models.Event) error {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
//get event from database by id
|
return errors.New("database not opened")
|
||||||
row := dh.database.QueryRow(`SELECT attendees FROM events WHERE id = ?`, event.Id)
|
|
||||||
|
|
||||||
var attendeesString string
|
|
||||||
if err := row.Scan(&attendeesString); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
fmt.Println(attendeesString)
|
|
||||||
|
|
||||||
var attendees []models.Person
|
var event models.Event
|
||||||
err := json.Unmarshal([]byte(attendeesString), &attendees)
|
err := dh.database.GetById(&event, "Attendees", uint(newEvent.Id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
for _, newAttendee := range event.Attendees {
|
for _, newAttendee := range newEvent.Attendees {
|
||||||
for _, attendee := range attendees {
|
if !dh.database.Exists(&models.Member{}, "", "id", newAttendee.Id, false) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, attendee := range event.Attendees {
|
||||||
if attendee.FirstName == newAttendee.FirstName && attendee.LastName == newAttendee.LastName {
|
if attendee.FirstName == newAttendee.FirstName && attendee.LastName == newAttendee.LastName {
|
||||||
continue next
|
continue next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
attendees = append(attendees, newAttendee)
|
dh.database.AddRelation(&event, newAttendee, "Attendees")
|
||||||
}
|
}
|
||||||
|
|
||||||
attendeesByte, err := json.Marshal(attendees)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
count := len(attendees)
|
|
||||||
_, err = dh.database.Exec("UPDATE events SET attendees= ? count= ? WHERE id= ?", string(attendeesByte), event.Id, count)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *DatabaseHandler) DeleteAttendeesFromEvent(event models.Event) error {
|
func (dh *DatabaseHandler) DeleteAttendeesFromEvent(newEvent models.Event) error {
|
||||||
//get event from database by id
|
if !dh.DatabaseOpened() {
|
||||||
row := dh.database.QueryRow(`SELECT attendees FROM events WHERE id = ?`, event.Id)
|
return errors.New("database not opened")
|
||||||
|
|
||||||
var attendeesString string
|
|
||||||
if err := row.Scan(&attendeesString); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(attendeesString)
|
|
||||||
|
|
||||||
var attendees []models.Person
|
|
||||||
err := json.Unmarshal([]byte(attendeesString), &attendees)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, newAttendee := range event.Attendees {
|
var event models.Event
|
||||||
for i, attendee := range attendees {
|
dh.database.GetById(&event, "Attendees", uint(newEvent.Id))
|
||||||
if attendee.FirstName == newAttendee.FirstName && attendee.LastName == newAttendee.LastName {
|
|
||||||
attendees = slices.Delete(attendees, i, i+1)
|
for _, newAttendee := range newEvent.Attendees {
|
||||||
|
for _, a := range event.Attendees {
|
||||||
|
if a.FirstName == newAttendee.FirstName && a.LastName == newAttendee.LastName {
|
||||||
|
dh.database.DeleteRelation(&event, a, "Attendees")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attendeesByte, err := json.Marshal(attendees)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
count := len(attendees)
|
|
||||||
_, err = dh.database.Exec("UPDATE events SET attendees= ? count= ? WHERE id= ?", string(attendeesByte), event.Id, count)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
49
handlers/group.go
Normal file
49
handlers/group.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"gitea.tecamino.com/paadi/memberDB/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (dh *DatabaseHandler) NewGroup(group *models.Group) error {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
|
if dh.database.Exists(&models.Group{}, "", "name", group.Name, false) {
|
||||||
|
return errors.New("group with name: " + group.Name + " exists already")
|
||||||
|
}
|
||||||
|
return dh.database.AddNewColum(&group)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dh *DatabaseHandler) GetGroup(id uint) (group []models.Group, err error) {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return group, errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dh.database.GetById(&group, "", id)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dh *DatabaseHandler) UpdateGroup(id int, group models.Group) (err error) {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
return dh.database.UpdateValuesById(&group, "", uint(group.Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dh *DatabaseHandler) DeleteGroup(ids ...uint) error {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ids) == 0 {
|
||||||
|
return errors.New("no ids given to be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
return dh.database.DeleteById(&models.Group{}, "", ids...)
|
||||||
|
}
|
||||||
@@ -1,48 +1,20 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"gitea.tecamino.com/paadi/memberDB/crypto"
|
"gitea.tecamino.com/paadi/memberDB/crypto"
|
||||||
"gitea.tecamino.com/paadi/memberDB/models"
|
"gitea.tecamino.com/paadi/memberDB/models"
|
||||||
"gitea.tecamino.com/paadi/memberDB/utils"
|
"gitea.tecamino.com/paadi/memberDB/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateNewMemberTable creates a new member table.
|
|
||||||
func (dh *DatabaseHandler) CreateNewMemberTable() error {
|
|
||||||
createTableSQL := `
|
|
||||||
CREATE TABLE IF NOT EXISTS members (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
first_name TEXT NOT NULL,
|
|
||||||
first_name_hash TEXT NOT NULL,
|
|
||||||
last_name TEXT NOT NULL,
|
|
||||||
last_name_hash TEXT NOT NULL,
|
|
||||||
birthday TEXT NOT NULL,
|
|
||||||
birthday_hash TEXT NOT NULL,
|
|
||||||
address TEXT NOT NULL,
|
|
||||||
zip_code TEXT NOT NULL,
|
|
||||||
town TEXT NOT NULL,
|
|
||||||
phone TEXT NOT NULL,
|
|
||||||
email TEXT UNIQUE NOT NULL,
|
|
||||||
first_visit TEXT NOT NULL,
|
|
||||||
last_visit TEXT NOT NULL,
|
|
||||||
member_group TEXT NOT NULL,
|
|
||||||
responsible_person TEXT NOT NULL
|
|
||||||
);`
|
|
||||||
|
|
||||||
_, err := dh.database.Exec(createTableSQL)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create table: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddNewMember adds a new member to memeber table at least fist, las name and birthday has to be entered
|
// AddNewMember adds a new member to memeber table at least fist, las name and birthday has to be entered
|
||||||
func (dh *DatabaseHandler) AddNewMember(members ...models.Member) error {
|
func (dh *DatabaseHandler) AddNewMember(members ...models.Member) error {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
|
|
||||||
exists, err := dh.memberExists(member)
|
exists, err := dh.memberExists(member)
|
||||||
@@ -102,7 +74,7 @@ func (dh *DatabaseHandler) AddNewMember(members ...models.Member) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().Format("2006-01-02 15:04:05")
|
now := utils.GetCurrentTime(dh.timeLocation)
|
||||||
encFirstVisit, err := crypto.Encrypt(now, dh.token)
|
encFirstVisit, err := crypto.Encrypt(now, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -113,17 +85,27 @@ func (dh *DatabaseHandler) AddNewMember(members ...models.Member) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
encGroup, err := crypto.Encrypt(member.Group, dh.token)
|
encComment, err := crypto.Encrypt(member.Comment, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
encResponsiblePerson, err := crypto.Encrypt(member.ResponsiblePerson, dh.token)
|
member.FirstNameHash = dh.hashField(member.FirstName)
|
||||||
if err != nil {
|
member.FirstName = encFirstName
|
||||||
return err
|
member.LastNameHash = dh.hashField(member.LastName)
|
||||||
}
|
member.LastName = encLastName
|
||||||
|
member.BirthdayHash = dh.hashField(member.Birthday)
|
||||||
|
member.Birthday = encBirthday
|
||||||
|
member.Address = encAddress
|
||||||
|
member.Zip = encZip
|
||||||
|
member.Town = encTown
|
||||||
|
member.Phone = encPhone
|
||||||
|
member.Email = encEmail
|
||||||
|
member.FirstVisit = encFirstVisit
|
||||||
|
member.LastVisit = encLastVisit
|
||||||
|
member.Comment = encComment
|
||||||
|
|
||||||
_, err = dh.database.Exec("INSERT INTO members (first_name, first_name_hash, last_name, last_name_hash, birthday, birthday_hash, address, zip_code, town, phone, email, first_visit, last_visit, member_group, responsible_person) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", encFirstName, dh.hashField(member.FirstName), encLastName, dh.hashField(member.LastName), encBirthday, dh.hashField(member.Birthday), encAddress, encZip, encTown, encPhone, encEmail, encFirstVisit, encLastVisit, encGroup, encResponsiblePerson)
|
err = dh.database.AddNewColum(&member)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -132,290 +114,219 @@ func (dh *DatabaseHandler) AddNewMember(members ...models.Member) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteMember removes members by given ids
|
// DeleteMember removes members by given ids
|
||||||
func (dh *DatabaseHandler) DeleteMember(ids ...int) error {
|
func (dh *DatabaseHandler) DeleteMember(ids ...uint) error {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
return errors.New("no ids given to be deleted")
|
return errors.New("no ids given to be deleted")
|
||||||
}
|
}
|
||||||
|
return dh.database.DeleteById(&models.Member{}, "", ids...)
|
||||||
placeholders := make([]string, len(ids))
|
|
||||||
args := make([]any, len(ids))
|
|
||||||
for i, id := range ids {
|
|
||||||
placeholders[i] = "?"
|
|
||||||
args[i] = id
|
|
||||||
}
|
|
||||||
query := fmt.Sprintf("DELETE FROM members WHERE id IN (%s)", strings.Join(placeholders, ","))
|
|
||||||
|
|
||||||
_, err := dh.database.Exec(query, args...)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMember returns one member by given id
|
// GetMember returns one member by given id
|
||||||
func (dh *DatabaseHandler) GetMember(id int) (members []models.Member, err error) {
|
func (dh *DatabaseHandler) GetMember(id uint) (members []models.Member, err error) {
|
||||||
var args any
|
if !dh.DatabaseOpened() {
|
||||||
query := `SELECT id, first_name, last_name, birthday, address, zip_code, town, phone, email, first_visit, last_visit, member_group, responsible_person FROM members`
|
return members, errors.New("database not opened")
|
||||||
|
|
||||||
if id > 0 {
|
|
||||||
query = ` WHERE id = ?`
|
|
||||||
args = id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := dh.database.Query(query, args)
|
err = dh.database.GetById(&members, "", id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
for rows.Next() {
|
for i := range members {
|
||||||
var id int
|
if members[i].FirstName != "" {
|
||||||
var encFirstName, encLastName, encBirthday, encAddress, encZip, encTown, encPhone, encEmail, encFirstVisit, encLastVisit, encGroup, encResponsiblePerson string
|
members[i].FirstName, err = crypto.Decrypt(members[i].FirstName, dh.token)
|
||||||
if err = rows.Scan(&id, &encFirstName, &encLastName, &encBirthday, &encAddress, &encZip, &encTown, &encPhone, &encEmail, &encFirstVisit, &encLastVisit, &encGroup, &encResponsiblePerson); err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
firstName, err := crypto.Decrypt(encFirstName, dh.token)
|
if members[i].LastName != "" {
|
||||||
if err != nil {
|
members[i].LastName, err = crypto.Decrypt(members[i].LastName, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastName, err := crypto.Decrypt(encLastName, dh.token)
|
if members[i].Birthday != "" {
|
||||||
if err != nil {
|
members[i].Birthday, err = crypto.Decrypt(members[i].Birthday, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
birthday, err := crypto.Decrypt(encBirthday, dh.token)
|
if members[i].Address != "" {
|
||||||
if err != nil {
|
members[i].Address, err = crypto.Decrypt(members[i].Address, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
address, err := crypto.Decrypt(encAddress, dh.token)
|
if members[i].Zip != "" {
|
||||||
if err != nil {
|
members[i].Zip, err = crypto.Decrypt(members[i].Zip, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zip, err := crypto.Decrypt(encZip, dh.token)
|
if members[i].Town != "" {
|
||||||
if err != nil {
|
members[i].Town, err = crypto.Decrypt(members[i].Town, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
town, err := crypto.Decrypt(encTown, dh.token)
|
if members[i].Phone != "" {
|
||||||
if err != nil {
|
members[i].Phone, err = crypto.Decrypt(members[i].Phone, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
phone, err := crypto.Decrypt(encPhone, dh.token)
|
if members[i].Email != "" {
|
||||||
if err != nil {
|
members[i].Email, err = crypto.Decrypt(members[i].Email, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
email, err := crypto.Decrypt(encEmail, dh.token)
|
if members[i].FirstVisit != "" {
|
||||||
if err != nil {
|
members[i].FirstVisit, err = crypto.Decrypt(members[i].FirstVisit, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
firstVisit, err := crypto.Decrypt(encFirstVisit, dh.token)
|
if members[i].LastVisit != "" {
|
||||||
if err != nil {
|
members[i].LastVisit, err = crypto.Decrypt(members[i].LastVisit, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastVisit, err := crypto.Decrypt(encLastVisit, dh.token)
|
if members[i].Comment != "" {
|
||||||
if err != nil {
|
members[i].Comment, err = crypto.Decrypt(members[i].Comment, dh.token)
|
||||||
return members, err
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group, err := crypto.Decrypt(encGroup, dh.token)
|
|
||||||
if err != nil {
|
|
||||||
return members, err
|
|
||||||
}
|
|
||||||
|
|
||||||
responsiblePerson, err := crypto.Decrypt(encResponsiblePerson, dh.token)
|
|
||||||
if err != nil {
|
|
||||||
return members, err
|
|
||||||
}
|
|
||||||
|
|
||||||
members = append(members, models.Member{
|
|
||||||
Id: id,
|
|
||||||
FirstName: firstName,
|
|
||||||
LastName: lastName,
|
|
||||||
Birthday: birthday,
|
|
||||||
Address: address,
|
|
||||||
Zip: zip,
|
|
||||||
Town: town,
|
|
||||||
Phone: phone,
|
|
||||||
Email: email,
|
|
||||||
FirstVisit: firstVisit,
|
|
||||||
LastVisit: lastVisit,
|
|
||||||
Group: group,
|
|
||||||
ResponsiblePerson: responsiblePerson,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
return members, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateMember updates/overrides all information given meber id
|
// UpdateMember updates/overrides all information given meber id
|
||||||
func (dh *DatabaseHandler) UpdateMember(id int, member models.Member) (err error) {
|
func (dh *DatabaseHandler) UpdateMember(id int, member models.Member) (err error) {
|
||||||
var queryParameters []string
|
if !dh.DatabaseOpened() {
|
||||||
var args []any
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
if member.FirstName != "" {
|
if member.FirstName != "" {
|
||||||
encFirstName, err := crypto.Encrypt(member.FirstName, dh.token)
|
member.FirstNameHash = dh.hashField(member.FirstName)
|
||||||
|
member.FirstName, err = crypto.Encrypt(member.FirstName, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
queryParameters = append(queryParameters, "first_name = ?")
|
|
||||||
queryParameters = append(queryParameters, "first_name_hash = ?")
|
|
||||||
|
|
||||||
args = append(args, encFirstName)
|
|
||||||
args = append(args, dh.hashField(member.FirstName))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.LastName != "" {
|
if member.LastName != "" {
|
||||||
encLastName, err := crypto.Encrypt(member.LastName, dh.token)
|
member.LastNameHash = dh.hashField(member.LastName)
|
||||||
|
member.LastName, err = crypto.Encrypt(member.LastName, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
queryParameters = append(queryParameters, "last_name = ?")
|
|
||||||
queryParameters = append(queryParameters, "last_name_hash = ?")
|
|
||||||
|
|
||||||
args = append(args, encLastName)
|
|
||||||
args = append(args, dh.hashField(member.LastName))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//check correct birtday format
|
//check correct birtday format
|
||||||
if member.Birthday != "" && utils.IsValidBirthday(member.Birthday) {
|
if member.Birthday != "" && utils.IsValidBirthday(member.Birthday) {
|
||||||
encBirthday, err := crypto.Encrypt(member.Birthday, dh.token)
|
member.BirthdayHash = dh.hashField(member.BirthdayHash)
|
||||||
|
member.Birthday, err = crypto.Encrypt(member.Birthday, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
queryParameters = append(queryParameters, "birthday = ?")
|
|
||||||
queryParameters = append(queryParameters, "birthday_hash = ?")
|
|
||||||
|
|
||||||
args = append(args, encBirthday)
|
|
||||||
args = append(args, dh.hashField(member.Birthday))
|
|
||||||
} else if member.Birthday != "" {
|
} else if member.Birthday != "" {
|
||||||
return errors.New("incorrect birthday format")
|
return errors.New("incorrect birthday format")
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.Address != "" {
|
if member.Address != "" {
|
||||||
encAddress, err := crypto.Encrypt(member.Address, dh.token)
|
member.Address, err = crypto.Encrypt(member.Address, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "address = ?")
|
|
||||||
|
|
||||||
args = append(args, encAddress)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.Zip != "" {
|
if member.Zip != "" {
|
||||||
encZip, err := crypto.Encrypt(member.Zip, dh.token)
|
member.Zip, err = crypto.Encrypt(member.Zip, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "zip_code = ?")
|
|
||||||
|
|
||||||
args = append(args, encZip)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.Town != "" {
|
if member.Town != "" {
|
||||||
encTown, err := crypto.Encrypt(member.Town, dh.token)
|
member.Town, err = crypto.Encrypt(member.Town, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "town = ?")
|
|
||||||
|
|
||||||
args = append(args, encTown)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.Phone != "" {
|
if member.Phone != "" {
|
||||||
encPhone, err := crypto.Encrypt(member.Phone, dh.token)
|
member.Phone, err = crypto.Encrypt(member.Phone, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "phone = ?")
|
|
||||||
|
|
||||||
args = append(args, encPhone)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//check correct email format
|
//check correct email format
|
||||||
if member.Email != "" && utils.IsValidEmail(member.Email) {
|
if member.Email != "" && utils.IsValidEmail(member.Email) {
|
||||||
encEmail, err := crypto.Encrypt(member.Email, dh.token)
|
member.Email, err = crypto.Encrypt(member.Email, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "email = ?")
|
|
||||||
|
|
||||||
args = append(args, encEmail)
|
|
||||||
} else if member.Email != "" {
|
} else if member.Email != "" {
|
||||||
return errors.New("incorrect email format")
|
return errors.New("incorrect email format")
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.FirstVisit != "" {
|
if member.FirstVisit != "" {
|
||||||
encFirstVisit, err := crypto.Encrypt(member.FirstVisit, dh.token)
|
member.FirstVisit, err = crypto.Encrypt(member.FirstVisit, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "first_visit = ?")
|
|
||||||
|
|
||||||
args = append(args, encFirstVisit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.LastVisit != "" {
|
if member.LastVisit != "" {
|
||||||
encLastVisit, err := crypto.Encrypt(member.LastVisit, dh.token)
|
member.LastVisit, err = crypto.Encrypt(member.LastVisit, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "last_visit = ?")
|
|
||||||
|
|
||||||
args = append(args, encLastVisit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.Group != "" {
|
if member.Comment != "" {
|
||||||
encFirstVisit, err := crypto.Encrypt(member.Group, dh.token)
|
member.Comment, err = crypto.Encrypt(member.Comment, dh.token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
queryParameters = append(queryParameters, "member_group = ?")
|
|
||||||
|
|
||||||
args = append(args, encFirstVisit)
|
|
||||||
}
|
}
|
||||||
|
return dh.database.UpdateValuesById(&member, "", uint(member.Id))
|
||||||
if member.ResponsiblePerson != "" {
|
|
||||||
encResponsiblePerson, err := crypto.Encrypt(member.ResponsiblePerson, dh.token)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
queryParameters = append(queryParameters, "responsible_person = ?")
|
|
||||||
|
|
||||||
args = append(args, encResponsiblePerson)
|
|
||||||
}
|
|
||||||
|
|
||||||
query := `UPDATE members SET `
|
|
||||||
query += strings.Join(queryParameters, ", ")
|
|
||||||
query += ` WHERE id = ?`
|
|
||||||
args = append(args, id)
|
|
||||||
|
|
||||||
_, err = dh.database.Exec(query, args...)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// memberExists helper to check wheter member already exists
|
// memberExists helper to check wheter member already exists
|
||||||
func (dh *DatabaseHandler) memberExists(member models.Member) (bool, error) {
|
func (dh *DatabaseHandler) memberExists(checkMember models.Member) (bool, error) {
|
||||||
query := `
|
if !dh.DatabaseOpened() {
|
||||||
SELECT 1 FROM members
|
return false, errors.New("database not opened")
|
||||||
WHERE first_name_hash = ? AND last_name_hash = ? AND birthday_hash = ?
|
|
||||||
LIMIT 1
|
|
||||||
`
|
|
||||||
var exists int
|
|
||||||
err := dh.database.QueryRow(query, dh.hashField(member.FirstName), dh.hashField(member.LastName), dh.hashField(member.Birthday)).Scan(&exists)
|
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return false, nil // no match
|
|
||||||
} else if err != nil {
|
|
||||||
return false, err // db error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil // match found
|
var members []models.Member
|
||||||
|
if !dh.database.Exists(&members, "", "birthdayHash", dh.hashField(checkMember.Birthday), false) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, member := range members {
|
||||||
|
if dh.hashField(checkMember.FirstName) == member.FirstNameHash && dh.hashField(checkMember.LastName) == member.LastNameHash && dh.hashField(checkMember.Birthday) == member.BirthdayHash {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,110 +1,46 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"gitea.tecamino.com/paadi/memberDB/models"
|
"gitea.tecamino.com/paadi/memberDB/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (dh *DatabaseHandler) CreateNewResponsibleTable() error {
|
func (dh *DatabaseHandler) AddNewResponsible(responsibles ...models.Responsible) error {
|
||||||
createTableSQL := `
|
if !dh.DatabaseOpened() {
|
||||||
CREATE TABLE IF NOT EXISTS responsible (
|
return errors.New("database not opened")
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
first_name TEXT NOT NULL,
|
|
||||||
last_name TEXT UNIQUE NOT NULL
|
|
||||||
);`
|
|
||||||
|
|
||||||
_, err := dh.database.Exec(createTableSQL)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create table: %w", err)
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dh *DatabaseHandler) AddNewResponsible(responsibles ...models.Person) error {
|
for i := range responsibles {
|
||||||
for _, responsible := range responsibles {
|
if !dh.database.Exists(&models.Member{}, "", "id", 25, false) {
|
||||||
|
|
||||||
exists, err := dh.responsibleExists(responsible)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if exists {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = dh.database.Exec("INSERT INTO responsible (first_name, last_name) VALUES (?, ?)", responsible.FirstName, responsible.LastName)
|
err := dh.database.AddNewColum(&responsibles[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *DatabaseHandler) GetResponsible(id int) (persons []models.Person, err error) {
|
func (dh *DatabaseHandler) GetResponsible(id uint) (responsibles models.Responsibles, err error) {
|
||||||
var args any
|
if !dh.DatabaseOpened() {
|
||||||
query := `SELECT id, first_name, last_name FROM responsible`
|
return responsibles, errors.New("database not opened")
|
||||||
|
|
||||||
if id > 0 {
|
|
||||||
query = ` WHERE id = ?`
|
|
||||||
args = id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := dh.database.Query(query, args)
|
err = dh.database.GetById(&responsibles, "Member", id)
|
||||||
if err != nil {
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var id int
|
|
||||||
var firstName, lastName string
|
|
||||||
if err = rows.Scan(&id, &firstName, &lastName); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
persons = append(persons, models.Person{
|
|
||||||
Id: id,
|
|
||||||
FirstName: firstName,
|
|
||||||
LastName: lastName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return persons, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *DatabaseHandler) DeleteResponsible(ids ...int) error {
|
func (dh *DatabaseHandler) DeleteResponsible(ids ...uint) error {
|
||||||
|
if !dh.DatabaseOpened() {
|
||||||
|
return errors.New("database not opened")
|
||||||
|
}
|
||||||
|
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
return errors.New("no ids given to be deleted")
|
return errors.New("no ids given to be deleted")
|
||||||
}
|
}
|
||||||
|
return dh.database.DeleteById(&models.Responsible{}, "", ids...)
|
||||||
placeholders := make([]string, len(ids))
|
|
||||||
args := make([]any, len(ids))
|
|
||||||
for i, id := range ids {
|
|
||||||
placeholders[i] = "?"
|
|
||||||
args[i] = id
|
|
||||||
}
|
|
||||||
query := fmt.Sprintf("DELETE FROM responsible WHERE id IN (%s)", strings.Join(placeholders, ","))
|
|
||||||
|
|
||||||
_, err := dh.database.Exec(query, args...)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dh *DatabaseHandler) responsibleExists(responsible models.Person) (bool, error) {
|
|
||||||
query := `
|
|
||||||
SELECT 1 FROM responsible
|
|
||||||
WHERE first_name = ? AND last_name = ?
|
|
||||||
LIMIT 1
|
|
||||||
`
|
|
||||||
var exists int
|
|
||||||
err := dh.database.QueryRow(query, responsible.FirstName, responsible.LastName).Scan(&exists)
|
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return false, nil // no match
|
|
||||||
} else if err != nil {
|
|
||||||
return false, err // db error
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil // match found
|
|
||||||
}
|
}
|
||||||
|
|||||||
9
main.go
9
main.go
@@ -12,8 +12,13 @@ func main() {
|
|||||||
url := flag.String("url", "127.0.0.1", "server url")
|
url := flag.String("url", "127.0.0.1", "server url")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
a := api.NewAPI(*url, *port)
|
a, err := api.NewAPI(*url, *port, nil)
|
||||||
if err := a.Run(); err != nil {
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.Run()
|
||||||
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
221
member_test.go
Normal file
221
member_test.go
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitea.tecamino.com/paadi/memberDB/api"
|
||||||
|
"gitea.tecamino.com/paadi/memberDB/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-playground/assert/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErrors(t *testing.T) {
|
||||||
|
dbName := "test.db"
|
||||||
|
if _, err := os.Stat(dbName); err == nil {
|
||||||
|
t.Log("remove user.db to start test with empty database")
|
||||||
|
if err := os.Remove(dbName); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("start member db test")
|
||||||
|
|
||||||
|
t.Log("initialize accessHandler")
|
||||||
|
|
||||||
|
r := gin.Default()
|
||||||
|
|
||||||
|
apiHandler, err := api.NewAPIHandler(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v1 := r.Group("v1")
|
||||||
|
v1.GET("/events", apiHandler.GetEvent)
|
||||||
|
v1.GET("/events/new", apiHandler.StartNewEvent)
|
||||||
|
v1.GET("/events/delete", apiHandler.DeleteEvent)
|
||||||
|
v1.GET("/members", apiHandler.GetMember)
|
||||||
|
v1.GET("/responsible", apiHandler.GetResponsible)
|
||||||
|
|
||||||
|
v1.POST("/database/open", apiHandler.OpenDatabase)
|
||||||
|
v1.POST("/members/add", apiHandler.AddNewMember)
|
||||||
|
v1.POST("/members/edit", apiHandler.UpdateMember)
|
||||||
|
v1.POST("/members/delete", apiHandler.DeleteMember)
|
||||||
|
v1.POST("/members/import/csv", apiHandler.ImportCSV)
|
||||||
|
|
||||||
|
v1.POST("/events/attendees/add", apiHandler.AddNewAttendees)
|
||||||
|
v1.POST("/events/attendees/delete", apiHandler.DeleteAttendee)
|
||||||
|
|
||||||
|
v1.POST("/responsible/add", apiHandler.AddNewResponsible)
|
||||||
|
v1.POST("/responsible/delete", apiHandler.DeleteResponsible)
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
Log string
|
||||||
|
Name string
|
||||||
|
Method string
|
||||||
|
Path string
|
||||||
|
Payload any
|
||||||
|
Cookie *http.Cookie
|
||||||
|
ignoreError bool
|
||||||
|
}
|
||||||
|
var requests []request
|
||||||
|
|
||||||
|
type payload struct {
|
||||||
|
DBPath string `json:"dbPath,omitempty"`
|
||||||
|
Create bool `json:"create,omitempty"`
|
||||||
|
FirstName string `json:"FirstName,omitempty"`
|
||||||
|
LastName string `json:"lastName,omitempty"`
|
||||||
|
Birthday string `json:"birthday,omitempty"`
|
||||||
|
}
|
||||||
|
requests = append(requests,
|
||||||
|
|
||||||
|
request{Log: "error db not opened", Name: "error db not opened", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Adrian", LastName: "Zürcher", Birthday: "23.06.1987"}, ignoreError: true},
|
||||||
|
request{Log: "open member db", Name: "open member db", Method: "POST", Path: "/v1/database/open", Payload: payload{DBPath: "test.db", Create: true}},
|
||||||
|
request{Log: "add new member", Name: "add new member", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Adrian", LastName: "Zürcher", Birthday: "23.06.1987"}, ignoreError: true},
|
||||||
|
request{Log: "error first name missing", Name: "error first name missing", Method: "POST", Path: "/v1/members/add", Payload: payload{LastName: "Zürcher", Birthday: "23.06.1987"}, ignoreError: true},
|
||||||
|
request{Log: "error last name missing", Name: "error last name missing", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Adrian", Birthday: "23.06.1987"}, ignoreError: true},
|
||||||
|
request{Log: "error birthday missing", Name: "error birthday missing", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Paulina", LastName: "Zürcher"}, ignoreError: true},
|
||||||
|
request{Log: "error wrong birthday format", Name: "error wrong birthday format", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Paulina", LastName: "Zürcher", Birthday: "213.06.1987"}, ignoreError: true},
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, request := range requests {
|
||||||
|
if request.Log != "" {
|
||||||
|
t.Log(request.Log)
|
||||||
|
|
||||||
|
}
|
||||||
|
var bodyReader io.Reader
|
||||||
|
if request.Payload != nil {
|
||||||
|
jsonBytes, _ := json.Marshal(request.Payload)
|
||||||
|
bodyReader = bytes.NewBuffer(jsonBytes)
|
||||||
|
}
|
||||||
|
req, _ := http.NewRequest(request.Method, request.Path, bodyReader)
|
||||||
|
if request.Cookie != nil {
|
||||||
|
req.AddCookie(request.Cookie) // attach refresh_token cookie
|
||||||
|
}
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
r.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
t.Log(request.Name+" response:", w.Body.String())
|
||||||
|
if !request.ignoreError {
|
||||||
|
assert.Equal(t, http.StatusOK, w.Code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestMemberDB(t *testing.T) {
|
||||||
|
dbName := "test.db"
|
||||||
|
if _, err := os.Stat(dbName); err == nil {
|
||||||
|
t.Log("remove user.db to start test with empty database")
|
||||||
|
if err := os.Remove(dbName); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("start member db test")
|
||||||
|
|
||||||
|
t.Log("initialize accessHandler")
|
||||||
|
|
||||||
|
r := gin.Default()
|
||||||
|
|
||||||
|
apiHandler, err := api.NewAPIHandler(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v1 := r.Group("v1")
|
||||||
|
v1.GET("/events", apiHandler.GetEvent)
|
||||||
|
v1.GET("/members", apiHandler.GetMember)
|
||||||
|
v1.GET("/responsible", apiHandler.GetResponsible)
|
||||||
|
|
||||||
|
v1.POST("/database/open", apiHandler.OpenDatabase)
|
||||||
|
v1.POST("/members/add", apiHandler.AddNewMember)
|
||||||
|
v1.POST("/members/edit", apiHandler.UpdateMember)
|
||||||
|
v1.POST("/members/delete", apiHandler.DeleteMember)
|
||||||
|
v1.POST("/members/import/csv", apiHandler.ImportCSV)
|
||||||
|
|
||||||
|
v1.POST("/events/new", apiHandler.StartNewEvent)
|
||||||
|
v1.POST("/events/attendees/add", apiHandler.AddNewAttendees)
|
||||||
|
v1.POST("/events/attendees/delete", apiHandler.DeleteAttendee)
|
||||||
|
v1.POST("/events/edit", apiHandler.UpdateEvent)
|
||||||
|
v1.POST("/events/delete", apiHandler.DeleteEvent)
|
||||||
|
|
||||||
|
v1.POST("/responsible/add", apiHandler.AddNewResponsible)
|
||||||
|
v1.POST("/responsible/delete", apiHandler.DeleteResponsible)
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
Log string
|
||||||
|
Name string
|
||||||
|
Method string
|
||||||
|
Path string
|
||||||
|
Payload any
|
||||||
|
Cookie *http.Cookie
|
||||||
|
ignoreError bool
|
||||||
|
}
|
||||||
|
var requests []request
|
||||||
|
|
||||||
|
type payload struct {
|
||||||
|
DBPath string `json:"dbPath,omitempty"`
|
||||||
|
Create bool `json:"create,omitempty"`
|
||||||
|
Ids []uint `json:"ids,omitempty"`
|
||||||
|
FirstName string `json:"FirstName,omitempty"`
|
||||||
|
LastName string `json:"lastName,omitempty"`
|
||||||
|
Birthday string `json:"birthday,omitempty"`
|
||||||
|
Group string `json:"group,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
requests = append(requests,
|
||||||
|
request{Log: "open member db", Name: "open member db", Method: "POST", Path: "/v1/database/open", Payload: payload{DBPath: "test.db", Create: true}},
|
||||||
|
|
||||||
|
request{Log: "add new member", Name: "add new member", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Adrian", LastName: "Zürcher", Birthday: "23.06.1987"}},
|
||||||
|
request{Log: "add existing member", Name: "add existing member", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Adrian", LastName: "Zürcher", Birthday: "23.06.1987"}, ignoreError: true},
|
||||||
|
request{Log: "add new member", Name: "add new member", Method: "POST", Path: "/v1/members/add", Payload: payload{FirstName: "Paulina", LastName: "Zürcher", Birthday: "15.01.1991"}},
|
||||||
|
request{Log: "get members", Name: "get members", Method: "GET", Path: "/v1/members"},
|
||||||
|
request{Log: "update members", Name: "update members", Method: "POST", Path: "/v1/members/edit?id=1", Payload: []models.Member{{Group: &models.Group{Name: "testGroup"}}}},
|
||||||
|
request{Log: "get again members", Name: "get again members", Method: "GET", Path: "/v1/members"},
|
||||||
|
//request{Log: "delete members", Name: "delete members", Method: "POST", Path: "/v1/members/delete", Payload: payload{Ids: []uint{2, 1}}},
|
||||||
|
request{Log: "get again members", Name: "get again members", Method: "GET", Path: "/v1/members"},
|
||||||
|
|
||||||
|
request{Log: "new event", Name: "new event", Method: "POST", Path: "/v1/events/new", Payload: models.Event{Name: "testEvent"}},
|
||||||
|
request{Log: "add new attendee", Name: "add new attendee", Method: "POST", Path: "/v1/events/attendees/add", Payload: models.Event{Attendees: []*models.Member{{Id: 26}}}},
|
||||||
|
request{Log: "add another attendee", Name: "add another attendee", Method: "POST", Path: "/v1/events/attendees/add", Payload: models.Event{Attendees: []*models.Member{{Id: 2}}}},
|
||||||
|
request{Log: "get events", Name: "get events", Method: "GET", Path: "/v1/events"},
|
||||||
|
//request{Log: "delete attendee", Name: "add delete attendee", Method: "POST", Path: "/v1/events/attendees/delete", Payload: models.Event{Attendees: []*models.Member{{FirstName: "Adi", LastName: "Züri"}}}},
|
||||||
|
request{Log: "get events", Name: "get events", Method: "GET", Path: "/v1/events"},
|
||||||
|
|
||||||
|
//request{Log: "add responsible", Name: "add responsible", Method: "POST", Path: "/v1/responsible/add", Payload: models.Responsibles{models.Responsible{Member: &models.Member{FirstName: "Adi", LastName: "Züri"}}}},
|
||||||
|
request{Log: "add another responsible", Name: "add another responsible", Method: "POST", Path: "/v1/responsible/add", Payload: models.Responsibles{models.Responsible{MemberId: 1}}},
|
||||||
|
request{Log: "add another responsible", Name: "add another responsible", Method: "POST", Path: "/v1/responsible/add", Payload: models.Responsibles{models.Responsible{MemberId: 25}}},
|
||||||
|
request{Log: "get responsible", Name: "get responsible", Method: "GET", Path: "/v1/responsible"},
|
||||||
|
//request{Log: "delete responsible id 1", Name: "delete responsible id 1", Method: "POST", Path: "/v1/responsible/delete", Payload: payload{Ids: []uint{1}}},
|
||||||
|
request{Log: "get responsible", Name: "get responsible", Method: "GET", Path: "/v1/responsible"},
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, request := range requests {
|
||||||
|
if request.Log != "" {
|
||||||
|
t.Log(request.Log)
|
||||||
|
|
||||||
|
}
|
||||||
|
var bodyReader io.Reader
|
||||||
|
if request.Payload != nil {
|
||||||
|
jsonBytes, _ := json.Marshal(request.Payload)
|
||||||
|
bodyReader = bytes.NewBuffer(jsonBytes)
|
||||||
|
}
|
||||||
|
req, _ := http.NewRequest(request.Method, request.Path, bodyReader)
|
||||||
|
if request.Cookie != nil {
|
||||||
|
req.AddCookie(request.Cookie) // attach refresh_token cookie
|
||||||
|
}
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
r.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
t.Log(request.Name+" response:", w.Body.String())
|
||||||
|
if !request.ignoreError {
|
||||||
|
assert.Equal(t, http.StatusOK, w.Code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Id int `json:"id"`
|
Id int `gorm:"primaryKey" json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `gorm:"column:name" json:"name"`
|
||||||
Date string `json:"date"`
|
Date string `gorm:"column:date" json:"date"`
|
||||||
Attendees []Person `json:"attendees"`
|
Day string `gorm:"column:day" json:"day"`
|
||||||
Count int `json:"count"`
|
Attendees []*Member `gorm:"many2many:member_events;"`
|
||||||
}
|
}
|
||||||
|
|||||||
6
models/group.go
Normal file
6
models/group.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type Group struct {
|
||||||
|
Id int `gorm:"primaryKey" json:"id"`
|
||||||
|
Name string `gorm:"column:name" json:"name"`
|
||||||
|
}
|
||||||
@@ -1,17 +1,24 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
type Member struct {
|
type Member struct {
|
||||||
Id int `json:"id,omitempty"`
|
Id int `gorm:"primaryKey" json:"id,omitempty"`
|
||||||
FirstName string `json:"firstName,omitempty"`
|
FirstName string `gorm:"column:firstName" json:"firstName,omitempty"`
|
||||||
LastName string `json:"lastName,omitempty"`
|
FirstNameHash string `gorm:"column:firstNameHash" json:"-"`
|
||||||
Birthday string `json:"birthday,omitempty"`
|
LastName string `gorm:"column:lastName" json:"lastName,omitempty"`
|
||||||
Address string `json:"address,omitempty"`
|
LastNameHash string `gorm:"column:lastNameHash" json:"-"`
|
||||||
Zip string `json:"zip,omitempty"`
|
Birthday string `gorm:"column:birthday" json:"birthday,omitempty"`
|
||||||
Town string `json:"town,omitempty"`
|
BirthdayHash string `gorm:"column:birthdayHash" json:"-"`
|
||||||
Phone string `json:"phone,omitempty"`
|
Address string `gorm:"column:address" json:"address,omitempty"`
|
||||||
Email string `json:"email,omitempty"`
|
Zip string `gorm:"column:zip" json:"zip,omitempty"`
|
||||||
FirstVisit string `json:"firstVisit,omitempty"`
|
Town string `gorm:"column:town" json:"town,omitempty"`
|
||||||
LastVisit string `json:"lastVisit,omitempty"`
|
Phone string `gorm:"column:phone" json:"phone,omitempty"`
|
||||||
Group string `json:"group,omitempty"`
|
Email string `gorm:"column:email" json:"email,omitempty"`
|
||||||
ResponsiblePerson string `json:"responsiblePerson,omitempty"`
|
FirstVisit string `gorm:"column:firstVisit" json:"firstVisit,omitempty"`
|
||||||
|
LastVisit string `gorm:"column:lastVisit" json:"lastVisit,omitempty"`
|
||||||
|
GroupId *int `json:"GroupId,omitempty"`
|
||||||
|
Group *Group `gorm:"foreignKey:GroupId" json:"group,omitempty"`
|
||||||
|
ResponsibleId *int `json:"ResponsibleId,omitempty"`
|
||||||
|
Responsible *Member `gorm:"foreignKey:ResponsibleId" json:"responsible,omitempty"`
|
||||||
|
Comment string `gorm:"column:comment" json:"comment,omitempty"`
|
||||||
|
Events []*Event `gorm:"many2many:member_events;" `
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
type Person struct {
|
|
||||||
Id int `json:"id,omitEmpty"`
|
|
||||||
FirstName string `json:"firstName"`
|
|
||||||
LastName string `json:"lastName"`
|
|
||||||
}
|
|
||||||
9
models/responsible.go
Normal file
9
models/responsible.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type Responsible struct {
|
||||||
|
Id uint `gorm:"primaryKey"`
|
||||||
|
MemberId uint
|
||||||
|
Member *Member `gorm:"foreignKey:MemberId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Responsibles []Responsible
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -25,3 +26,11 @@ func IsValidBirthday(birthday string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetCurrentTime(loc *time.Location) string {
|
||||||
|
return time.Now().In(loc).Format("2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCurrentDay(loc *time.Location) string {
|
||||||
|
return fmt.Sprint(time.Now().In(loc).Weekday())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user