io.quarkus.security.runtime.QuarkusSecurityIdentity Maven / Gradle / Ivy
package io.quarkus.security.runtime;
import java.security.Permission;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import io.quarkus.security.StringPermission;
import io.quarkus.security.credential.Credential;
import io.quarkus.security.identity.SecurityIdentity;
import io.smallrye.mutiny.Uni;
public class QuarkusSecurityIdentity implements SecurityIdentity {
private final Principal principal;
private final Set roles;
private final Set credentials;
private final Map attributes;
private final List>> permissionCheckers;
private final boolean anonymous;
private QuarkusSecurityIdentity(Builder builder) {
this.principal = builder.principal;
this.roles = Collections.unmodifiableSet(builder.roles);
this.credentials = Collections.unmodifiableSet(builder.credentials);
this.attributes = Collections.unmodifiableMap(builder.attributes);
this.permissionCheckers = Collections.unmodifiableList(builder.permissionCheckers);
this.anonymous = builder.anonymous;
}
@Override
public Principal getPrincipal() {
return principal;
}
@Override
public boolean isAnonymous() {
return anonymous;
}
@Override
public Set getRoles() {
return roles;
}
@Override
public boolean hasRole(String role) {
return roles.contains(role);
}
@Override
public T getCredential(Class credentialType) {
for (Credential i : credentials) {
if (credentialType.isAssignableFrom(i.getClass())) {
return (T) i;
}
}
return null;
}
@Override
public Set getCredentials() {
return credentials;
}
@Override
public T getAttribute(String name) {
return (T) attributes.get(name);
}
@Override
public Map getAttributes() {
return attributes;
}
@Override
public Uni checkPermission(Permission permission) {
if (permissionCheckers.isEmpty()) {
return Uni.createFrom().item(false);
}
List> results = new ArrayList<>(permissionCheckers.size());
for (Function> checker : permissionCheckers) {
Uni res = checker.apply(permission);
if (res != null) {
results.add(res);
}
}
if (results.isEmpty()) {
return Uni.createFrom().item(false);
}
if (results.size() == 1) {
return results.get(0);
}
return Uni.combine().all().unis(results).with(new Function, Boolean>() {
@Override
public Boolean apply(List> o) {
Boolean result = null;
//if any are true we return true
//otherwise if all are null we return null
//if some are false and some null we return false
for (Object i : o) {
if (i != null) {
boolean val = (boolean) i;
if (val) {
return true;
}
result = false;
}
}
return result;
}
});
}
public static Builder builder() {
return new Builder();
}
public static Builder builder(SecurityIdentity identity) {
Builder builder = new Builder()
.addAttributes(identity.getAttributes())
.addCredentials(identity.getCredentials())
.addRoles(identity.getRoles())
.addPermissionChecker(new Function>() {
@Override
public Uni apply(Permission permission) {
// sustain previous permission checks
return identity.checkPermission(permission);
}
})
.setPrincipal(identity.getPrincipal())
.setAnonymous(identity.isAnonymous());
return builder;
}
public static class Builder {
Principal principal;
Set roles = new HashSet<>();
Set credentials = new HashSet<>();
Set permissions = new HashSet<>();
Map attributes = new HashMap<>();
List>> permissionCheckers = new ArrayList<>();
private boolean anonymous;
boolean built = false;
public Builder setPrincipal(Principal principal) {
if (built) {
throw new IllegalStateException();
}
this.principal = principal;
return this;
}
public Builder addRole(String role) {
if (built) {
throw new IllegalStateException();
}
this.roles.add(role);
return this;
}
public Builder addRoles(Set roles) {
if (built) {
throw new IllegalStateException();
}
this.roles.addAll(roles);
return this;
}
public Builder addCredential(Credential credential) {
if (built) {
throw new IllegalStateException();
}
credentials.add(credential);
return this;
}
public Builder addCredentials(Set credentials) {
if (built) {
throw new IllegalStateException();
}
this.credentials.addAll(credentials);
return this;
}
public Builder addAttribute(String key, Object value) {
if (built) {
throw new IllegalStateException();
}
attributes.put(key, value);
return this;
}
public Builder addAttributes(Map attributes) {
if (built) {
throw new IllegalStateException();
}
this.attributes.putAll(attributes);
return this;
}
/**
* Adds a permission as String.
*
* @param permission The permission in a String format.
* @return This builder
*/
public Builder addPermissionAsString(String permission) {
return addPermissionsAsString(Set.of(permission));
}
/**
* Adds permissions as String
*
* @param permissions The permissions in a String format.
* @return This builder
*/
public Builder addPermissionsAsString(Set permissions) {
return addPermissions(permissions.stream().map(p -> toPermission(p))
.collect(Collectors.toSet()));
}
/**
* Adds a permission.
*
* @param permission The permission
* @return This builder
*/
public Builder addPermission(Permission permission) {
return addPermissions(Set.of(permission));
}
/**
* Adds permissions.
*
* @param permissions The permissions
* @return This builder
*/
public Builder addPermissions(Set permissions) {
this.permissions.addAll(permissions);
return this;
}
/**
* Adds a permission checker function. This permission checker has the following semantics:
*
* If it returns null, or the CompletionStage evaluates to null then this check is ignored
* If every function returns null or false then the check is failed
* If any function returns true the check passes
*
* @param function The permission checker function
* @return This builder
*/
public Builder addPermissionChecker(Function> function) {
if (built) {
throw new IllegalStateException();
}
permissionCheckers.add(function);
return this;
}
/**
* Adds a permission check functions.
*
* @param functions The permission check functions
* @return This builder
* @see #addPermissionChecker(Function)
*/
public Builder addPermissionCheckers(List>> functions) {
if (built) {
throw new IllegalStateException();
}
if (functions != null) {
permissionCheckers.addAll(functions);
}
return this;
}
/**
* Sets an anonymous identity status.
*
* @param anonymous the anonymous status
* @return This builder
*/
public Builder setAnonymous(boolean anonymous) {
if (built) {
throw new IllegalStateException();
}
this.anonymous = anonymous;
return this;
}
public QuarkusSecurityIdentity build() {
if (principal == null && !anonymous) {
throw new IllegalStateException("Principal is null but anonymous status is false");
}
addPossesedPermissionsChecker();
built = true;
return new QuarkusSecurityIdentity(this);
}
private void addPossesedPermissionsChecker() {
if (!permissions.isEmpty()) {
addPermissionChecker(
new Function>() {
@Override
public Uni apply(Permission requiredPermission) {
for (Permission possessedPermission : permissions) {
if (possessedPermission.implies(requiredPermission)) {
return Uni.createFrom().item(true);
}
}
return Uni.createFrom().item(false);
}
});
}
}
static Permission toPermission(String permissionAsString) {
int semicolonIndex = permissionAsString.indexOf(':');
if (semicolonIndex > 0 && semicolonIndex < permissionAsString.length() - 1) {
return new StringPermission(permissionAsString.substring(0, semicolonIndex),
permissionAsString.substring(semicolonIndex + 1));
} else {
return new StringPermission(permissionAsString);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy