add golang backend for login an d webserver

This commit is contained in:
Adrian Zürcher
2025-05-28 21:48:30 +02:00
parent c8b27813ae
commit 8cfb720c42
15 changed files with 761 additions and 0 deletions

202
backend/login/login.go Normal file
View File

@@ -0,0 +1,202 @@
package login
import (
"backend/dbRequest"
"backend/login/models"
"backend/utils"
"database/sql"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
_ "modernc.org/sqlite"
)
func (lm *LoginManager) AddUser(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
user := models.User{}
err = json.Unmarshal(body, &user)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
if !user.IsValid() {
c.JSON(http.StatusBadRequest, gin.H{
"error": "user empty",
})
return
}
db, err := sql.Open(lm.dbType, lm.dbFile)
if dbRequest.CheckDBError(c, user.Name, err) {
return
}
defer db.Close()
var exists bool
if err := db.QueryRow(dbRequest.DBUserLookup, user.Name).Scan(&exists); dbRequest.CheckDBError(c, user.Name, err) {
return
}
if exists {
c.JSON(http.StatusOK, gin.H{
"error": fmt.Sprintf("user '%s' exists already", user.Name),
})
return
}
hash, err := utils.HashPassword(user.Password)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
if _, err := db.Exec(dbRequest.DBNewUser, user.Name, hash); dbRequest.CheckDBError(c, user.Name, err) {
return
}
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("user '%s' successfully added", user.Name),
})
}
func (lm *LoginManager) RemoveUser(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
user := models.User{}
err = json.Unmarshal(body, &user)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
if !user.IsValid() {
c.JSON(http.StatusBadRequest, gin.H{
"error": "user empty",
})
return
}
db, err := sql.Open(lm.dbType, lm.dbFile)
if dbRequest.CheckDBError(c, user.Name, err) {
return
}
defer db.Close()
var storedPassword string
if err := db.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&storedPassword); dbRequest.CheckDBError(c, user.Name, err) {
return
}
if !utils.CheckPassword(user.Password, storedPassword) {
c.JSON(http.StatusBadRequest, gin.H{
"error": "wrong password",
})
return
}
if _, err := db.Exec(dbRequest.DBRemoveUser, user.Name); dbRequest.CheckDBError(c, user.Name, err) {
return
}
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("user '%s' successfully removed", user.Name),
})
}
func (lm *LoginManager) Login(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
user := models.User{}
err = json.Unmarshal(body, &user)
if err != nil {
fmt.Println(2)
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
if !user.IsValid() {
c.JSON(http.StatusBadRequest, gin.H{
"error": "user empty",
})
return
}
db, err := sql.Open(lm.dbType, lm.dbFile)
if dbRequest.CheckDBError(c, user.Name, err) {
return
}
defer db.Close()
var storedPassword string
if err := db.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&storedPassword); dbRequest.CheckDBError(c, user.Name, err) {
return
}
if !utils.CheckPassword(user.Password, storedPassword) {
fmt.Println(2, user.Password)
c.JSON(http.StatusBadRequest, gin.H{
"error": "wrong password",
})
return
}
// Create token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": user.Name,
"exp": time.Now().Add(time.Hour * 72).Unix(), // expires in 72h
})
secret, err := utils.GenerateJWTSecret(32) // 32 bytes = 256 bits
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "error generate jwt token"})
return
}
// Sign and get the complete encoded token as a string
tokenString, err := token.SignedString(secret)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Could not generate token"})
return
}
c.JSON(http.StatusOK, models.User{
Name: user.Name,
Token: tokenString,
})
}

49
backend/login/manager.go Normal file
View File

@@ -0,0 +1,49 @@
package login
import (
"backend/dbRequest"
"backend/utils"
"database/sql"
"fmt"
"os"
)
type LoginManager struct {
dbType string
dbFile string
}
func NewLoginManager(dir string) (*LoginManager, error) {
if dir == "" {
dir = "."
}
var typ string = "sqlite"
var file string = fmt.Sprintf("%s/user.db", dir)
if _, err := os.Stat(file); err != nil {
db, err := sql.Open(typ, file)
if err != nil {
return nil, err
}
defer db.Close()
_, err = db.Exec(dbRequest.DBCreate)
if err != nil {
return nil, err
}
hash, err := utils.HashPassword("tecamino@2025")
if err != nil {
return nil, err
}
_, err = db.Exec(dbRequest.DBNewUser, "admin", hash)
if err != nil {
return nil, err
}
}
return &LoginManager{
dbType: typ,
dbFile: file,
}, nil
}

View File

@@ -0,0 +1,11 @@
package models
type User struct {
Name string `json:"user"`
Password string `json:"password,omitempty"`
Token string `json:"token,omitempty"`
}
func (u *User) IsValid() bool {
return u.Name != ""
}