login
This commit is contained in:
parent
5a987b898b
commit
8e0e53af0d
@ -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
37
api/auth/middleware.go
Normal 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) {
|
||||
|
||||
}
|
@ -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{
|
||||
|
@ -21,6 +21,7 @@ type Config struct {
|
||||
API struct {
|
||||
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
58
database/auth/login.go
Normal 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
|
||||
}
|
23
database/auth/middleware.go
Normal file
23
database/auth/middleware.go
Normal 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
|
||||
}
|
@ -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
1
go.mod
@ -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
2
go.sum
@ -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=
|
||||
|
@ -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"`
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user