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

show warning in ui if user or role could not be resolved #3593

Merged
merged 1 commit into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ public Set<ConqueryPermission> getEffectivePermissions() {
return permissions;
}

public synchronized void addMember(User user) {
if (members.add(user.getId())) {
log.trace("Added user {} to group {}", user.getId(), getId());
updateStorage();
}
}

@Override
public void updateStorage() {
storage.updateGroup(this);
Expand All @@ -55,16 +62,9 @@ public GroupId createId() {
return new GroupId(name);
}

public synchronized void addMember(User user) {
if (members.add(user.getId())) {
log.trace("Added user {} to group {}", user.getId(), getId());
updateStorage();
}
}

public synchronized void removeMember(User user) {
if (members.remove(user.getId())) {
log.trace("Removed user {} from group {}", user.getId(), getId());
public synchronized void removeMember(UserId user) {
if (members.remove(user)) {
log.trace("Removed user {} from group {}", user, getId());
updateStorage();
}
}
Expand All @@ -84,9 +84,9 @@ public synchronized void addRole(Role role) {
}
}

public synchronized void removeRole(Role role) {
if (roles.remove(role.getId())) {
log.trace("Removed role {} from group {}", role.getId(), getId());
public synchronized void removeRole(RoleId role) {
if (roles.remove(role)) {
log.trace("Removed role {} from group {}", role, getId());
updateStorage();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@

import java.util.Set;

import com.bakdata.conquery.io.storage.MetaStorage;
import com.bakdata.conquery.models.auth.permissions.ConqueryPermission;
import com.bakdata.conquery.models.identifiable.ids.specific.RoleId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;

public interface RoleOwner {

void addRole(Role role);

void removeRole(Role role);
void removeRole(RoleId role);

/**
* Return a copy of the roles hold by the owner.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,6 @@ public Set<ConqueryPermission> getEffectivePermissions() {
return permissions;
}

@Override
public UserId createId() {
return new UserId(name);
}

public synchronized void addRole(Role role) {
if (roles.add(role.getId())) {
log.trace("Added role {} to user {}", role.getId(), getId());
Expand All @@ -85,9 +80,9 @@ public synchronized void addRole(Role role) {
}

@Override
public synchronized void removeRole(Role role) {
if (roles.remove(role.getId())) {
log.trace("Removed role {} from user {}", role.getId(), getId());
public synchronized void removeRole(RoleId role) {
if (roles.remove(role)) {
log.trace("Removed role {} from user {}", role, getId());
updateStorage();
}
}
Expand All @@ -101,7 +96,59 @@ public void updateStorage() {
storage.updateUser(this);
}

public void authorize(@NonNull Authorized object, @NonNull Ability ability) {
@Override
public UserId createId() {
return new UserId(name);
}

/**
* This class is non-static so it's a fixed part of the enclosing User object.
* It's protected for testing purposes only.
*/
public class ShiroUserAdapter extends FilteredUser {

@Getter
private final ThreadLocal<ConqueryAuthenticationInfo> authenticationInfo =
ThreadLocal.withInitial(() -> new ConqueryAuthenticationInfo(User.this, null, null, false, null));

@Override
public Object getPrincipal() {
return getId();
} @Override
public void checkPermission(Permission permission) throws AuthorizationException {
SecurityUtils.getSecurityManager().checkPermission(getPrincipals(), permission);
}

@Override
public void checkPermissions(Collection<Permission> permissions) throws AuthorizationException {
SecurityUtils.getSecurityManager().checkPermissions(getPrincipals(), permissions);
}

@Override
public PrincipalCollection getPrincipals() {
return authenticationInfo.get().getPrincipals();
}

@Override
public boolean isPermitted(Permission permission) {
return SecurityUtils.getSecurityManager().isPermitted(getPrincipals(), permission);
}

@Override
public boolean[] isPermitted(List<Permission> permissions) {
return SecurityUtils.getSecurityManager().isPermitted(getPrincipals(), permissions);
}

@Override
public boolean isPermittedAll(Collection<Permission> permissions) {
return SecurityUtils.getSecurityManager().isPermittedAll(getPrincipals(), permissions);
}





} public void authorize(@NonNull Authorized object, @NonNull Ability ability) {
if (isOwner(object)) {
return;
}
Expand Down Expand Up @@ -168,52 +215,5 @@ public User getUser() {
}


/**
* This class is non-static so it's a fixed part of the enclosing User object.
* It's protected for testing purposes only.
*/
public class ShiroUserAdapter extends FilteredUser {

@Getter
private final ThreadLocal<ConqueryAuthenticationInfo> authenticationInfo =
ThreadLocal.withInitial(() -> new ConqueryAuthenticationInfo(User.this, null, null, false, null));

@Override
public void checkPermission(Permission permission) throws AuthorizationException {
SecurityUtils.getSecurityManager().checkPermission(getPrincipals(), permission);
}

@Override
public void checkPermissions(Collection<Permission> permissions) throws AuthorizationException {
SecurityUtils.getSecurityManager().checkPermissions(getPrincipals(), permissions);
}

@Override
public PrincipalCollection getPrincipals() {
return authenticationInfo.get().getPrincipals();
}

@Override
public boolean isPermitted(Permission permission) {
return SecurityUtils.getSecurityManager().isPermitted(getPrincipals(), permission);
}

@Override
public boolean[] isPermitted(List<Permission> permissions) {
return SecurityUtils.getSecurityManager().isPermitted(getPrincipals(), permissions);
}

@Override
public boolean isPermittedAll(Collection<Permission> permissions) {
return SecurityUtils.getSecurityManager().isPermittedAll(getPrincipals(), permissions);
}


@Override
public Object getPrincipal() {
return getId();
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ public IntrospectionDelegatingRealm(MetaStorage storage, IntrospectionDelegating
this.keycloakApi = keycloakApi;
}

private static String extractDisplayName(JWTClaimsSet claims) {
try {
final String name = claims.getStringClaim("name");

if (StringUtils.isBlank(name)) {
throw new UnsupportedTokenException("Claim 'name' was empty");
}
return name;
}
catch (java.text.ParseException e) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FQN?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In der Klasse gibt leider zwei unterschiedliche mit selben namen

throw new IncorrectCredentialsException("Unable to extract username from token", e);
}
}

@Override
protected void onInit() {
super.onInit();
Expand Down Expand Up @@ -126,7 +140,6 @@ public ConqueryAuthenticationInfo doGetAuthenticationInfo(AuthenticationToken to
return new ConqueryAuthenticationInfo(user, token, this, true, URI.create(logoutEndpoint));
}


/**
* Is called on every request to ensure that the token is still valid.
*/
Expand Down Expand Up @@ -163,6 +176,12 @@ else if (!(response instanceof TokenIntrospectionSuccessResponse)) {

}

private static UserId getUserId(JWTClaimsSet claims) {
final String subject = claims.getSubject();
UserId userId = new UserId(subject);
log.trace("Extracted UserId {}", userId);
return userId;
}

private void validateAudiences(JWTClaimsSet claims) {
// Check if the token is intended for our client/resource
Expand All @@ -182,28 +201,6 @@ private void validateAudiences(JWTClaimsSet claims) {
}
}

private static UserId getUserId(JWTClaimsSet claims) {
final String subject = claims.getSubject();
UserId userId = new UserId(subject);
log.trace("Extracted UserId {}", userId);
return userId;
}

private static String extractDisplayName(JWTClaimsSet claims) {
try {
final String name = claims.getStringClaim("name");

if (StringUtils.isBlank(name)) {
throw new UnsupportedTokenException("Claim 'name' was empty");
}
return name;
}
catch (java.text.ParseException e) {
throw new IncorrectCredentialsException("Unable to extract username from token", e);
}
}


/**
* Validates token and synchronizes user and its group memberships with keycloak.
*/
Expand Down Expand Up @@ -232,6 +229,32 @@ public JWTClaimsSet load(String token) throws Exception {
return claimsSet;
}

private synchronized User getOrCreateUser(JWTClaimsSet claims) {
UserId userId = getUserId(claims);
final String displayName = extractDisplayName(claims);

User user = storage.getUser(userId);

if (user != null) {
log.trace("Found existing user: {}", user);
// Update display name if necessary
if (!user.getLabel().equals(displayName)) {
log.info("Updating display name of user [{}]: '{}' -> '{}'", user.getName(), user.getLabel(), displayName);
user.setLabel(displayName);
user.updateStorage();
}

return user;
}

// Construct a new User if none could be found in the storage
user = new User(userId.getName(), displayName, storage);
storage.addUser(user);
log.info("Created new user: {}", user);

return user;
}

@Nullable
private Set<Group> getUserGroups(JWTClaimsSet claims, String groupIdAttribute) {
final Set<KeycloakGroup> userGroups = keycloakApi.getUserGroups(claims.getSubject());
Expand All @@ -247,6 +270,25 @@ private Set<Group> getUserGroups(JWTClaimsSet claims, String groupIdAttribute) {
.collect(Collectors.toSet());
}

private void syncGroupMappings(User user, Set<Group> mappedGroupsToDo) {
// TODO mark mappings as managed by keycloak
for (Group group : storage.getAllGroups()) {
if (group.containsMember(user)) {
if (mappedGroupsToDo.contains(group)) {
// Mapping is still valid, remove from todo-list
mappedGroupsToDo.remove(group);
}
else {
// Mapping is not valid any more remove user from group
group.removeMember(user.getId());
}
}
}

for (Group group : mappedGroupsToDo) {
group.addMember(user);
}
}

private Optional<Group> tryGetGroup(KeycloakGroup keycloakGroup) {

Expand Down Expand Up @@ -306,54 +348,6 @@ private synchronized Group createGroup(String name, String label) {
return group;
}


private void syncGroupMappings(User user, Set<Group> mappedGroupsToDo) {
// TODO mark mappings as managed by keycloak
for (Group group : storage.getAllGroups()) {
if (group.containsMember(user)) {
if (mappedGroupsToDo.contains(group)) {
// Mapping is still valid, remove from todo-list
mappedGroupsToDo.remove(group);
}
else {
// Mapping is not valid any more remove user from group
group.removeMember(user);
}
}
}

for (Group group : mappedGroupsToDo) {
group.addMember(user);
}
}


private synchronized User getOrCreateUser(JWTClaimsSet claims) {
UserId userId = getUserId(claims);
final String displayName = extractDisplayName(claims);

User user = storage.getUser(userId);

if (user != null) {
log.trace("Found existing user: {}", user);
// Update display name if necessary
if (!user.getLabel().equals(displayName)) {
log.info("Updating display name of user [{}]: '{}' -> '{}'", user.getName(), user.getLabel(), displayName);
user.setLabel(displayName);
user.updateStorage();
}

return user;
}

// Construct a new User if none could be found in the storage
user = new User(userId.getName(), displayName, storage);
storage.addUser(user);
log.info("Created new user: {}", user);

return user;
}

}

}
Loading
Loading