Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help Wanted: EF Core Adapter #4

Closed
VictorioBerra opened this issue Jun 11, 2019 · 8 comments
Closed

Help Wanted: EF Core Adapter #4

VictorioBerra opened this issue Jun 11, 2019 · 8 comments
Assignees
Labels
help wanted Extra attention is needed

Comments

@VictorioBerra
Copy link

No description provided.

@huazhikui
Copy link
Member

huazhikui commented Jun 12, 2019

@VictorioBerra
Entity Class:

   [Table("casbin_policy")]
    public class PermissionPolicy : IEntity
    {
        /// <summary>
        /// 
        /// </summary>
        [Key]
        [Column("id")]
        public string Id { set; get; }

        /// <summary>
        /// policy type
        /// </summary>
        [Column("ptype")]
        public string Ptype { set; get; }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetPolicyCotent()
        {
            StringBuilder sb = new StringBuilder(Ptype);
            void Append(string v)
            {
                if (string.IsNullOrEmpty(v))
                {
                    return;
                }
                sb.Append($", {v}");
            }
            Append(V0);
            Append(V1);
            Append(V2);
            Append(V3);
            Append(V4);
            Append(V5);
            return sb.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        [Column("v0")]
        public string V0 { set; get; }

        /// <summary>
        /// 
        /// </summary>
        [Column("v1")]
        public string V1 { set; get; }

        /// <summary>
        /// 
        /// </summary>
        [Column("v2")]
        public string V2 { set; get; }

        /// <summary>
        /// 
        /// </summary>
        [Column("v3")]
        public string V3 { set; get; }

        /// <summary>
        /// 
        /// </summary>
        [Column("v4")]
        public string V4 { set; get; }

        /// <summary>
        /// 
        /// </summary>
        [Column("v5")]
        public string V5 { set; get; } 
    }

Adapter class:

  /// <summary>
    /// 
    /// </summary>
    public class PermDbAdapter : NetCasbin.Persist.IAdapter
    {
        private readonly IPermPolicyRepository _permissionRepository;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="permissionRepository"></param>
        public PermDbAdapter(IPermPolicyRepository permissionRepository)
        {
            _permissionRepository = permissionRepository;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IAdapter NewAdapter()
        {
            var repos = ServiceLocator.CurrentScopedServices.GetService<IPermPolicyRepository>();
            return new PermDbAdapter(repos);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="model"></param>
        public void LoadPolicy(Model model)
        {
            var rules = _permissionRepository.FindAll();
            LoadPolicyData(model, NetCasbin.Persist.Helper.LoadPolicyLine, rules);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="model"></param>
        public void SavePolicy(Model model)
        {
            _permissionRepository.Clear();
            var rules = model.Model["p"]["p"].Policy.Select(p => CreateRule("p", p.ToArray()));
            rules = rules.Concat(model.Model["g"]["g"].Policy.Select(p => CreateRule("g", p.ToArray())));
            if (rules.Any())
            {
                _permissionRepository.Insert(rules);
            }
        }

        #region NotImplemented
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sec"></param>
        /// <param name="ptype"></param>
        /// <param name="fieldIndex"></param>
        /// <param name="fieldValues"></param>
        public void RemoveFilteredPolicy(string sec, string ptype, int fieldIndex, params string[] fieldValues)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sec"></param>
        /// <param name="ptype"></param>
        /// <param name="rule"></param>
        public void AddPolicy(string sec, string ptype, IList<string> rule)
        {
            //var policy = CreateRule("p", rule.ToArray());
            //policy.Id = ObjectId.GenerateNewStringId();
            //_casbinRuleRepository.Insert(policy);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sec"></param>
        /// <param name="ptype"></param>
        /// <param name="rule"></param>
        public void RemovePolicy(string sec, string ptype, IList<string> rule)
        {
            throw new Exception();
        }

        #endregion

        private void LoadPolicyData(Model model, Helper.LoadPolicyLineHandler<String, Model> handler, IEnumerable<PermissionPolicy> rules)
        {

            foreach (var rule in rules)
            {
                //model.HasPolicy(rule.Ptype,rule.Ptype, rule.)
                handler(rule.GetPolicyCotent(), model);
            }
        }

        private PermissionPolicy CreateRule(string ptype, string[] policyData)
        {
            var count = policyData.Count();
            var rule = new PermissionPolicy
            {
                Id = ObjectId.GenerateNewStringId(),
                Ptype = ptype,
                V0 = count > 0 ? policyData[0] : null,
                V1 = count > 1 ? policyData[1] : null,
                V2 = count > 2 ? policyData[2] : null,
                V3 = count > 3 ? policyData[3] : null,
                V4 = count > 4 ? policyData[4] : null,
                V5 = count > 5 ? policyData[5] : null,
            };
            return rule;
        }
    }

@VictorioBerra
Copy link
Author

This looks nice. Also I was hoping for maybe a single call in my Core Startup.cs like .AddDatabaseAdapter(). See how IdentityServer does it here http://docs.identityserver.io/en/latest/reference/ef.html

Code snippet:

    services.AddIdentityServer()
        // this adds the config data from DB (clients, resources, CORS)
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));
        });

This reduces the necessary work to almost nothing.

@xcaptain
Copy link

Nice discuss, I wrote a simple example using DI and file adapter policy see https://gist.github.com/xcaptain/920115af7bfe81a57fa58f62ea9e4887
I'm Also looking for a EF Core based adapter, but I don't know how to inject a Ef Core entity into this adapter

@xcaptain
Copy link

Updated my gist to use custom PermDbAdapter, CasbinRule.cs is auto generated from dotnet ef dbcontext scafold command, the middleware works but still looking for a better way to inject PermDbAdapter

@hsluoyz
Copy link
Member

hsluoyz commented Jun 15, 2019

Hi @huazhikui , there's no adapters for Casbin.NET yet. I think we need to develop one, for example for EF. It can also be an example for others to implement a Casbin adapter in C#.

@xcaptain
Copy link

I implemented a CasbinService for my asp dotnet core project, it works well. EFcore interact with the database through a DbContext, this DbContext is injected into service container as a scoped service, to create an EFcore adapter I think we should consider injecting the whole DbContext directly or create a repository class to interact with casbin_rule table.

@huazhikui
Copy link
Member

@xcaptain good idea. i implemented the repository class and inject adapter in my other project.
Because, I think that is the repository should not be included in this project. of course,
we can provide an extension package to implement your ideas.

@hsluoyz
Copy link
Member

hsluoyz commented Oct 2, 2019

We have it now: https://github.com/casbin-net/EFCore-Adapter

@hsluoyz hsluoyz closed this as completed Oct 2, 2019
@hsluoyz hsluoyz added the help wanted Extra attention is needed label Oct 2, 2019
@hsluoyz hsluoyz self-assigned this Oct 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants