Added access checking middleware
Added URLAccessRepository Refactor
This commit is contained in:
@@ -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)
|
||||
|
||||
55
src/domain/repository/role_repository.go
Normal file
55
src/domain/repository/role_repository.go
Normal 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
|
||||
}
|
||||
58
src/domain/repository/url_access_repository.go
Normal file
58
src/domain/repository/url_access_repository.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
10
src/go.sum
10
src/go.sum
@@ -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=
|
||||
|
||||
25
src/internal/server/access_handler.go
Normal file
25
src/internal/server/access_handler.go
Normal 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)
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user