casbin / xorm-adapter

Xorm adapter for Casbin
https://github.com/casbin/casbin
Apache License 2.0
384 stars 58 forks source link

SavePolicy reports "No element on slice when insert" error when the model's policy is null #40

Closed liupzmin closed 3 years ago

liupzmin commented 3 years ago

hi, I am using SavePolicy of enforcer in my program to save policies manully. but I get an xorm error which is ErrNoElementsOnSlice when the model is null. I found the following code:

// SavePolicy saves policy to database.
func (a *Adapter) SavePolicy(model model.Model) error {
    err := a.dropTable()
    if err != nil {
        return err
    }
    err = a.createTable()
    if err != nil {
        return err
    }

    lines := make([]*CasbinRule, 0, 64)

    for ptype, ast := range model["p"] {
        for _, rule := range ast.Policy {
            line := a.genPolicyLine(ptype, rule)
            lines = append(lines, line)
        }
    }

    for ptype, ast := range model["g"] {
        for _, rule := range ast.Policy {
            line := a.genPolicyLine(ptype, rule)
            lines = append(lines, line)
        }
    }

    _, err = a.engine.Insert(&lines)

    return err
}

I want to know whether we can add a length check about lines in this function to solve the problem?

hsluoyz commented 3 years ago

@liupzmin you need to check whether model is null before calling this function.

liupzmin commented 3 years ago

@liupzmin you need to check whether model is null before calling this function.

@hsluoyz Please, correct me if I'm wrong. Consider this scenario, my goal is to remove all policies, which is not possible in the current situation.

hsluoyz commented 3 years ago

@liupzmin you should call ClearPolicy() first, then SavePolicy()

liupzmin commented 3 years ago

@liupzmin you should call ClearPolicy() first, then SavePolicy()

I don't understand what you mean. the ClearPolicy() just set policy to nil, SavePolicy() will collect the lines of policies, and then insert it to db, the slice of lines that collected by SavePolicy() is empty now, this is why a.engine.Insert(&lines) reports error .

hsluoyz commented 3 years ago

@closetool

hsluoyz commented 3 years ago

@liupzmin did you try what I said? Does it work?

liupzmin commented 3 years ago

@liupzmin did you try what I said? Does it work?

yes, I have tried, Please see the attachment screenshot:

casbin

liupzmin commented 3 years ago

Although the final logical result is correct, I mean, I don't want to get an error.

liupzmin commented 3 years ago

may be we can do this:

    for ptype, ast := range model["p"] {
        for _, rule := range ast.Policy {
            line := a.genPolicyLine(ptype, rule)
            lines = append(lines, line)
        }
    }

    for ptype, ast := range model["g"] {
        for _, rule := range ast.Policy {
            line := a.genPolicyLine(ptype, rule)
            lines = append(lines, line)
        }
    }
        // check here to  avoid inserting empty slice
        if len(lines) <= 0 {
        return nil
        }

        _, err = a.engine.Insert(&lines)

        return err
hsluoyz commented 3 years ago

@tson1111