casbin / gorm-adapter

GORM adapter for Casbin, see extended version of GORM Adapter Ex at: https://github.com/casbin/gorm-adapter-ex
https://github.com/casbin/casbin
Apache License 2.0
678 stars 206 forks source link

Understanding how to correctly update policies in a database #211

Closed andrerav closed 1 year ago

andrerav commented 1 year ago

Hi,

I have inherited a legacy Go program that uses casbin and gorm-adapter to update a set of policies in a database. The program is basically sequenced as follows:


    rules = [][]string { ... } 
    roles = [][]string { ... } 
    users = [][]string { ... } 

    enforcer.GetAdapter().(*gormadapter.Adapter).Transaction(enforcer, func(e casbin.IEnforcer) error {
        var userGroups [][]string
        namedGroupingPolices := enforcer.GetNamedGroupingPolicy("g")

        for _, namedGroupingPolicy := range namedGroupingPolices {
            if strings.Contains(namedGroupingPolicy[0], "user:") {
                userGroups = append(userGroups, namedGroupingPolicy)
            }
        }

        gormDB.Exec("DELETE FROM casbin_rule")

        enforcer.LoadPolicy()
        enforcer.AddNamedPolicies("p", rules)
        enforcer.AddNamedGroupingPolicies("g", roles)
        enforcer.AddNamedGroupingPolicies("g", userGroups)
        enforcer.AddNamedGroupingPolicies("g", users)
        return nil
    })
    if err != nil {
        fmt.Printf("Transaction failed: %+v\n", err)
        return
    }

Now, the obvious problem I am trying to fix is that the line with the DELETE sql statement is being executed outside the transaction. However, I don't understand why the DELETE statement is there. All I know is that if I simply remove it, this program will not update the policies in the database.

What is the recommended practice to do what this program is supposed to do, given that you hopefully understand what this program is trying to achieve?

(Sorry for posting this as an issue, but you don't have a discussion section here)

casbin-bot commented 1 year ago

@tangyang9464 @JalinWang @imp2002

hsluoyz commented 1 year ago

@PokIsemaine

weloe commented 1 year ago

about use transaction, you can use db := enforcer.GetAdapter().(*gormadapter.Adapter).GetDb() to exec sql like https://github.com/casbin/casbin/issues/1205#issuecomment-1501221142 about update policies, can use update api

// UpdatableAdapter is the interface for Casbin adapters with add update policy function.
type UpdatableAdapter interface {
    Adapter
    // UpdatePolicy updates a policy rule from storage.
    // This is part of the Auto-Save feature.
    UpdatePolicy(sec string, ptype string, oldRule, newRule []string) error
    // UpdatePolicies updates some policy rules to storage, like db, redis.
    UpdatePolicies(sec string, ptype string, oldRules, newRules [][]string) error
    // UpdateFilteredPolicies deletes old rules and adds new rules.
    UpdateFilteredPolicies(sec string, ptype string, newRules [][]string, fieldIndex int, fieldValues ...string) ([][]string, error)
}
andrerav commented 1 year ago

Fantastic @weloe, thank you very much. On the short term, using GetDb() solved my problem. On the longer term, I will definitely try to rewrite this into using UpdatableAdapter instead.