-
Notifications
You must be signed in to change notification settings - Fork 681
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
GUACAMOLE-220: Add base extension API support for user groups. #274
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took a first pass at it. Looks really good to me - just minor questions/comments.
* @throws GuacamoleException | ||
* If an error occurs while retrieving the user groups. | ||
*/ | ||
RelatedObjectSet getMemberUserGroups() throws GuacamoleException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason that getUserGroups()
and getMemberUserGroups()
are both necessary? Based on the stubs and descriptions, here, they look identical? I see that they're both implemented in DelegatingUserGroup
, but they have identical implementations, there, and getMemberUserGroups()
does not appear to be used anywhere outside of there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getUserGroups()
returns the user groups of which the current group is a member, while getMemberUserGroups()
returns the user groups which are members of the current group.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, in that case, the comments above the code need to be updated. The comment above getUserGroups()
says:
Returns a set of all readable user groups that are members of this user group.
and the comment above getMemberUserGroups()
starts with:
Returns a set of all readable user groups that are members of this user group.
Also, the @return
comment seems to be identical for both of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK - this should now be corrected.
* A read-only implementation of RelatedObjectSet which uses a backing Set | ||
* of identifiers to determine which objects are present. | ||
*/ | ||
public class SimpleRelatedObjectSet implements RelatedObjectSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think there's any value to implementing a AbstractRelatedObjectSet
class like you've done for several of the other Simple
classes, that implements a bunch of these default behaviors? Perhaps not initially useful for the JDBC extension, but is it something that would be helpful as other extensions implement the RelatedObjectSet
class without having to rely on the behavior of SimpleRelatedObjectSet
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In principle, yes, but I'm not sure what that would be. There are only two functions that are effectively unimplemented by SimpleRelatedObjectSet
:
addObjects()
removeObjects()
both of which make changes to the RelatedObjectSet
in a way that would be implementation dependent. It does make sense to provide default behaviors, but I don't think there are any sensible default behaviors we can provide here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sense.
User self = userContext.self(); | ||
Permissions effective = self.getEffectivePermissions(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the ConnectionGroupTree
class you did:
Permissions effective = userContext.self().getEffectivePermissions();
eliminating the need for the existence of the self
object. Any reason not to do the same, here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. Sounds fine to me. I'll make the change.
@@ -143,13 +144,14 @@ public DirectoryResource(UserContext userContext, Directory<InternalType> direct | |||
|
|||
// An admin user has access to all objects | |||
User self = userContext.self(); | |||
SystemPermissionSet systemPermissions = self.getSystemPermissions(); | |||
Permissions effective = self.getEffectivePermissions(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same note as above - any reason not to do
Permissions effective = userContext.self().getEffectivePermissions()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. No reason. Will do.
User self = userContext.self(); | ||
Permissions effective = self.getEffectivePermissions(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As with previous places, guessing these two lines could be collapsed...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more style/grammar nitpicks.
@@ -19,6 +19,9 @@ | |||
|
|||
package org.apache.guacamole.net.auth; | |||
|
|||
import java.util.Collections; | |||
import java.util.Set; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra line added, here - seems like most files have a single space between import
and class documentation.
* Note that, as with user identifiers, user group identifiers form the | ||
* basis of identity which applies across authentication providers. It is | ||
* expected that any two user groups having the same identifier represent | ||
* the same group, even if defined by different authentication providers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing period at the end of this sentence.
* Returns all user permissions given to this user. | ||
* Returns a read-only view of all permissions granted to this user. The | ||
* exact semantics of what permissions are granted are up to the | ||
* implementation, and the permissions within this view may implied, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"may be implied"
…BE implied, not "may implied".
OK, I believe I've addressed the issues above, with the exception of adding a |
Cool - will try to review one last time tonight and get it merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, about to merge.
This change adds the base classes necessary for exposing user groups via extensions, and for declaring the permissions which apply to a user but are not necessarily directly granted to that user.
Overall, this involves:
UserGroup
interface, as well as the usualDelegatingUserGroup
, andDirectory<UserGroup>
onUserContext
.Permissions
, whichUser
andUserGroup
share, defining the interface common to any object which can be granted permissions.getEffectivePermissions()
function onUser
which returns aPermissions
that represents all permissions which apply to the user, even if those permissions are inherited through some arbitrary means (such as user groups). The traditionalgetUserPermissions()
,getConnectionPermissions()
, etc. directly on theUser
return permission sets which describe permissions which are directly granted only.getEffectiveUserGroups()
function onAuthenticatedUser
which allows implementations to expose the identity of a user's group memberships in addition to the user's own identity. This forms the means by which membership in groups can be shared across extensions (for example, LDAP group membership can affect a user in MySQL so long as an identical MySQL group exists, even if that user does not exist in MySQL).RelatedObjectSet
interface, similar toPermissionSet
, which abstracts batch add/remove operations on a group of objects sharing some arbitrary relation, such as the member users of a user group, the parent user groups of a user, etc. This allows relations between specific objects to be established or removed without affecting the existence of those objects (asDirectory
would require) nor necessarily other relations to those objects.The user groups themselves are exposed via a
Directory<UserGroup>
at theUserContext
level, like all other objects. A newObjectPermissionSet
for user group permissions is exposed withinPermissions
. User membership within groups, group membership within groups, the set of groups containing a particular user, and the set of groups containing a particular group can all be maintained through the various getters returningRelatedObjectSet
instances.Other than (1) updating the REST services and JavaScript to use effective permissions rather than directly-granted permissions and (2) any stubs necessary to allow the database auth to continue working, no changes outside the API are made here.
Assuming these changes move forward, I will open further pull requests for the REST API changes, interface changes, and finally database auth changes.