Start of migration

This commit is contained in:
Max 2024-12-15 16:53:34 +03:00
parent bbf33b8c7e
commit 86f599e88d
3 changed files with 213 additions and 0 deletions

View File

@ -0,0 +1,112 @@
package middleware
import (
"enshi/ABAC/rules"
"fmt"
"github.com/gin-gonic/gin"
)
type WorkRule struct {
Rules []rules.RuleFunction
MustBeCompleted int
}
type Policy func(c *gin.Context) (bool, []error)
type RuleSets map[string]rules.RuleFunction
type RulesToCheck map[string]WorkRule
type MiddlewareProvider struct {
Policies map[string]Policy
}
func CreateRuleFunction(rulesToCheck []rules.RuleFunction, mustBeCompleted int) rules.RuleFunction {
return func(c *gin.Context) (bool, []error) {
isAllowed, errors := rules.CheckRules(
c,
rulesToCheck,
mustBeCompleted,
)
return isAllowed, errors
}
}
func CreatePolicy(ruleSets RuleSets) Policy {
return func(c *gin.Context) (bool, []error) {
targetAction, exists := c.Get("target")
if !exists {
return false, nil
}
for action, rule := range ruleSets {
if action == targetAction {
return rules.CheckRule(c, rule)
}
}
return false, nil
}
}
// Accepts
//
// ruleSetName -> `string` name of the policy(like old one "postPolicy" etc.)
//
// rulesToCheck -> map where keys like ["GET", "POST", etc.] and values are struct of type {rules: [list of rules to check], mustBeCompleted: how many rules must be completed from the list before}
func (m *MiddlewareProvider) RegisterPolicy(
ruleSetName string,
rulesToCheck RulesToCheck,
) error {
for k := range m.Policies {
if k == ruleSetName {
return fmt.Errorf("name: " + ruleSetName + " already exists")
}
}
newRuleSets := make(RuleSets)
for setName, workRule := range rulesToCheck {
newRuleFunction := CreateRuleFunction(workRule.Rules, workRule.MustBeCompleted)
newRuleSets[setName] = newRuleFunction
}
newPolicy := CreatePolicy(newRuleSets)
m.Policies[ruleSetName] = newPolicy
return nil
}
func (m *MiddlewareProvider) GetMiddleware(
policyName string,
) gin.HandlerFunc {
return func(c *gin.Context) {
validName := false
for key := range m.Policies {
if key == policyName {
validName = true
}
}
if !validName {
c.Abort()
fmt.Println("invalid policy name: " + policyName)
return
}
isAllowed, errors := m.Policies[policyName](c)
if rules.ShouldAbortRequest(c, isAllowed, errors) {
c.Abort()
return
}
c.Next()
}
}

View File

@ -0,0 +1,30 @@
package middleware
import (
"github.com/gin-gonic/gin"
)
const (
GET = "GET"
PUT = "PUT"
POST = "POST"
DELETE = "DELETE"
)
func TargetMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
switch c.Request.Method {
case "DELETE":
c.Set("target", DELETE)
case "PUT":
c.Set("target", PUT)
case "POST":
c.Set("target", POST)
case "GET":
c.Set("target", DELETE)
}
c.Next()
}
}

View File

@ -1,6 +1,8 @@
package routes package routes
import ( import (
globalrules "enshi/ABAC/GlobalRules"
"enshi/ABAC/rules"
"enshi/middleware" "enshi/middleware"
"enshi/middleware/getters" "enshi/middleware/getters"
"enshi/routes/authRoutes" "enshi/routes/authRoutes"
@ -16,6 +18,10 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
const (
POST_MIDDLEWARE = "post_middleware"
)
func testCookie(c *gin.Context) { func testCookie(c *gin.Context) {
cock, _ := c.Cookie("auth_cookie") cock, _ := c.Cookie("auth_cookie")
c.IndentedJSON(http.StatusOK, gin.H{"token": "SLESAR' U STASA " + strings.Split(cock, "_")[0]}) c.IndentedJSON(http.StatusOK, gin.H{"token": "SLESAR' U STASA " + strings.Split(cock, "_")[0]})
@ -43,7 +49,72 @@ func testAuth(c *gin.Context) {
} }
func SetupRotes(g *gin.Engine) error { func SetupRotes(g *gin.Engine) error {
middlewareProvider := middleware.MiddlewareProvider{
Policies: make(map[string]middleware.Policy),
}
var policies = map[string]middleware.RulesToCheck{
POST_MIDDLEWARE: {
middleware.GET: {
Rules: make([]rules.RuleFunction, 0),
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
},
middleware.POST: {
Rules: []rules.RuleFunction{
globalrules.AuthorizedRule,
},
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
},
middleware.PUT: {
Rules: []rules.RuleFunction{
globalrules.AuthorizedRule,
globalrules.IsOwnerOfThePostRule,
},
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
},
middleware.DELETE: {
Rules: []rules.RuleFunction{
globalrules.AuthorizedRule,
globalrules.IsOwnerOfThePostRule,
globalrules.IsAdminRule,
},
MustBeCompleted: 2,
},
},
}
for middlewareName, rulesToCheck := range policies {
middlewareProvider.RegisterPolicy(middlewareName, rulesToCheck)
}
g.Use(middleware.CORSMiddleware()) g.Use(middleware.CORSMiddleware())
g.Use(middleware.TargetMiddleware())
testGroup := g.Group("/test/")
testGroup.Use(middlewareProvider.GetMiddleware(POST_MIDDLEWARE))
testGroup.GET(
"posts/:post-id",
postsRoutes.GetPost,
)
testGroup.GET(
"posts/random",
postsRoutes.GetRandomPost,
)
testGroup.PUT(
"posts/:post-id",
postsRoutes.UpdatePost,
)
testGroup.POST(
"posts",
postsRoutes.CreatePost,
)
testGroup.DELETE(
"posts/:post-id",
postsRoutes.DeletePost,
)
// Free group routes // Free group routes
freeGroup := g.Group("/") freeGroup := g.Group("/")