Access Groups Associated with Project Role Using Atlassian API - jira

I am currently developing a plugin that allows project administrators to manage users in groups. I have been combing through the api reference documentation and I cannot seem to find any calls that I can make that will allow me to see the groups associated with a particular project.
I have looked through the API's at every location that is relevant to what I am searching for to no avail.
I currently have a database query that provides me what I am looking for.
SELECT ROLETYPEPARAMETER AS "Groups"
FROM projectrole PROJECT_ROLE,
projectroleactor PROJECT_ROLE_ACTOR
JOIN project PROJECT
ON PROJECT.id = PROJECT_ROLE_ACTOR.PID
JOIN cwd_group
ON group_name = roletypeparameter
WHERE PROJECT_ROLE_ACTOR.projectroleid = PROJECT_ROLE.id
AND PKEY = <projectkey>;
I would prefer to manipulate this data through the API if at all possible.
All the other pieces are available for me to complete the plugin to add, remove users from groups.
I know the information that I am looking for is available. If you navigate to the roles page you have both the users in roles, and also the groups in roles. I'm sure i'm overlooking something minor with the API to give me the groups associated with the project.

After implementing my database route, I came back to a non-database approach. This is the implementation that solves the problem.
The way the groups are implemented is as a role actor as a set underneath the project roles. One more level down you have your group names as a descriptor to the role actor.
//Create TreeMap to Store the Role-Group association. Note a role can have more than one group
TreeMap<String,Collection<String>> projectGroups = new TreeMap<String,Collection<String>>();
//Get all the project roles
Collection<ProjectRole> projectRoles = projectRoleManager.getProjectRoles();
//Iterate through each role and get the groups associated with the role
for (ProjectRole projectRole : projectRoles)
{
//Get the role actors for the project role
ProjectRoleActors roleActors = projectRoleManager.getProjectRoleActors(projectRole, project);
//Create an iterator to grab all of the groups for this project role
Iterator <RoleActor> roleActorIterator = roleActors.getRoleActors().iterator();
//Create a collection of strings to store all of the group's roles to put in the map
Collection <String> groupRoles = new ArrayList<String>();
//Iterate the role actors to get the groups
while (roleActorIterator.hasNext())
{
//Add the group by string name into collection
groupRoles.add(roleActorIterator.next().getDescriptor());
}//END While
//Add that role, and the associated groups to that role into our map.
projectGroups.put(projectRole.getName(), groupRoles);
}//END For
The output of this will look similarly to this
{Administrators=[jira-administrators], Developers=[jira-developers, jira-users], Users=[jira-users]}

Related

Providing access to User Groups using Identity Server 3

The application I'm currently working on is a huge ASP.NET MVC web application which uses traditional Windows Authentication model. We are trying to migrate to Single Sign On model using Identity Server 3 and Open ID Connect.
Coming to my question, is there any way/work around to provide access on a user group basis when using Identity Server? The problem here is that the my user groups could either be role based or Active directory groups. I'm looking for something like InMemoryGroup (similar to InMemoryUser).
Something that mimicks the following for a Group of users that can be role based or not:
new InMemoryUser
{
Username = "harry",
Password = "thisispassword#123",
Subject = "1",
Claims = new Claim[]
{
new Claim(Constants.ClaimTypes.Name, "Harry Potter"),
new Claim(Constants.ClaimTypes.GivenName, "Harry"),
new Claim(Constants.ClaimTypes.FamilyName, "Potter"),
new Claim(Constants.ClaimTypes.Email, "harry.potter#hogwarts.com"),
new Claim(Constants.ClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(Constants.ClaimTypes.Role, "Administrator"),
}
}
I'm relatively new to Identity Server and Open ID Connect and not able to find anything online and would really appreciate any leads.
To represent the fact that a user is a member of a group you just add a claim. You could add:
new Claim("Group", "Hogwarts Student")
to your in memory user. The claim indicates that Harry is a member of the "Hogwarts Student" group. There is a couple of things going on here you want to be aware of. The constructor being called is:
new Claim(string claimType, string claimValue)
There Identity Server provides some standard ones in the Constants class but you can make up your own. Also, you can have multiple group claims, so you could have
new Claim("Group", "Hogwarts Student"),
new Claim("Group", "Gryffindor House)
If you wanted to see if Harry was in the "Gryffindor House" group, you'd just search through is list of claims where the claim type is equal to "Group" and the claim value is equal to "Gryffindor House".
Finally, the difference between groups and roles is generally more a matter of application semantics that a physical difference in how they are stored. In general, the set of users that can perform the "Administrator" role for an application is just a group of users. It is the way that an application treats users of a group that makes the group a role.

MVC EF get many-to-many relationship table

I set up my many-to-many relationship in EF. But I can only refer to the main tables, not the bridge table. How can I refer to the bridge table?
for example:
User: UserID, name
Group: GroupID, group
UserGroup: UserID, GroupID
I can refer to the User table and Group table by typing
context.User.(some linq expression)
context.Group.(some lin1 expression)
But I cannot refer to the bridge table by typing
context.UserGroup
It would be great to know which versions of MVC and EF you are working with. Based on the assumption that its MVC 4 and EF5...
The point of a Join table is to keep referential integrity going. As #timothy says, there is no reason to refer to the (UserGroup) Join table unless there is actual additional data in it i.e. payload. If you're putting other data in the UserGroup table then its not a Join table anyway.
Rather use some Lazy or Eager loading to get the Group data you need:
Lazy Loading
var users = context.Users
foreach (User x in users)
{
foreach (Group f in x.Groups)
//notice the x user being referred to here for Groups
{
// Whatever you want to do with the objects
}
}
Eager Loading
var users = context.Users.Include(g => g.Groups)
foreach (User x in users)
{
foreach (Group f in x.Groups)
//notice the x user being referred to here for Groups
{
// Whatever you want to do with the objects
}
}
The 'foreach' code above is just added to show how to include it in a loop example. Its the first line of these Loading examples that are important.
Once you have defined 'var users' the rest is "easy".
Good Luck!
When defining a many-to-many relationship you have two options.
Link User to Group, and let it know that UserGroup is your join table
Link User to UserGroup as many-to-one, also link Group to UserGroup using many-to-one.
The reason to use option 2 is when you have something other than just the two IDs in the join table. An example I had recently was a SortOrder field.
When querying with a materialized join table, it feels a little clumsy:
context.User.Select(user => new {
Name = user.Name,
Groups = user.GroupJoins
.OrderBy(groupJoin => groupJoin.SortOrder)
.Select(groupJoin => groupJoin.Group.Name)
});
Why you want refer to that junction table...?!
If you want to get Users of a group:
var users = from u in db.UserGroups.Include("User").Include("Group")
Where u.GroupID == gid
select u;
And simply vice versa if you need Groups of a User:
var groups = from g in db.UserGroups.Include("User").Include("Group")
Where g.UserID == uid
select g;

Insert new object by attaching existing entity properties in Nhibernate

We have create screens with duplicate option for each object. For ex: While creating new Customer along with details, user can chose existing customer to copy groups associated from existing to new user. So I would like to know how to assign properties of new customer for 1:n and m:n scenario.
For "Customer" and "CustomerGroups". Will the below approach work fine?
Customer existing = repo<Customer>(id);
Customer newCust = new Customer();
for(var group in existing.Groups)
newCust.CustomerGroups.Add(new CustomerGroup(){ **AllpropertiesexceptID**, **Customer=newCust** } );
For Order and OrderItems, since its m:n relationship, just attaching existing items with new order.
Orders existing = repo(id);
Order newOrder = new Order();
for(var item in existing.Items)
newOrder.Items.Add(item);
Is it required to do Session.Evict for the existing Order or Customer for performing these operations.
You might be thinking too much. :) Just go ahead and create separate lookalike objects, pretending NHibernate isn't even there. As long as the new instances have different (unset) identity properties, NHibernate won't even realize they are "copies".

finding user group name while logging with glassfish jdbcRealm

I know that while user logs in we can find the user name by
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
request.login(username, password);
Principal principal = request.getUserPrincipal();
principal.getName();
but how do i get the user Group (without doing any db query).
I tried the below but it doesn't work, it always returns false for all group.
context.getExternalContext().isUserInRole("USER")
request.isUserInRole("USER")
I want to point out that groups and roles are different concepts.
Suppose you have a web app where someone can write articles, someone can only comment and others can only read. So you have three roles: WRITER, COMMENTER and READER.
Now this web app is used internally to your organization. The organigram provides these groups: PROJECTMANAGER, ARCHITECT, SYSADMIN and DEVELOPER.
In few words roles are related to webapp, groups are related to your organigram.
In glassfish-web.xml you can bind groups and/or users to roles. For example PROJECTMANAGERs and ARCHITECTs are WRITERs, SYSADMINs are COMMENTERs and DEVELOPERs are READERs.
Thus in general there is no way to retrieve users's groups without a db query. Anyway a ploy is to create roles with the same name as groups (in glassfish-web.xml). Besides in the admin console there is a flag to automatically maps roles to groups.
A few thoughts to augment Alf's informative response:
A user may belong to multiple groups.
Each group may be have associated with it multiple roles. For GlassFish 3.1.2 the mapping between roles and groups is made in glassfish-web.xml, i.e:
<security-role-mapping>
<role-name>USER</role-name>
<group-name>USER</group-name>
</security-role-mapping>
Roles must be defined to your web-app, in web.xml:
<security-role>
<role-name>USER</role-name>
</security-role>
The above maps a group USER into a role USER in the web-app. Certainly you can choose names that differ - just keep the same value in the role-name elements for both.

Spring Security (Acegi) and user Groups (vs. Roles)

We're developing an app (using Grails Spring Security (formerly Acegi)) in which we'll have thousands of users that span 10-15 discreet user types. In the current system, each user type equates to a "group", and the specific roles and permissions are tied to the group. The user gets all their "roles" from the group.
For example, we might have two user groups:
CLOWN: roles = ride_clown_car, toot_horn, receive_applause
ACROBAT: roles = do_flip, walk_tightrope, receive_applause
We have three users, one assigned to the CLOWN group, one assigned to the ACROBAT group, and one assigned to both (has union of CLOWN and ACROBAT roles).
If we change permissions, we do so at the group level. For example, if we add a swing_on_trapeze permission to the ACROBAT group, all acrobats will automatically inherit it.
In Grails terms, the permissions on the controllers would still be at the role level. So an action with #Secured (['toot_horn']) would allow users in the CLOWN group but not in the ACROBAT group. #Secured (['receive_applause']) would allow both CLOWNS and ACROBATS.
How would I do this in Spring Security given the two-tiered nature of the model (user, role)? Do I need to implement my own custom authentication to collect roles based via groups?
Thanks!
You should be using the new Spring Security Core plugin since the Acegi plugin isn't being developed and is basically deprecated.
But either way, both plugins just expect that there's something like a getAuthorities() method in your user class that returns role instances. In a scenario like this where the user has many groups, just collect all of the groups' roles:
class User {
...
def getAllRoles() {
Set allRoles = []
groups.each { allRoles.addAll it.roles }
allRoles
}
}
This assumes that you have a many-to-many between User and Group:
static hasMany = [groups: Group]
and Group has a many-to-many with Role:
static hasMany = [roles: Role]
To use this set the 'relationalAuthorities' property to 'allRoles' in SecurityConfig.groovy so it uses that instead of the many-to-many between user and role:
relationalAuthorities='allRoles'
There's no configuration required for the Spring Security core plugin since it depends on an application-defined getAuthorities method already, so just use something like this in your User class:
Set<Role> getAuthorities() {
Set allRoles = []
groups.each { allRoles.addAll it.roles }
allRoles
}

Resources