This commit is contained in:
BENEDEK László 2024-10-10 21:41:49 +02:00
parent 5a987b898b
commit 8e0e53af0d
10 changed files with 198 additions and 8 deletions

View File

@ -1,7 +1,43 @@
package auth
import "github.com/gin-gonic/gin"
import (
"net/http"
"git.tek.govt.hu/dowerx/szoe-pontok/config"
"git.tek.govt.hu/dowerx/szoe-pontok/database/auth"
"git.tek.govt.hu/dowerx/szoe-pontok/model"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
func Login(c *gin.Context) {
var user model.User
if c.MustBindWith(&user, binding.Form) != nil {
return
}
val := validator.New(validator.WithRequiredStructEnabled())
if err := val.Struct(user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": http.StatusBadRequest,
"error": err.Error(),
})
return
}
if token, err := auth.Login(user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": http.StatusBadRequest,
"error": err.Error(),
})
return
} else {
c.SetCookie("token", token, config.GetConfig().API.TokenLife, "/", "", false, false)
c.JSON(http.StatusOK, gin.H{
"status": http.StatusOK,
"token": token,
})
}
}

37
api/auth/middleware.go Normal file
View File

@ -0,0 +1,37 @@
package auth
import (
"net/http"
"git.tek.govt.hu/dowerx/szoe-pontok/database/auth"
"github.com/gin-gonic/gin"
)
func LoggedIn(c *gin.Context) {
token, err := c.Cookie("token")
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{
"status": http.StatusUnauthorized,
"error": "missing token",
})
c.Abort()
return
}
neptun, err := auth.LoggedIn(token)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{
"status": http.StatusUnauthorized,
"error": "not logged in",
})
c.Abort()
return
}
c.Set("neptun", neptun)
}
func IsAdmin(c *gin.Context) {
}

View File

@ -25,6 +25,19 @@ func Listen(address string, path string) {
apiAuth.POST("register", auth.Register)
apiAuth.GET("login", auth.Login)
}
apiTest := api.Group("test").Use(auth.LoggedIn)
{
apiTest.GET("logged_in", func(c *gin.Context) {
neptun, _ := c.Get("neptun")
c.JSON(http.StatusOK, gin.H{
"status": http.StatusOK,
"message": "if you see this you are logged in",
"neptun": neptun,
})
})
}
}
server := &http.Server{

View File

@ -19,8 +19,9 @@ type Config struct {
Redis redis.Options
API struct {
Address string
Path string
Address string
Path string
TokenLife int
}
}
@ -42,6 +43,7 @@ func GetConfig() *Config {
flag.StringVar(&config.API.Address, "api-address", ":5000", "API address")
flag.StringVar(&config.API.Path, "api-path", "api", "API path root")
flag.IntVar(&config.API.TokenLife, "api-token-life", 24*60*60, "API login token lifetime in seconds")
if err := envflag.Parse(); err != nil {
panic(err)

58
database/auth/login.go Normal file
View File

@ -0,0 +1,58 @@
package auth
import (
"errors"
"time"
"git.tek.govt.hu/dowerx/szoe-pontok/config"
"git.tek.govt.hu/dowerx/szoe-pontok/database"
"git.tek.govt.hu/dowerx/szoe-pontok/model"
"golang.org/x/crypto/bcrypt"
"golang.org/x/exp/rand"
)
func generateToken(length int) string {
validRunes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789")
token := make([]rune, length)
for i := range token {
token[i] = validRunes[rand.Intn(len(validRunes))]
}
return string(token)
}
func Login(user model.User) (string, error) {
db := database.GetDB()
rows, err := db.NamedQuery(`select "password" from "user" where "neptun" = :neptun and "email" = :email`,
map[string]interface{}{
"neptun": user.Neptun,
"email": user.Email,
})
if err != nil {
return "", err
}
if !rows.Next() {
return "", errors.New("no such user")
}
var hash string
if err = rows.Scan(&hash); err != nil {
return "", err
}
if bcrypt.CompareHashAndPassword([]byte(hash), []byte(user.Password)) != nil {
return "", errors.New("wrong password")
}
token := generateToken(32)
rdb, ctx := database.GetRDB()
result := rdb.Set(ctx, token, user.Neptun, time.Duration(config.GetConfig().API.TokenLife)*time.Second)
if result.Err() != nil {
return "", result.Err()
}
return token, nil
}

View File

@ -0,0 +1,23 @@
package auth
import (
"git.tek.govt.hu/dowerx/szoe-pontok/database"
"github.com/redis/go-redis/v9"
)
func LoggedIn(token string) (string, error) {
rdb, ctx := database.GetRDB()
result, err := rdb.Get(ctx, token).Result()
if err == redis.Nil {
return "", err
}
return result, nil
}
func IsAdmin(neptun string) error {
// db := database.GetDB()
return nil
}

View File

@ -1,11 +1,13 @@
package database
import (
"context"
"fmt"
"git.tek.govt.hu/dowerx/szoe-pontok/config"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
"github.com/redis/go-redis/v9"
)
var db *sqlx.DB
@ -22,3 +24,19 @@ func GetDB() *sqlx.DB {
return db
}
var rdb *redis.Client
var ctx context.Context
func GetRDB() (*redis.Client, context.Context) {
if rdb == nil {
ctx = context.Background()
rdb = redis.NewClient(&config.GetConfig().Redis)
if err := rdb.Ping(ctx).Err(); err != nil {
panic(err)
}
}
return rdb, ctx
}

1
go.mod
View File

@ -32,6 +32,7 @@ require (
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect

2
go.sum
View File

@ -83,6 +83,8 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -10,9 +10,9 @@ type User struct {
type Task struct {
ID int `db:"id"`
Description string `db:"description" form:"description"`
Points int `db:"points" form:"points" validate:"required"`
Recipient string `db:"recipient" form:"recipient" validate:"required,len=6"`
Issuer string `db:"issuer" form:"issuer" validate:"required,len=6"`
Date time.Time `db:"date"`
Description string `db:"description" form:"description" json:"description"`
Points int `db:"points" form:"points" json:"points" validate:"required"`
Recipient string `db:"recipient" form:"recipient" json:"recipient" validate:"required,len=6"`
Issuer string `db:"issuer" form:"issuer" json:"issuer" validate:"required,len=6"`
CreatedDate time.Time `db:"created_date" json:"created_date"`
}