Added access checking middleware

Added URLAccessRepository
Refactor
This commit is contained in:
2025-10-22 10:53:20 +02:00
parent 89b665c3d9
commit 662a9b7ffd
11 changed files with 192 additions and 34 deletions

View File

@@ -2,8 +2,8 @@ package repository
import entity "git.ego.freeddns.org/egommerce/api-entities/identity/entity"
type UserRepositoryInterface interface {
GetByID(id string) (*entity.User, error)
type RepositoryInterface interface {
FindByID(id string) (*entity.User, error)
Create(user *entity.User) (*entity.User, error)
Update(user *entity.User) (*entity.User, error)
Delete(id int64) (bool, error)

View File

@@ -0,0 +1,55 @@
package repository
import (
"context"
"errors"
entity "git.ego.freeddns.org/egommerce/api-entities/identity/entity"
"github.com/jackc/pgx/v5/pgxpool"
)
type RoleRepository struct {
db *pgxpool.Pool
}
func NewRoleRepository(db *pgxpool.Pool) *RoleRepository {
return &RoleRepository{db}
}
func (r *RoleRepository) FindByID(id string) (*entity.Role, error) {
var role entity.Role
sql := `SELECT id, roles, url FROM identity.roles WHERE id=$1 LIMIT 1`
err := r.db.QueryRow(context.Background(), sql, id).
Scan(&role.ID, &role.Roles, &role.URL)
if err != nil {
return nil, errors.New("failed to fetch role from DB: " + err.Error())
}
return &role, nil
}
func (r *RoleRepository) Create(role *entity.Role) (string, error) {
var id string
// sql := `INSERT INTO identity.users(email, username, password) VALUES($1, $2, $3) LIMIT 1 RETURNING id`
// err := r.db.QueryRow(context.Background(), sql, user.Email, user.Username, user.Password).Scan(&id)
// if err != nil {
// if err = db.IsDuplicatedRow(err); err != nil {
// return "", errors.New("username/email is already taken")
// }
// return "", errors.New("db error: " + err.Error())
// }
return id, nil
}
func (r *RoleRepository) Update(role *entity.Role) (*entity.Role, error) {
return &entity.Role{}, nil
}
func (r *RoleRepository) Delete(id int64) (bool, error) {
return true, nil
}

View File

@@ -0,0 +1,58 @@
package repository
import (
"context"
"errors"
entity "git.ego.freeddns.org/egommerce/api-entities/identity/entity"
"github.com/jackc/pgx/v5/pgxpool"
)
type URLAccessRepository struct {
db *pgxpool.Pool
}
func NewURLAccessRepository(db *pgxpool.Pool) *URLAccessRepository {
return &URLAccessRepository{db}
}
func (r *URLAccessRepository) FindByID(id string) (*entity.URLAccess, error) {
var urlAccess entity.URLAccess
sql := `SELECT id, roles, url, service FROM identity.url_access WHERE id=$1 LIMIT 1`
err := r.db.QueryRow(context.Background(), sql, id).
Scan(&urlAccess.ID, &urlAccess.Roles, &urlAccess.URL, &urlAccess.Service)
if err != nil {
return nil, errors.New("failed to fetch url_access from DB: " + err.Error())
}
return &urlAccess, nil
}
func (r *URLAccessRepository) Create(role *entity.URLAccess) (string, error) {
var id string
return id, nil
}
func (r *URLAccessRepository) Update(role *entity.URLAccess) (*entity.URLAccess, error) {
return &entity.URLAccess{}, nil
}
func (r *URLAccessRepository) Delete(id int64) (bool, error) {
return true, nil
}
func (r *URLAccessRepository) FindByURLAndService(url, service string) (*entity.URLAccess, error) {
var urlAccess entity.URLAccess
sql := `SELECT id, roles, url FROM identity.url_access WHERE url=$1 AND service=$2 LIMIT 1`
err := r.db.QueryRow(context.Background(), sql, url, service).
Scan(&urlAccess.ID, &urlAccess.Roles, &urlAccess.URL)
if err != nil {
return nil, errors.New("failed to fetch url_access from DB: " + err.Error())
}
return &urlAccess, nil
}

View File

@@ -18,7 +18,7 @@ func NewUserRepository(db *pgxpool.Pool) *UserRepository {
return &UserRepository{db}
}
func (r *UserRepository) GetByID(id string) (*entity.User, error) {
func (r *UserRepository) FindByID(id string) (*entity.User, error) {
var user entity.User
sql := `SELECT id, username, password, email, created_at FROM identity.users WHERE id=$1 LIMIT 1`
@@ -31,19 +31,6 @@ func (r *UserRepository) GetByID(id string) (*entity.User, error) {
return &user, nil
}
func (r *UserRepository) GetByUsername(login string) (*entity.User, error) {
var user entity.User
sql := `SELECT id, username, password, email, created_at FROM identity.users WHERE username=$1 LIMIT 1`
err := r.db.QueryRow(context.Background(), sql, login).
Scan(&user.ID, &user.Username, &user.Password, &user.Email, &user.CreatedAt)
if err != nil {
return nil, errors.New("failed to fetch user from DB: " + err.Error())
}
return &user, nil
}
func (r *UserRepository) Create(user *entity.User) (string, error) {
var id string
@@ -67,3 +54,16 @@ func (r *UserRepository) Update(user *entity.User) (*entity.User, error) {
func (r *UserRepository) Delete(id int64) (bool, error) {
return true, nil
}
func (r *UserRepository) FindByUsername(login string) (*entity.User, error) {
var user entity.User
sql := `SELECT id, username, password, email, created_at FROM identity.users WHERE username=$1 LIMIT 1`
err := r.db.QueryRow(context.Background(), sql, login).
Scan(&user.ID, &user.Username, &user.Password, &user.Email, &user.CreatedAt)
if err != nil {
return nil, errors.New("failed to fetch user from DB: " + err.Error())
}
return &user, nil
}

View File

@@ -5,11 +5,12 @@ go 1.24.0
toolchain go1.24.1
require (
git.ego.freeddns.org/egommerce/api-entities v0.3.11
git.ego.freeddns.org/egommerce/api-entities v0.3.17
git.ego.freeddns.org/egommerce/go-api-pkg v0.4.9
github.com/go-pg/migrations/v8 v8.1.0
github.com/go-pg/pg/v10 v10.15.0
github.com/go-redis/redis/v8 v8.11.5
github.com/gofiber/contrib/jwt v1.1.2
github.com/gofiber/fiber/v2 v2.52.9
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.6.0
@@ -18,12 +19,14 @@ require (
)
require (
github.com/MicahParks/keyfunc/v2 v2.1.0 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-pg/zerochecker v0.2.0 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect

View File

@@ -1,9 +1,11 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
git.ego.freeddns.org/egommerce/api-entities v0.3.11 h1:WpBCVZ4ND69oxDRlJOOd0qbX4hN7xDIl9ViVT2OqEsw=
git.ego.freeddns.org/egommerce/api-entities v0.3.11/go.mod h1:IqynARw+06GOm4eZGZuepmbi7bUxWBnOB4jd5cI7jf8=
git.ego.freeddns.org/egommerce/api-entities v0.3.17 h1:AEnTwJseSqd7VwG74/QBNb3dv050RdMCQBeQF62WJHE=
git.ego.freeddns.org/egommerce/api-entities v0.3.17/go.mod h1:IqynARw+06GOm4eZGZuepmbi7bUxWBnOB4jd5cI7jf8=
git.ego.freeddns.org/egommerce/go-api-pkg v0.4.9 h1:Y9MisGDhl/ti4gsegl9MC7KoY2aHuyA0LvIESPoiPkE=
git.ego.freeddns.org/egommerce/go-api-pkg v0.4.9/go.mod h1:Q4onxocNdFhzD9QnQK3ubd68chbJPexjDraEHoIEN3Y=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/MicahParks/keyfunc/v2 v2.1.0 h1:6ZXKb9Rp6qp1bDbJefnG7cTH8yMN1IC/4nf+GVjO99k=
github.com/MicahParks/keyfunc/v2 v2.1.0/go.mod h1:rW42fi+xgLJ2FRRXAfNx9ZA8WpD4OeE/yHVMteCkw9k=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -34,10 +36,14 @@ github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4
github.com/go-pg/zerochecker v0.2.0/go.mod h1:NJZ4wKL0NmTtz0GKCoJ8kym6Xn/EQzXRl2OnAe7MmDo=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/gofiber/contrib/jwt v1.1.2 h1:GmWnOqT4A15EkA8IPXwSpvNUXZR4u5SMj+geBmyLAjs=
github.com/gofiber/contrib/jwt v1.1.2/go.mod h1:CpIwrkUQ3Q6IP8y9n3f0wP9bOnSKx39EDp2fBVgMFVk=
github.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=

View File

@@ -0,0 +1,25 @@
package server
import (
domain "git.ego.freeddns.org/egommerce/identity-service/domain/repository"
"git.ego.freeddns.org/egommerce/identity-service/internal/service"
"github.com/gofiber/fiber/v2"
)
func (s *Server) AccessHandlerFn(c *fiber.Ctx) error {
url, srvName := c.Query("q"), c.Query("srv")
urlRepo := domain.NewURLAccessRepository(s.GetDatabase())
userRepo := domain.NewUserRepository(s.GetDatabase())
authSrv := service.NewAuthService(userRepo, s.GetCache())
authSrv.VerifyToken("asd")
urlAcc, err := urlRepo.FindByURLAndService(url, srvName)
if err != nil {
return s.Error(c, fiber.StatusBadRequest, "unable to fetch requested url data")
}
return c.JSON(urlAcc.Roles)
}

View File

@@ -3,6 +3,8 @@ package server
import (
"log"
cnf "git.ego.freeddns.org/egommerce/go-api-pkg/config"
jwt "github.com/gofiber/contrib/jwt"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
)
@@ -29,25 +31,25 @@ func LoggingMiddleware() func(c *fiber.Ctx) error {
func XRequestIDMiddleware() func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
requestID := uuid.New().String()
c.Set("X-Request-ID", requestID)
c.Set("X-Request-ID", uuid.New().String())
return c.Next()
}
}
// JWTProtected func for specify routes group with JWT authentication.
// See: https://github.com/gofiber/jwt
// func JWTProtected() func(*fiber.Ctx) error {
// // Create config for JWT authentication middleware.
// config := jwt.Config{
// SigningKey: []byte(baseCnf.GetEnv("JWT_ACCESS_TOKEN_SECRET_KEY", "FallbackAccessTokenSecret")),
// ContextKey: "jwt", // used in private routes
// ErrorHandler: jwtError,
// }
func JWTProtected(s *Server) func(c *fiber.Ctx) error {
secret := []byte(cnf.GetEnv("JWT_ACCESS_TOKEN_SECRET_KEY", "FallbackAccessTokenSecret"))
// return jwt.New(config)
// }
return func(c *fiber.Ctx) error {
return jwt.New(jwt.Config{
SigningKey: jwt.SigningKey{Key: secret},
ContextKey: "jwt",
ErrorHandler: func(c *fiber.Ctx, err error) error {
return s.Error(c, fiber.StatusUnauthorized, "unauthorized")
},
})(c)
}
}
// func jwtError(c *fiber.Ctx, err error) error {
// // Return status 400 Bad Request and failed authentication error.

View File

@@ -22,5 +22,6 @@ func SetupRouter(s *Server) {
s.Group("/v1").
Post("/login", s.LoginHandlerFn).
Post("/refresh", s.RefreshHandlerFn).
Post("/register", s.RegisterHandlerFn)
Post("/register", s.RegisterHandlerFn).
Get("/access", JWTProtected(s), s.AccessHandlerFn)
}

View File

@@ -36,7 +36,7 @@ func NewAuthService(userRepo *domain.UserRepository, cache *redis.Client) *Auth
}
func (a *Auth) Login(login, passwd string) (string, error) {
user, err := a.userRepo.GetByUsername(login)
user, err := a.userRepo.FindByUsername(login)
if err != nil {
// if err = database.NoRowsInQuerySet(err); err != nil {
// return "", errors.New("no user found")
@@ -75,6 +75,11 @@ func (a *Auth) RefreshToken(accessToken string) (string, error) {
return newAccessToken, nil
}
func (a *Auth) VerifyToken(token string) (string, error) {
return token, nil
}
func (a *Auth) Register(email, login, passwd string) (string, error) {
passwd, _ = passSrv.Hash(passwd)

View File

@@ -48,6 +48,9 @@ type JWT struct {
}
func (s *JWT) CreateAccessToken(id string) (string, error) {
fmt.Println(time.Now().Add(s.accessTokenExpireTime).Unix())
fmt.Println(s.accessTokenExpireTime)
claims := &jwt.StandardClaims{
Subject: id,
IssuedAt: time.Now().Unix(),