github.com/RevenueMonster/sqlike@v1.0.6/plugin/casbin/casbin.go (about)

     1  package casbin
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"strings"
     7  
     8  	"github.com/RevenueMonster/sqlike/sql/expr"
     9  	"github.com/RevenueMonster/sqlike/sqlike"
    10  	"github.com/RevenueMonster/sqlike/sqlike/actions"
    11  	"github.com/RevenueMonster/sqlike/sqlike/indexes"
    12  	"github.com/RevenueMonster/sqlike/sqlike/options"
    13  	"github.com/RevenueMonster/sqlike/sqlike/primitive"
    14  	"github.com/casbin/casbin/v2/model"
    15  	"github.com/casbin/casbin/v2/persist"
    16  )
    17  
    18  // Adapter :
    19  type Adapter struct {
    20  	ctx      context.Context
    21  	table    *sqlike.Table
    22  	filtered bool
    23  }
    24  
    25  var _ persist.FilteredAdapter = new(Adapter)
    26  
    27  // MustNew :
    28  func MustNew(ctx context.Context, table *sqlike.Table) persist.FilteredAdapter {
    29  	a, err := New(ctx, table)
    30  	if err != nil {
    31  		panic(err)
    32  	}
    33  	return a
    34  }
    35  
    36  // New :
    37  func New(ctx context.Context, table *sqlike.Table) (persist.FilteredAdapter, error) {
    38  	if table == nil {
    39  		return nil, errors.New("invalid <nil> table")
    40  	}
    41  	a := &Adapter{
    42  		ctx:   ctx,
    43  		table: table,
    44  	}
    45  	if err := a.createTable(); err != nil {
    46  		return nil, err
    47  	}
    48  	if err := a.table.Indexes().
    49  		CreateOneIfNotExists(
    50  			a.ctx,
    51  			indexes.Index{
    52  				Type: indexes.Primary,
    53  				Columns: indexes.Columns(
    54  					"PType",
    55  					"V0", "V1", "V2",
    56  					"V3", "V4", "V5",
    57  				),
    58  			}); err != nil {
    59  		return nil, err
    60  	}
    61  	return a, nil
    62  }
    63  
    64  // LoadPolicy :
    65  func (a *Adapter) LoadPolicy(model model.Model) error {
    66  	result, err := a.table.Find(a.ctx, nil)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	policies := []*Policy{}
    72  	if err := result.All(&policies); err != nil {
    73  		return err
    74  	}
    75  
    76  	for _, r := range policies {
    77  		loadPolicy(r, model)
    78  	}
    79  	return nil
    80  }
    81  
    82  // LoadFilteredPolicy :
    83  func (a *Adapter) LoadFilteredPolicy(model model.Model, filter interface{}) error {
    84  	var policies []*Policy
    85  	x, ok := filter.(primitive.Group)
    86  	if !ok {
    87  		return errors.New("invalid filter data type, expected []interface{}")
    88  	}
    89  
    90  	act := new(actions.FindActions)
    91  	act.Conditions = x
    92  	result, err := a.table.Find(
    93  		a.ctx,
    94  		act,
    95  		options.Find().
    96  			SetNoLimit(true).
    97  			SetDebug(true),
    98  	)
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	if err := result.All(&policies); err != nil {
   104  		return err
   105  	}
   106  
   107  	for _, policy := range policies {
   108  		loadPolicy(policy, model)
   109  	}
   110  	a.filtered = true
   111  	return nil
   112  }
   113  
   114  // SavePolicy : saves all policy rules to the storage.
   115  func (a *Adapter) SavePolicy(model model.Model) error {
   116  	var policies []*Policy
   117  	for ptype, ast := range model["p"] {
   118  		for _, r := range ast.Policy {
   119  			policies = append(policies, toPolicy(ptype, r))
   120  		}
   121  	}
   122  
   123  	for ptype, ast := range model["g"] {
   124  		for _, r := range ast.Policy {
   125  			policies = append(policies, toPolicy(ptype, r))
   126  		}
   127  	}
   128  
   129  	if len(policies) > 0 {
   130  		if _, err := a.table.Insert(
   131  			a.ctx,
   132  			&policies,
   133  			options.Insert().
   134  				SetMode(options.InsertOnDuplicate),
   135  		); err != nil {
   136  			return err
   137  		}
   138  	}
   139  	return nil
   140  }
   141  
   142  // AddPolicy : adds a policy policy to the storage. This is part of the Auto-Save feature.
   143  func (a *Adapter) AddPolicy(sec string, ptype string, rules []string) error {
   144  	if _, err := a.table.InsertOne(
   145  		a.ctx,
   146  		toPolicy(ptype, rules),
   147  		options.InsertOne().
   148  			SetMode(options.InsertIgnore),
   149  	); err != nil {
   150  		return err
   151  	}
   152  	return nil
   153  }
   154  
   155  // RemovePolicy : removes a policy policy from the storage. This is part of the Auto-Save feature.
   156  func (a *Adapter) RemovePolicy(sec string, ptype string, rules []string) error {
   157  	policy := toPolicy(ptype, rules)
   158  	if _, err := a.table.DeleteOne(
   159  		a.ctx,
   160  		actions.DeleteOne().
   161  			Where(
   162  				expr.Equal("PType", policy.PType),
   163  				expr.Equal("V0", policy.V0),
   164  				expr.Equal("V1", policy.V1),
   165  				expr.Equal("V2", policy.V2),
   166  				expr.Equal("V3", policy.V3),
   167  				expr.Equal("V4", policy.V4),
   168  				expr.Equal("V5", policy.V5),
   169  			),
   170  	); err != nil {
   171  		return err
   172  	}
   173  	return nil
   174  }
   175  
   176  // RemoveFilteredPolicy : removes policy rules that match the filter from the storage. This is part of the Auto-Save feature.
   177  func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, idx int, values ...string) error {
   178  	policy := new(Policy)
   179  	policy.PType = ptype
   180  	length := len(values)
   181  	if idx <= 0 && 0 < idx+length {
   182  		policy.V0 = values[0-idx]
   183  	}
   184  	if idx <= 1 && 1 < idx+length {
   185  		policy.V1 = values[1-idx]
   186  	}
   187  	if idx <= 2 && 2 < idx+length {
   188  		policy.V2 = values[2-idx]
   189  	}
   190  	if idx <= 3 && 3 < idx+length {
   191  		policy.V3 = values[3-idx]
   192  	}
   193  	if idx <= 4 && 4 < idx+length {
   194  		policy.V4 = values[4-idx]
   195  	}
   196  	if idx <= 5 && 5 < idx+length {
   197  		policy.V5 = values[5-idx]
   198  	}
   199  	return nil
   200  }
   201  
   202  // IsFiltered :
   203  func (a *Adapter) IsFiltered() bool {
   204  	return a.filtered
   205  }
   206  
   207  func loadPolicy(policy *Policy, m model.Model) {
   208  	tokens := append([]string{}, policy.PType)
   209  
   210  	if len(policy.V0) > 0 {
   211  		tokens = append(tokens, policy.V0)
   212  	}
   213  	if len(policy.V1) > 0 {
   214  		tokens = append(tokens, policy.V1)
   215  	}
   216  	if len(policy.V2) > 0 {
   217  		tokens = append(tokens, policy.V2)
   218  	}
   219  	if len(policy.V3) > 0 {
   220  		tokens = append(tokens, policy.V3)
   221  	}
   222  	if len(policy.V4) > 0 {
   223  		tokens = append(tokens, policy.V4)
   224  	}
   225  	if len(policy.V5) > 0 {
   226  		tokens = append(tokens, policy.V5)
   227  	}
   228  
   229  	key := tokens[0]
   230  	sec := key[:1]
   231  	m[sec][key].Policy = append(m[sec][key].Policy, tokens[1:])
   232  	m[sec][key].PolicyMap[strings.Join(tokens[1:], model.DefaultSep)] = len(m[sec][key].Policy) - 1
   233  }
   234  
   235  func toPolicy(ptype string, rules []string) *Policy {
   236  	policy := new(Policy)
   237  	policy.PType = ptype
   238  	length := len(rules)
   239  	if length > 0 {
   240  		policy.V0 = rules[0]
   241  	}
   242  	if length > 1 {
   243  		policy.V1 = rules[1]
   244  	}
   245  	if length > 2 {
   246  		policy.V2 = rules[2]
   247  	}
   248  	if length > 3 {
   249  		policy.V3 = rules[3]
   250  	}
   251  	if length > 4 {
   252  		policy.V4 = rules[4]
   253  	}
   254  	if length > 5 {
   255  		policy.V5 = rules[5]
   256  	}
   257  	return policy
   258  }
   259  
   260  func (a *Adapter) createTable() error {
   261  	return a.table.UnsafeMigrate(a.ctx, Policy{})
   262  }