Steve Coleman
Steve Coleman

Reputation: 2027

Servicestack Roles Users and Groups

Since roles don't contain permissions. I am a bit confused by the Roles and Permission in ServiceStack. It appears they are really the same thing? I want to implement a Group, that has roles, that has permissions. Based on the servicestack default implementation I don't think I can extend the provider and get the nested information.

How would i achieve this and still use the authentication attributes. If i had an attribute

[RequiredPermission("CanAccessPerm")] 
That is in Role:HasAccessRole That is in Group:HasAccessGroup

I would want to only use perms to determine access at the API level. Then Roles and Groups to determine who has perms. If Roles contained permissions then I could just extend the CredentialsAuthProvider TryAuthenticate and additionally look at a group table. Is there a way to do this and not rewrite the whole authentication?

Edit 12/12 I am using container.Register(c => new OrmLiteAuthRepository(c.Resolve()) { UseDistinctRoleTables = AppSettings.Get("UseDistinctRoleTables", true), }); How do I get to the IManage roles? I see i can override the IAuthRepository.

I found this link. But its not a replacement for Auth ServiceStack - roles and permissions

-_Edit 12/29 -- It is not calling the methods in MyOrmLiteAuthRepository. Do you know why?

AppHost.cs

            container.Register<IAuthRepository>(c =>
                new MyOrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>())
                {
                    UseDistinctRoleTables = AppSettings.Get("UseDistinctRoleTables", true),
                });


CustomAuthRepo
    public class MyOrmLiteAuthRepository : OrmLiteAuthRepository
    {
        public MyOrmLiteAuthRepository(IDbConnectionFactory dbFactory) : base(dbFactory) { }

        public MyOrmLiteAuthRepository(IDbConnectionFactory dbFactory, string namedConnnection = null)
            : base(dbFactory, namedConnnection)
        {
            DbFactory = dbFactory;
            NamedConnnection = namedConnnection;
        }

        public IDbConnectionFactory DbFactory { get; set; }
        public string NamedConnnection { get; set; }

        public override ICollection<string> GetPermissions(string userAuthId)
        {
            var permissions = base.GetPermissions(userAuthId);

            using (var ss = HostContext.ResolveService<SecurityService>(new BasicRequest()))
            {
                permissions = ss.UserPermissions(Convert.ToInt32(userAuthId));
            }

            return permissions;
        }


        public override bool HasPermission(string userAuthId, string permission)
        {
            var hasPermission = base.HasPermission(userAuthId, permission);

            using (var ss = HostContext.ResolveService<SecurityService>(new BasicRequest()))
            {
                hasPermission = ss.UserHasPermInRoleOrGroup(permission, Convert.ToInt32(userAuthId));
            }

            return hasPermission;
        }
    }

Upvotes: 4

Views: 395

Answers (1)

mythz
mythz

Reputation: 143284

Roles/Permissions work similar in that a User can have multiple Roles and Permissions but they're logically different in that a Role defines the Role a person has like "Employee", "Manager", etc and Permission defines functionality they have access to like "CanSubmitPurchaseOrders", "CanRefundCustomers", etc.

ServiceStack doesn't support Roles having permissions themselves but you can implement this functionality yourself in your own Custom AuthProvider by overriding OnAuthenticated() and populating the Permissions collections of AuthUserSession with a combination of all the permissions in all the Roles a User is in. If you're not using a custom AuthProvider you can modify the Users Session by implementing the OnAuthenticated() Session of Auth Event Hooks.

Alternatively if you're using an AuthRepository like OrmLiteAuthRepository you can change how permissions are managed by overriding its IManageRoles GetPermissions() and HasPermission() APIs to also inspect the Permissions that the Users Roles have assigned to them which you would need to maintain in an out-of-band table.

Overriding OrmLiteAuthRepository

OrmLiteAuthRepository implements IManageRoles so when needed you can cast IAuthRepository to IManageRoles, e.g:

var manageRoles = (IManageRoles)container.Resolve<IAuthRepository>();

You can override OrmLiteAuthRepository and implement your own GetPermissions() and HasPermission() with normal inheritance, e.g:

public class MyOrmLiteAuthRepository : OrmLiteAuthRepository
{
    public MyOrmLiteAuthRepository(IDbConnectionFactory dbFactory) : base(dbFactory) { }

    public MyOrmLiteAuthRepository(IDbConnectionFactory dbFactory, string namedConnnection = null) 
        : base(dbFactory, namedConnnection) {}

    public override ICollection<string> GetPermissions(string userAuthId)
    {
        return base.GetPermissions(userAuthId);
    }

    public override bool HasPermission(string userAuthId, string permission)
    {
        return base.HasPermission(userAuthId, permission);
    }
}

Upvotes: 4

Related Questions