Grab all Users with Permission to Publish Content

Topics: Administration, Customizing Orchard
Sep 27, 2014 at 10:55 PM
Is it possible to somehow create an array or list of users with the permission to publish content. So far I have only been able to find a way to grab a user by their username or by the currently logged in user. I need to create a list of users with the ability to publish that I can stick into a token. I also need to create a list of their emails, this is actually more important than just a list of their usernames, but from my understanding you could grab the emails based off of the username.
Sep 27, 2014 at 11:41 PM
Hi!

I think
var users = _contentManager.Query<UserPart, UserPartRecord>().List();
should do the trick.
Sep 28, 2014 at 12:01 AM
Edited Sep 28, 2014 at 12:38 AM
Awesome thank you I was having a problem putting the query into a list. My next problem is trying to determine if the user has the permission to publish so I can add them to a list of users that can publish content. I don't see a member function for the var users that looks like it will do this. Can I use the .has function?

Edit: I've been looking into this further and have found a class that has a member function you can use to test if a user is in a certain role. This could work but a better solution would be if the same thing existed but to check if a user has a certain permission. Is this already built into orchard?
Sep 28, 2014 at 2:52 AM
Hi!

As far as I know Orchard has a RoleBased permission system and maybe you should rethink your solution and create a role and list all users who have this role.

You can get the role of the user like this:
 var users = _contentManager.Query<UserPart, UserPartRecord>().List();

 var user = users.FirstOrDefault();

 var roles = user.As<UserRolesPart>().Roles;
If you really like to check on a permission you can do that with the IAuthorizationService. Get this service from the IoC and use it like this:
var result = _authService.TryCheckAccess(Permission.Named("PublishContent"), user, null);
I am not sure if its the most elegent way but it should work.
Sep 30, 2014 at 4:37 PM
So this is what I am doing to set my tokens but they are coming up as blank or empty when I try to use them within Orchard.

public void Evaluate(dynamic context) {
        var forContent = context.For<ISite>("Site", (Func<ISite>)(() => _orchardServices.WorkContext.CurrentSite));

        //Grab a list of all the users
        var users = _orchardServices.ContentManager.Query<UserPart, UserPartRecord>().List();

        //Implement the OrchardRoleProvider class to determine if a user is in a role that can publish content
        OrchardRoleProvider roleProvider = new OrchardRoleProvider(); 

        //Create two lists to contain the usernames and emails of users who can publish content
        List<string> publisherUserNames = new List<string>();
        List<string> publisherUserEmails = new List<string>();

        //Determine if users are in a role that can publish content and if they are add their username and email to separate lists
        foreach (var user in users)
        {

            if (roleProvider.IsUserInRole(user.UserName, "Publisher") || 
                roleProvider.IsUserInRole(user.UserName, "Administrator") ||
                roleProvider.IsUserInRole(user.UserName, "Institution Admin")) 
            {
                publisherUserNames.Add(user.UserName);
                publisherUserEmails.Add(user.Email);
            }

        }

        //Convert lists to comma separated strings
        string publisherUserEmailsString = String.Join(",", publisherUserEmails);
        string publisherUserNamesString = String.Join(",", publisherUserNames);

        //Prevent string from being empty
        if (string.IsNullOrEmpty(publisherUserEmailsString))
        {
            publisherUserEmailsString = "Email was empty";
        }

        if (string.IsNullOrEmpty(publisherUserNamesString))
        {
            publisherUserNamesString = "Names were empty";
        }

        forContent
            .Token("Publishers", (Func<ISite, object>)(content => publisherUserNamesString))
            .Chain("Publishers", "Text", (Func<ISite, object>)(content => publisherUserNamesString))
            .Token("PublishersEmail", (Func<ISite, object>)(content => publisherUserEmailsString))
            .Chain("PublishersEmail", "Text", (Func<ISite, object>)(content => publisherUserEmailsString))
            .Token("SuperUserEmail", (Func<ISite, object>)(content => _membershipService.GetUser(content.SuperUser).Email))
            .Chain("SuperUserEmail", "User", (Func<ISite, object>)(content => _membershipService.GetUser(content.SuperUser).Email))
            ;

        if (context.Target == "Site") {
            // is there a content available in the context ?
            if (forContent.Data != null && forContent.Data.ContentItem != null) {
                var customSettingsPart = _contentDefinitionManager.GetTypeDefinition("Site");
                foreach (var partField in customSettingsPart.Parts.SelectMany(x => x.PartDefinition.Fields)) {
                    var field = partField;
                    var tokenName = partField.Name;
                    forContent.Token(
                        tokenName,
                        (Func<IContent, object>)(content => LookupField(content, field.Name).Storage.Get<string>()));
                    forContent.Chain(
                        tokenName,
                        partField.FieldDefinition.Name,
                        (Func<IContent, object>)(content => LookupField(content, field.Name)));
                }
            }
        }
    }
Any ideas why this isn't working? Thank you.
Developer
Oct 1, 2014 at 12:06 AM
Did you try setting a breakpoint and follow the execution?
Oct 1, 2014 at 5:20 PM
I think part of my problem is in using the IsUserInRole method of the class OrchardRoleProvider. The class doesn't actually seem to do anything other than throw a new exception:

public override bool IsUserInRole(string username, string roleName) {
        throw new NotImplementedException();
    }
Does this mean the method hasn't actually been implemented yet?

Thank you.
Oct 1, 2014 at 5:27 PM
Edited Oct 1, 2014 at 5:27 PM
Can you try something like this:
foreach (var user in users)
{
 var roles = user.As<UserRolesPart>().Roles;
 if (roles.Contains("Publisher") || 
  roles.Contains("Administrator") ||
  roles.Contains("Institution Admin")) 
  {
   publisherUserNames.Add(user.UserName);
   publisherUserEmails.Add(user.Email);
  }
}
Code not tested but hopefully should work :)
Marked as answer by emeraldarcher on 10/1/2014 at 9:47 AM