import java.util.List;
import javax.annotation.PostConstruct;
-import javax.naming.ldap.LdapName;
import org.argeo.api.cms.CmsSession;
+import org.argeo.cms.auth.RoleNameUtils;
import org.argeo.eclipse.ui.ColumnViewerComparator;
import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
import org.argeo.util.LangUtils;
private static final long serialVersionUID = -5234573509093747505L;
public String getText(Object element) {
- LdapName userDn = ((CmsSession) element).getUserDn();
- return userDn.getRdn(userDn.size() - 1).getValue().toString();
+ String userDn = ((CmsSession) element).getUserDn();
+ return RoleNameUtils.getLastRdnValue(userDn);
}
public String getToolTipText(Object element) {
Map<String, String> dns = new HashMap<String, String>();
for (UserDirectory userDirectory : userDirectories.keySet()) {
Boolean readOnly = userDirectory.isReadOnly();
- String baseDn = userDirectory.getGlobalId();
+ String baseDn = userDirectory.getContext();
if (onlyWritable && readOnly)
continue;
// private final UUID uuid;
+ public ContentName(String namespaceURI, String localPart) {
+ super(namespaceURI, localPart, checkPrefix(RuntimeNamespaceContext.getNamespaceContext(), namespaceURI));
+ }
+
public ContentName(String namespaceURI, String localPart, NamespaceContext nsContext) {
super(namespaceURI, localPart, checkPrefix(nsContext, namespaceURI));
}
;
public final static String CR_NAMESPACE_URI = "http://argeo.org/ns/cr";
-// public final static String CR_BASIC_NAMESPACE_URI = CR_NAMESPACE_URI + "/basic";
-// public final static String CR_OWNER_NAMESPACE_URI = CR_NAMESPACE_URI + "/owner";
-// public final static String CR_POSIX_NAMESPACE_URI = CR_NAMESPACE_URI + "/posix";
public final static String CR_DEFAULT_PREFIX = "cr";
public final static String LDAP_NAMESPACE_URI = "http://argeo.org/ns/ldap";
public final static String LDAP_DEFAULT_PREFIX = "ldap";
-
+ public final static String ROLE_NAMESPACE_URI = "http://argeo.org/ns/role";
+ public final static String ROLE_DEFAULT_PREFIX = "role";
+
private final ContentName value;
CrName() {
--- /dev/null
+package org.argeo.api.acr;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import javax.xml.namespace.NamespaceContext;
+
+/**
+ * Programmatically defined {@link NamespaceContext}, code contributing
+ * namespaces MUST register here with a single default prefix.
+ */
+public class RuntimeNamespaceContext implements NamespaceContext {
+ private NavigableMap<String, String> prefixes = new TreeMap<>();
+ private NavigableMap<String, String> namespaces = new TreeMap<>();
+
+ @Override
+ public String getPrefix(String namespaceURI) {
+ return NamespaceUtils.getPrefix((ns) -> {
+ String prefix = namespaces.get(ns);
+ if (prefix == null)
+ throw new IllegalStateException("Namespace " + ns + " is not registered.");
+ return prefix;
+ }, namespaceURI);
+ }
+
+ @Override
+ public String getNamespaceURI(String prefix) {
+ return NamespaceUtils.getNamespaceURI((p) -> {
+ String ns = prefixes.get(p);
+ if (ns == null)
+ throw new IllegalStateException("Prefix " + p + " is not registered.");
+ return ns;
+ }, prefix);
+ }
+
+ @Override
+ public Iterator<String> getPrefixes(String namespaceURI) {
+ return Collections.singleton(getPrefix(namespaceURI)).iterator();
+ }
+
+ /*
+ * STATIC
+ */
+
+ private final static RuntimeNamespaceContext INSTANCE = new RuntimeNamespaceContext();
+
+ static {
+ register(CrName.CR_NAMESPACE_URI, CrName.CR_DEFAULT_PREFIX);
+ register(CrName.LDAP_NAMESPACE_URI, CrName.LDAP_DEFAULT_PREFIX);
+ register(CrName.ROLE_NAMESPACE_URI, CrName.ROLE_DEFAULT_PREFIX);
+ }
+
+ public static NamespaceContext getNamespaceContext() {
+ return INSTANCE;
+ }
+
+ public static Map<String, String> getPrefixes() {
+ return Collections.unmodifiableNavigableMap(INSTANCE.prefixes);
+ }
+
+ public synchronized static void register(String namespaceURI, String prefix) {
+ NavigableMap<String, String> prefixes = INSTANCE.prefixes;
+ NavigableMap<String, String> namespaces = INSTANCE.namespaces;
+ if (prefixes.containsKey(prefix)) {
+ String ns = prefixes.get(prefix);
+ if (ns.equals(namespaceURI))
+ return; // ignore silently
+ throw new IllegalStateException("Prefix " + prefix + " is already registered with namespace URI " + ns);
+ }
+ if (namespaces.containsKey(namespaceURI)) {
+ String p = namespaces.get(namespaceURI);
+ if (p.equals(prefix))
+ return; // ignore silently
+ throw new IllegalStateException("Namespace " + namespaceURI + " is already registered with prefix " + p);
+ }
+ prefixes.put(prefix, namespaceURI);
+ namespaces.put(namespaceURI, prefix);
+ }
+}
import org.argeo.api.acr.Content;
import org.argeo.api.acr.ContentSession;
+import org.argeo.api.acr.RuntimeNamespaceContext;
/** A {@link ContentSession} implementation. */
public interface ProvidedSession extends ContentSession {
@Override
default String getPrefix(String namespaceURI) {
- Iterator<String> prefixes = getPrefixes(namespaceURI);
- return prefixes.hasNext() ? prefixes.next() : null;
+ return RuntimeNamespaceContext.getNamespaceContext().getPrefix(namespaceURI);
}
-// /** @return the bound namespace or null if not found */
-// String findNamespace(String prefix);
-//
-// // TODO find the default prefix?
-// Set<String> findPrefixes(String namespaceURI);
-//
-// /** To be overridden for optimisation, as it will be called a lot */
-// default String findPrefix(String namespaceURI) {
-// Set<String> prefixes = findPrefixes(namespaceURI);
-// if (prefixes.isEmpty())
-// return null;
-// return prefixes.iterator().next();
-// }
-
-// @Override
-// default String getNamespaceURI(String prefix) {
-// String namespaceURI = NamespaceUtils.getStandardNamespaceURI(prefix);
-// if (namespaceURI != null)
-// return namespaceURI;
-// if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix))
-// return XMLConstants.NULL_NS_URI;
-// namespaceURI = findNamespace(prefix);
-// if (namespaceURI != null)
-// return namespaceURI;
-// return XMLConstants.NULL_NS_URI;
-// }
-//
-// @Override
-// default String getPrefix(String namespaceURI) {
-// String prefix = NamespaceUtils.getStandardPrefix(namespaceURI);
-// if (prefix != null)
-// return prefix;
-// if (XMLConstants.NULL_NS_URI.equals(namespaceURI))
-// return XMLConstants.DEFAULT_NS_PREFIX;
-// return findPrefix(namespaceURI);
-// }
-//
-// @Override
-// default Iterator<String> getPrefixes(String namespaceURI) {
-// Iterator<String> standard = NamespaceUtils.getStandardPrefixes(namespaceURI);
-// if (standard != null)
-// return standard;
-// if (XMLConstants.NULL_NS_URI.equals(namespaceURI))
-// return Collections.singleton(XMLConstants.DEFAULT_NS_PREFIX).iterator();
-// Set<String> prefixes = findPrefixes(namespaceURI);
-// assert prefixes != null;
-// return prefixes.iterator();
-// }
+ @Override
+ default String getNamespaceURI(String prefix) {
+ return RuntimeNamespaceContext.getNamespaceContext().getNamespaceURI(prefix);
+ }
+ @Override
+ default Iterator<String> getPrefixes(String namespaceURI) {
+ return RuntimeNamespaceContext.getNamespaceContext().getPrefixes(namespaceURI);
+ }
}
import java.util.UUID;
import java.util.function.Consumer;
-import javax.naming.ldap.LdapName;
import javax.security.auth.Subject;
/** An authenticated user session. */
String getUserRole();
- LdapName getUserDn();
+ String getUserDn();
String getLocalId();
import org.argeo.api.acr.Content;
import org.argeo.api.acr.CrName;
+import org.argeo.api.acr.RuntimeNamespaceContext;
import org.argeo.api.acr.spi.ContentProvider;
import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.acr.spi.ProvidedRepository;
document = dBuilder.newDocument();
Element root = document.createElementNS(CrName.CR_NAMESPACE_URI, CrName.ROOT.get().toPrefixedString());
- for (String prefix : typesManager.getPrefixes().keySet()) {
+ for (String prefix : RuntimeNamespaceContext.getPrefixes().keySet()) {
// root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix,
// contentTypesManager.getPrefixes().get(prefix));
- DomUtils.addNamespace(root, prefix, typesManager.getPrefixes().get(prefix));
+ DomUtils.addNamespace(root, prefix,
+ RuntimeNamespaceContext.getNamespaceContext().getNamespaceURI(prefix));
}
document.appendChild(root);
import org.argeo.api.acr.ContentSession;
import org.argeo.api.acr.CrName;
import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.RuntimeNamespaceContext;
import org.argeo.api.acr.spi.ContentProvider;
import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.acr.spi.ProvidedRepository;
* NAMESPACE CONTEXT
*/
- @Override
- public String getNamespaceURI(String prefix) {
- return NamespaceUtils.getNamespaceURI((p) -> contentRepository.getTypesManager().getPrefixes().get(p), prefix);
- }
-
- @Override
- public Iterator<String> getPrefixes(String namespaceURI) {
- return NamespaceUtils.getPrefixes((ns) -> contentRepository.getTypesManager().getPrefixes().entrySet().stream()
- .filter(e -> e.getValue().equals(ns)).map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()),
- namespaceURI);
- }
+// @Override
+// public String getNamespaceURI(String prefix) {
+// return RuntimeNamespaceContext.getNamespaceContext().getNamespaceURI(prefix);
+//// return NamespaceUtils.getNamespaceURI((p) -> contentRepository.getTypesManager().getPrefixes().get(p), prefix);
+// }
+//
+// @Override
+// public Iterator<String> getPrefixes(String namespaceURI) {
+// return RuntimeNamespaceContext.getNamespaceContext().getPrefixes(namespaceURI);
+//// return NamespaceUtils.getPrefixes((ns) -> contentRepository.getTypesManager().getPrefixes().entrySet().stream()
+//// .filter(e -> e.getValue().equals(ns)).map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()),
+//// namespaceURI);
+// }
@Override
public CompletionStage<ContentSession> edit(Consumer<ContentSession> work) {
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.xerces.xs.XSTypeDefinition;
import org.argeo.api.acr.CrAttributeType;
import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.RuntimeNamespaceContext;
import org.argeo.api.cms.CmsLog;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
/** Register content types. */
class TypesManager {
private final static CmsLog log = CmsLog.getLog(TypesManager.class);
- private Map<String, String> prefixes = new TreeMap<>();
+// private Map<String, String> prefixes = new TreeMap<>();
// immutable factories
private SchemaFactory schemaFactory;
for (CmsContentTypes cs : CmsContentTypes.values()) {
StreamSource source = new StreamSource(cs.getResource().toExternalForm());
sources.add(source);
- if (prefixes.containsKey(cs.getDefaultPrefix()))
- throw new IllegalStateException("Prefix " + cs.getDefaultPrefix() + " is already mapped with "
- + prefixes.get(cs.getDefaultPrefix()));
- prefixes.put(cs.getDefaultPrefix(), cs.getNamespace());
+// if (prefixes.containsKey(cs.getDefaultPrefix()))
+// throw new IllegalStateException("Prefix " + cs.getDefaultPrefix() + " is already mapped with "
+// + prefixes.get(cs.getDefaultPrefix()));
+// prefixes.put(cs.getDefaultPrefix(), cs.getNamespace());
+ RuntimeNamespaceContext.register(cs.getNamespace(), cs.getDefaultPrefix());
}
reload();
}
public synchronized void registerTypes(String defaultPrefix, String namespace, String xsdSystemId) {
- if (prefixes.containsKey(defaultPrefix))
- throw new IllegalStateException(
- "Prefix " + defaultPrefix + " is already mapped with " + prefixes.get(defaultPrefix));
- prefixes.put(defaultPrefix, namespace);
+// if (prefixes.containsKey(defaultPrefix))
+// throw new IllegalStateException(
+// "Prefix " + defaultPrefix + " is already mapped with " + prefixes.get(defaultPrefix));
+// prefixes.put(defaultPrefix, namespace);
+ RuntimeNamespaceContext.register(namespace, defaultPrefix);
sources.add(new StreamSource(xsdSystemId));
reload();
}
}
- public Map<String, String> getPrefixes() {
- return prefixes;
- }
+// public Map<String, String> getPrefixes() {
+// return prefixes;
+// }
public List<Source> getSources() {
return sources;
@Override
public Iterator<Content> iterator() {
List<Content> res = new ArrayList<>();
- for (Iterator<HierarchyUnit> it = directory.getRootHierarchyUnits(false).iterator(); it.hasNext();) {
+ for (Iterator<HierarchyUnit> it = directory.getDirectHierarchyUnits(false).iterator(); it.hasNext();) {
res.add(new HierarchyUnitContent(getSession(), provider, it.next()));
}
return res.iterator();
@Override
public Iterator<Content> iterator() {
List<Content> lst = new ArrayList<>();
- for (HierarchyUnit hu : hierarchyUnit.getDirectHierachyUnits())
+ for (HierarchyUnit hu : hierarchyUnit.getDirectHierachyUnits(false))
lst.add(new HierarchyUnitContent(getSession(), provider, hu));
for (Role role : hierarchyUnit.getHierarchyUnitRoles(null, false))
package org.argeo.cms.auth;
+import static org.argeo.api.cms.CmsConstants.ROLE_ADMIN;
+import static org.argeo.api.cms.CmsConstants.ROLE_ANONYMOUS;
+import static org.argeo.api.cms.CmsConstants.ROLE_USER;
+import static org.argeo.api.cms.CmsConstants.ROLE_USER_ADMIN;
+
import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
+//import javax.naming.InvalidNameException;
+//import javax.naming.ldap.LdapName;
import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;
import org.argeo.cms.internal.auth.ImpliedByPrincipal;
import org.argeo.cms.internal.http.WebCmsSessionImpl;
import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.cms.security.NodeSecurityUtils;
import org.argeo.osgi.useradmin.AuthenticatingUser;
import org.osgi.service.http.HttpContext;
import org.osgi.service.useradmin.Authorization;
final static String SINGLE_USER_LOCAL_ID = "single-user";
+ private final static List<String> RESERVED_ROLES = Collections
+ .unmodifiableList(Arrays.asList(new String[] { ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_USER, ROLE_USER_ADMIN }));
+
static void addAuthorization(Subject subject, Authorization authorization) {
assert subject != null;
checkSubjectEmpty(subject);
boolean singleUser = authorization instanceof SingleUserAuthorization;
Set<Principal> principals = subject.getPrincipals();
- try {
- String authName = authorization.getName();
-
- // determine user's principal
- final LdapName name;
- final Principal userPrincipal;
- if (authName == null) {
- name = NodeSecurityUtils.ROLE_ANONYMOUS_NAME;
- userPrincipal = new AnonymousPrincipal();
- principals.add(userPrincipal);
- } else {
- name = new LdapName(authName);
- NodeSecurityUtils.checkUserName(name);
- userPrincipal = new X500Principal(name.toString());
- principals.add(userPrincipal);
-
- if (singleUser) {
- principals.add(new ImpliedByPrincipal(NodeSecurityUtils.ROLE_ADMIN_NAME, userPrincipal));
- principals.add(new DataAdminPrincipal());
- }
+// try {
+ String authName = authorization.getName();
+
+ // determine user's principal
+// final LdapName name;
+ final Principal userPrincipal;
+ if (authName == null) {
+// name = NodeSecurityUtils.ROLE_ANONYMOUS_NAME;
+ userPrincipal = new AnonymousPrincipal();
+ principals.add(userPrincipal);
+ } else {
+// name = new LdapName(authName);
+ checkUserName(authName);
+ userPrincipal = new X500Principal(authName.toString());
+ principals.add(userPrincipal);
+
+ if (singleUser) {
+ principals.add(new ImpliedByPrincipal(CmsConstants.ROLE_ADMIN, userPrincipal));
+ principals.add(new DataAdminPrincipal());
}
+ }
- // Add roles provided by authorization
- for (String role : authorization.getRoles()) {
- LdapName roleName = new LdapName(role);
- if (roleName.equals(name)) {
- // skip
- } else if (roleName.equals(NodeSecurityUtils.ROLE_ANONYMOUS_NAME)) {
- // skip
- } else {
- NodeSecurityUtils.checkImpliedPrincipalName(roleName);
- principals.add(new ImpliedByPrincipal(roleName.toString(), userPrincipal));
- if (roleName.equals(NodeSecurityUtils.ROLE_ADMIN_NAME))
- principals.add(new DataAdminPrincipal());
- }
+ // Add roles provided by authorization
+ for (String role : authorization.getRoles()) {
+// LdapName roleName = new LdapName(role);
+ if (role.equals(authName)) {
+ // skip
+ } else if (role.equals(CmsConstants.ROLE_ANONYMOUS)) {
+ // skip
+ } else {
+// NodeSecurityUtils.checkImpliedPrincipalName(role);
+ principals.add(new ImpliedByPrincipal(role, userPrincipal));
+ if (role.equals(CmsConstants.ROLE_ADMIN))
+ principals.add(new DataAdminPrincipal());
}
-
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Cannot commit", e);
}
+
+// } catch (InvalidNameException e) {
+// throw new IllegalArgumentException("Cannot commit", e);
+// }
}
private static void checkSubjectEmpty(Subject subject) {
return principals.iterator().next();
}
+ private static void checkUserName(String name) throws IllegalArgumentException {
+ if (RESERVED_ROLES.contains(name))
+ throw new IllegalArgumentException(name + " is a reserved name");
+ }
+
private CmsAuthUtils() {
}
--- /dev/null
+package org.argeo.cms.auth;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.ContentName;
+import org.argeo.api.acr.CrName;
+
+public enum CmsRole implements SystemRole {
+ userAdmin, //
+ groupAdmin;
+
+ private final static String QUALIFIER = "cms.";
+
+ private final ContentName name;
+
+ CmsRole() {
+ name = new ContentName(CrName.ROLE_NAMESPACE_URI, QUALIFIER + name());
+ }
+
+ public QName getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return name.toPrefixedString();
+ }
+}
return roles.contains(role);
}
+ /** Implies this {@link SystemRole} in this context. */
+ public final static boolean implies(SystemRole role, String context) {
+ return role.implied(currentSubject(), context);
+ }
+
/** Executes as the current user */
public final static <T> T doAs(PrivilegedAction<T> action) {
return Subject.doAs(currentSubject(), action);
--- /dev/null
+package org.argeo.cms.auth;
+
+public class RoleNameUtils {
+
+ /*
+ * UTILITIES
+ */
+ public final static String getLastRdnValue(String dn) {
+ // we don't use LdapName for portability with Android
+ // TODO make it more robust
+ String[] parts = dn.split(",");
+ String[] rdn = parts[0].split("=");
+ return rdn[1];
+ }
+
+ public final static String getParent(String dn) {
+ int index = dn.indexOf(',');
+ return dn.substring(index + 1);
+ }
+
+ /** Up two levels. */
+ public final static String getContext(String dn) {
+ return getParent(getParent(dn));
+ }
+}
--- /dev/null
+package org.argeo.cms.auth;
+
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.xml.namespace.QName;
+
+import org.argeo.cms.internal.auth.ImpliedByPrincipal;
+
+public interface SystemRole {
+ QName getName();
+
+ default boolean implied(Subject subject, String context) {
+ Set<ImpliedByPrincipal> roles = subject.getPrincipals(ImpliedByPrincipal.class);
+ for (ImpliedByPrincipal role : roles) {
+ if (role.isSystemRole()) {
+ if (role.getRoleName().equals(getName())) {
+ if (role.getContext().equalsIgnoreCase(context))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
import java.util.function.Consumer;
import javax.crypto.SecretKey;
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.x500.X500Principal;
import org.argeo.api.cms.CmsAuth;
+import org.argeo.api.cms.CmsConstants;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsSession;
import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.cms.security.NodeSecurityUtils;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.useradmin.Authorization;
private final UUID uuid;
private final String localSessionId;
private Authorization authorization;
- private final LdapName userDn;
+// private final LdapName userDn;
+ private final String userDn;
private final boolean anonymous;
private final ZonedDateTime creationTime;
// this.initialSubject = initialSubject;
this.localSessionId = localSessionId;
this.authorization = authorization;
- if (authorization.getName() != null)
- try {
- this.userDn = new LdapName(authorization.getName());
- this.anonymous = false;
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Invalid user name " + authorization.getName(), e);
- }
- else {
- this.userDn = NodeSecurityUtils.ROLE_ANONYMOUS_NAME;
+ if (authorization.getName() != null) {
+ this.userDn = authorization.getName();
+ this.anonymous = false;
+ } else {
+ this.userDn = CmsConstants.ROLE_ANONYMOUS;
this.anonymous = true;
}
this.uuid = uuid;
}
@Override
- public LdapName getUserDn() {
+ public String getUserDn() {
return userDn;
}
Map<String, String> dns = new HashMap<String, String>();
for (UserDirectory userDirectory : userDirectories.keySet()) {
Boolean readOnly = userDirectory.isReadOnly();
- String baseDn = userDirectory.getGlobalId();
+ String baseDn = userDirectory.getContext();
if (onlyWritable && readOnly)
continue;
}
public Set<UserDirectory> getUserDirectories() {
- TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getGlobalId().compareTo(o2.getGlobalId()));
+ TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getContext().compareTo(o2.getContext()));
res.addAll(userDirectories.keySet());
return res;
}
String name = user.getName();
NavigableMap<String, UserDirectory> possible = new TreeMap<>();
for (UserDirectory userDirectory : userDirectories.keySet()) {
- if (name.endsWith(userDirectory.getGlobalId())) {
- possible.put(userDirectory.getGlobalId(), userDirectory);
+ if (name.endsWith(userDirectory.getContext())) {
+ possible.put(userDirectory.getContext(), userDirectory);
}
}
if (possible.size() == 0)
package org.argeo.cms.internal.auth;
+import static org.argeo.api.acr.RuntimeNamespaceContext.getNamespaceContext;
+
import java.security.Principal;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
+import javax.xml.namespace.QName;
+import org.argeo.api.acr.CrName;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.cms.auth.RoleNameUtils;
import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Role;
/**
* A {@link Principal} which has been implied by an {@link Authorization}. If it
* identity is removed, the related {@link ImpliedByPrincipal}s can thus be
* removed.
*/
-public final class ImpliedByPrincipal implements Principal, Role {
- private final LdapName name;
+public final class ImpliedByPrincipal implements Principal {
+ private final String name;
private Set<Principal> causes = new HashSet<Principal>();
- private int type = Role.ROLE;
+ private QName roleName;
+// private int type = Role.ROLE;
+
+ private boolean systemRole = false;
+ private String context;
public ImpliedByPrincipal(String name, Principal userPrincipal) {
- try {
- this.name = new LdapName(name);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Badly formatted role name", e);
+ this.name = name;
+ String cn = RoleNameUtils.getLastRdnValue(name);
+ roleName = NamespaceUtils.parsePrefixedName(getNamespaceContext(), cn);
+ if (roleName.getNamespaceURI().equals(CrName.ROLE_NAMESPACE_URI)) {
+ systemRole = true;
}
+ context = RoleNameUtils.getContext(name);
+// try {
+// this.name = new LdapName(name);
+// } catch (InvalidNameException e) {
+// throw new IllegalArgumentException("Badly formatted role name", e);
+// }
if (userPrincipal != null)
causes.add(userPrincipal);
}
- public ImpliedByPrincipal(LdapName name, Principal userPrincipal) {
- this.name = name;
- if (userPrincipal != null)
- causes.add(userPrincipal);
- }
+// public ImpliedByPrincipal(LdapName name, Principal userPrincipal) {
+// this.name = name;
+// if (userPrincipal != null)
+// causes.add(userPrincipal);
+// }
public String getName() {
- return name.toString();
- }
-
- public boolean addMember(Principal user) {
- throw new UnsupportedOperationException();
- }
-
- public boolean removeMember(Principal user) {
- throw new UnsupportedOperationException();
- }
-
- public boolean isMember(Principal member) {
- return causes.contains(member);
- }
-
- public Enumeration<? extends Principal> members() {
- return Collections.enumeration(causes);
+ return name;
}
/*
* USER ADMIN
*/
+// public boolean addMember(Principal user) {
+// throw new UnsupportedOperationException();
+// }
+//
+// public boolean removeMember(Principal user) {
+// throw new UnsupportedOperationException();
+// }
+//
+// public boolean isMember(Principal member) {
+// return causes.contains(member);
+// }
+//
+// public Enumeration<? extends Principal> members() {
+// return Collections.enumeration(causes);
+// }
+//
+//
+// /** Type of {@link Role}, if known. */
+// public int getType() {
+// return type;
+// }
+//
+// /** Not supported for the time being. */
+// public Dictionary<String, Object> getProperties() {
+// throw new UnsupportedOperationException();
+// }
- @Override
- /** Type of {@link Role}, if known. */
- public int getType() {
- return type;
+ /*
+ * OBJECT
+ */
+
+ public QName getRoleName() {
+ return roleName;
}
- @Override
- /** Not supported for the time being. */
- public Dictionary<String, Object> getProperties() {
- throw new UnsupportedOperationException();
+ public String getContext() {
+ return context;
}
- /*
- * OBJECT
- */
+ public boolean isSystemRole() {
+ return systemRole;
+ }
@Override
public int hashCode() {
} else {
throw new IllegalArgumentException("Unsupported scheme " + u.getScheme());
}
- String basePath = userDirectory.getGlobalId();
+ String basePath = userDirectory.getContext();
addUserDirectory(userDirectory);
if (isSystemRolesBaseDn(basePath)) {
addStandardSystemRoles();
}
if (log.isDebugEnabled()) {
- log.debug("User directory " + userDirectory.getGlobalId() + (u != null ? " [" + u.getScheme() + "]" : "")
+ log.debug("User directory " + userDirectory.getContext() + (u != null ? " [" + u.getScheme() + "]" : "")
+ " enabled." + (realm != null ? " " + realm + " realm." : ""));
}
return userDirectory;
+++ /dev/null
-package org.argeo.cms.security;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.api.cms.CmsConstants;
-
-public class NodeSecurityUtils {
- public final static LdapName ROLE_ADMIN_NAME, ROLE_DATA_ADMIN_NAME, ROLE_ANONYMOUS_NAME, ROLE_USER_NAME,
- ROLE_USER_ADMIN_NAME;
- public final static List<LdapName> RESERVED_ROLES;
- static {
- try {
- ROLE_ADMIN_NAME = new LdapName(CmsConstants.ROLE_ADMIN);
- ROLE_DATA_ADMIN_NAME = new LdapName(CmsConstants.ROLE_DATA_ADMIN);
- ROLE_USER_NAME = new LdapName(CmsConstants.ROLE_USER);
- ROLE_USER_ADMIN_NAME = new LdapName(CmsConstants.ROLE_USER_ADMIN);
- ROLE_ANONYMOUS_NAME = new LdapName(CmsConstants.ROLE_ANONYMOUS);
- RESERVED_ROLES = Collections.unmodifiableList(Arrays.asList(
- new LdapName[] { ROLE_ADMIN_NAME, ROLE_ANONYMOUS_NAME, ROLE_USER_NAME, ROLE_USER_ADMIN_NAME }));
- } catch (InvalidNameException e) {
- throw new Error("Cannot initialize login module class", e);
- }
- }
-
- public static void checkUserName(LdapName name) throws IllegalArgumentException {
- if (RESERVED_ROLES.contains(name))
- throw new IllegalArgumentException(name + " is a reserved name");
- }
-
- public static void checkImpliedPrincipalName(LdapName roleName) throws IllegalArgumentException {
-// if (ROLE_USER_NAME.equals(roleName) || ROLE_ANONYMOUS_NAME.equals(roleName))
-// throw new IllegalArgumentException(roleName + " cannot be listed as role");
- }
-
-}
private final Hashtable<String, Object> properties;
private final LdapName baseDn;
// private final LdapName userBaseDn, groupBaseDn;
- private final Rdn userBaseRdn, groupBaseRdn;
- private final String userObjectClass, userBase, groupObjectClass, groupBase;
+ private final Rdn userBaseRdn, groupBaseRdn, systemRoleBaseRdn;
+ private final String userObjectClass, groupObjectClass;
private final boolean readOnly;
private final boolean disabled;
forcedPassword = UserAdminConf.forcedPassword.getValue(properties);
userObjectClass = UserAdminConf.userObjectClass.getValue(properties);
- userBase = UserAdminConf.userBase.getValue(properties);
+ String userBase = UserAdminConf.userBase.getValue(properties);
groupObjectClass = UserAdminConf.groupObjectClass.getValue(properties);
- groupBase = UserAdminConf.groupBase.getValue(properties);
+ String groupBase = UserAdminConf.groupBase.getValue(properties);
+ String systemRoleBase = UserAdminConf.systemRoleBase.getValue(properties);
try {
baseDn = new LdapName(UserAdminConf.baseDn.getValue(properties));
userBaseRdn = new Rdn(userBase);
// userBaseDn = new LdapName(userBase + "," + baseDn);
groupBaseRdn = new Rdn(groupBase);
// groupBaseDn = new LdapName(groupBase + "," + baseDn);
+ systemRoleBaseRdn = new Rdn(systemRoleBase);
} catch (InvalidNameException e) {
throw new IllegalArgumentException("Badly formated base DN " + UserAdminConf.baseDn.getValue(properties),
e);
*/
@Override
- public String getGlobalId() {
+ public String getContext() {
return getBaseDn().toString();
}
try {
LdapName name = (LdapName) getBaseDn().clone();
String[] segments = path.split("/");
- String parentSegment = null;
+ Rdn parentRdn = null;
for (String segment : segments) {
- String attr = "ou";
- if (parentSegment != null) {
- if (getUserBase().equals(parentSegment))
- attr = "uid";
- else if (getGroupBase().equals(parentSegment))
- attr = "cn";
+ // TODO make attr names configurable ?
+ String attr = LdapAttrs.ou.name();
+ if (parentRdn != null) {
+ if (getUserBaseRdn().equals(parentRdn))
+ attr = LdapAttrs.uid.name();
+ else if (getGroupBaseRdn().equals(parentRdn))
+ attr = LdapAttrs.cn.name();
+ else if (getSystemRoleBaseRdn().equals(parentRdn))
+ attr = LdapAttrs.cn.name();
}
Rdn rdn = new Rdn(attr, segment);
name.add(rdn);
-
- // TODO make it more robust using RDNs
- parentSegment = rdn.toString();
+ parentRdn = rdn;
}
return name;
} catch (InvalidNameException e) {
throw new UnsupportedOperationException();
}
- void isFunctionalHierarchyUnit(HierarchyUnit hu) {
-
- }
-
// @Override
// public List<? extends Role> getHierarchyUnitRoles(String filter, boolean deep) {
// try {
// }
@Override
- public Iterable<HierarchyUnit> getRootHierarchyUnits(boolean functionalOnly) {
+ public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
throw new UnsupportedOperationException();
}
}
protected DirectoryGroup newGroup(LdapName name, Attributes attrs) {
+ if (LdapNameUtils.getParentRdn(name).equals(getSystemRoleBaseRdn()))
+ return new LdifGroup.LdifSystemPermissions(this, name, attrs);
+
if (hasObjectClass(attrs, LdapObjs.organization))
return new LdifGroup.LdifOrganization(this, name, attrs);
else
protected int roleType(LdapName dn) {
Rdn technicalRdn = LdapNameUtils.getParentRdn(dn);
- if (groupBaseRdn.equals(technicalRdn))
+ if (getGroupBaseRdn().equals(technicalRdn) || getSystemRoleBaseRdn().equals(technicalRdn))
return Role.GROUP;
else if (userBaseRdn.equals(technicalRdn))
return Role.USER;
return userObjectClass;
}
- @Deprecated
- String getUserBase() {
- return userBase;
- }
-
Rdn getUserBaseRdn() {
return userBaseRdn;
}
return groupObjectClass;
}
- @Deprecated
- String getGroupBase() {
- return groupBase;
- }
-
Rdn getGroupBaseRdn() {
return groupBaseRdn;
}
+ Rdn getSystemRoleBaseRdn() {
+ return systemRoleBaseRdn;
+ }
+
LdapName getBaseDn() {
return (LdapName) baseDn.clone();
}
if (!(ud instanceof AbstractUserDirectory))
throw new IllegalArgumentException("Only " + AbstractUserDirectory.class.getName() + " is supported");
AbstractUserDirectory userDirectory = (AbstractUserDirectory) ud;
- String basePath = userDirectory.getGlobalId();
+ String basePath = userDirectory.getContext();
if (isSystemRolesBaseDn(basePath)) {
this.systemRoles = userDirectory;
systemRoles.setExternalRoles(this);
}
public Set<UserDirectory> getUserDirectories() {
- TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getGlobalId().compareTo(o2.getGlobalId()));
+ TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getContext().compareTo(o2.getContext()));
res.addAll(businessRoles.values());
return res;
}
HierarchyUnit getParent();
- Iterable<HierarchyUnit> getDirectHierachyUnits();
-
- Iterable<HierarchyUnit> getFunctionalHierachyUnits();
+ Iterable<HierarchyUnit> getDirectHierachyUnits(boolean functionalOnly);
boolean isFunctional();
- String getBasePath();
+ String getContext();
List<? extends Role> getHierarchyUnitRoles(String filter, boolean deep);
public class IpaUtils {
public final static String IPA_USER_BASE = "cn=users,cn=accounts";
public final static String IPA_GROUP_BASE = "cn=groups,cn=accounts";
+ public final static String IPA_ROLE_BASE = "cn=roles,cn=accounts";
public final static String IPA_SERVICE_BASE = "cn=services,cn=accounts";
private final static String KRB_PRINCIPAL_NAME = LdapAttrs.krbPrincipalName.name().toLowerCase();
properties.put(UserAdminConf.realm.name(), realm);
properties.put(UserAdminConf.userBase.name(), IPA_USER_BASE);
properties.put(UserAdminConf.groupBase.name(), IPA_GROUP_BASE);
+ properties.put(UserAdminConf.systemRoleBase.name(), IPA_ROLE_BASE);
properties.put(UserAdminConf.readOnly.name(), Boolean.TRUE.toString());
}
package org.argeo.osgi.useradmin;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
this.attributes = attributes;
Rdn rdn = LdapNameUtils.getLastRdn(dn);
- functional = !(directory.getUserBaseRdn().equals(rdn) || directory.getGroupBaseRdn().equals(rdn));
+ functional = !(directory.getUserBaseRdn().equals(rdn) || directory.getGroupBaseRdn().equals(rdn)
+ || directory.getSystemRoleBaseRdn().equals(rdn));
}
@Override
}
@Override
- public Iterable<HierarchyUnit> getDirectHierachyUnits() {
- return children;
- }
-
- @Override
- public Iterable<HierarchyUnit> getFunctionalHierachyUnits() {
+ public Iterable<HierarchyUnit> getDirectHierachyUnits(boolean functionalOnly) {
List<HierarchyUnit> res = new ArrayList<>();
- for (HierarchyUnit hu : children) {
- if (hu.isFunctional())
- res.add(hu);
- }
- return res;
+ if (functionalOnly)
+ for (HierarchyUnit hu : children) {
+ if (hu.isFunctional())
+ res.add(hu);
+ }
+ else
+ res.addAll(children);
+ return Collections.unmodifiableList(res);
}
@Override
}
@Override
- public String getBasePath() {
+ public String getContext() {
return dn.toString();
}
}
@Override
- public Iterable<HierarchyUnit> getRootHierarchyUnits(boolean functionalOnly) {
+ public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
if (functionalOnly) {
List<HierarchyUnit> res = new ArrayList<>();
for (HierarchyUnit hu : rootHierarchyUnits) {
public OsUserDirectory(URI uriArg, Dictionary<String, ?> props) {
super(uriArg, props, false);
try {
- osUserDn = new LdapName(LdapAttrs.uid.name() + "=" + osUsername + "," + getUserBase() + "," + getBaseDn());
+ osUserDn = new LdapName(LdapAttrs.uid.name() + "=" + osUsername + "," + getUserBaseRdn() + "," + getBaseDn());
Attributes attributes = new BasicAttributes();
attributes.put(LdapAttrs.uid.name(), osUsername);
osUser = newUser(osUserDn, attributes);
/** Relative base DN for users */
groupBase("ou=Groups"),
+ /** Relative base DN for users */
+ systemRoleBase("ou=Roles"),
+
/** Read-only source */
readOnly(null),
* The base of the hierarchy defined by this directory. This could typically be
* an LDAP base DN.
*/
- String getGlobalId();
+ String getContext();
String getName();
Optional<String> getRealm();
- Iterable<HierarchyUnit> getRootHierarchyUnits(boolean functionalOnly);
+ Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly);
HierarchyUnit getHierarchyUnit(String path);