package org.jboss.resteasy.skeleton.key.idm.service;
import org.jboss.resteasy.skeleton.key.idm.IdentityManager;
import org.jboss.resteasy.skeleton.key.idm.i18n.Messages;
import org.jboss.resteasy.skeleton.key.idm.model.data.Realm;
import org.jboss.resteasy.skeleton.key.idm.model.data.RequiredCredential;
import org.jboss.resteasy.skeleton.key.idm.model.data.Resource;
import org.jboss.resteasy.skeleton.key.idm.model.data.Role;
import org.jboss.resteasy.skeleton.key.idm.model.data.RoleMapping;
import org.jboss.resteasy.skeleton.key.idm.model.data.ScopeMapping;
import org.jboss.resteasy.skeleton.key.idm.model.data.User;
import org.jboss.resteasy.skeleton.key.idm.model.data.UserAttribute;
import org.jboss.resteasy.skeleton.key.idm.model.data.UserCredential;
import org.jboss.resteasy.skeleton.key.representations.idm.RealmRepresentation;
import org.jboss.resteasy.skeleton.key.representations.idm.RequiredCredentialRepresentation;
import org.jboss.resteasy.skeleton.key.representations.idm.ResourceRepresentation;
import org.jboss.resteasy.skeleton.key.representations.idm.RoleMappingRepresentation;
import org.jboss.resteasy.skeleton.key.representations.idm.ScopeMappingRepresentation;
import org.jboss.resteasy.skeleton.key.representations.idm.UserRepresentation;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Path("/realms")
public class RealmFactory
{
protected IdentityManager identityManager;
@Context
protected UriInfo uriInfo;
public RealmFactory(IdentityManager identityManager)
{
this.identityManager = identityManager;
}
@POST
@Consumes("application/json")
public Response importDomain(RealmRepresentation rep)
{
Realm realm = createRealm(rep);
UriBuilder builder = uriInfo.getRequestUriBuilder().path(realm.getId());
return Response.created(builder.build())
.entity(RealmResource.realmRep(realm, uriInfo))
.type(MediaType.APPLICATION_JSON_TYPE).build();
}
protected Realm createRealm(RealmRepresentation rep)
{
verifyRealmRepresentation(rep);
Realm realm = new Realm();
KeyPair keyPair = null;
try
{
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException(e);
}
realm.setPrivateKey(keyPair.getPrivate());
realm.setPublicKey(keyPair.getPublic());
realm.setName(rep.getRealm());
realm.setEnabled(rep.isEnabled());
realm.setTokenLifespan(rep.getTokenLifespan());
realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
realm.setSslNotRequired(rep.isSslNotRequired());
realm = identityManager.create(realm);
Map<String, User> userMap = new HashMap<String, User>();
Role adminRole = identityManager.create(realm, "admin");
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials())
{
RequiredCredential credential = new RequiredCredential();
credential.setType(requiredCred.getType());
credential.setInput(requiredCred.isInput());
credential.setSecret(requiredCred.isSecret());
identityManager.create(realm, credential);
}
for (UserRepresentation userRep : rep.getUsers())
{
User user = new User();
user.setUsername(userRep.getUsername());
user.setEnabled(userRep.isEnabled());
user = identityManager.create(realm, user);
userMap.put(user.getUsername(), user);
if (userRep.getCredentials() != null)
{
for (UserRepresentation.Credential cred : userRep.getCredentials())
{
UserCredential credential = new UserCredential();
credential.setType(cred.getType());
credential.setValue(cred.getValue());
credential.setHashed(cred.isHashed());
identityManager.create(user, credential);
}
}
if (userRep.getAttributes() != null)
{
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet())
{
UserAttribute attribute = new UserAttribute();
attribute.setName(entry.getKey());
attribute.setValue(entry.getValue());
identityManager.create(user, attribute);
}
}
}
for (RoleMappingRepresentation mapping : rep.getRoleMappings())
{
RoleMapping roleMapping = createRoleMapping(userMap, mapping);
User user = userMap.get(mapping.getUsername());
identityManager.create(realm, user, roleMapping);
}
for (ScopeMappingRepresentation scope : rep.getScopeMappings())
{
ScopeMapping scopeMapping = createScopeMapping(userMap, scope);
User user = userMap.get(scope.getUsername());
identityManager.create(realm, user, scopeMapping);
}
if (rep.getResources() != null)
{
for (ResourceRepresentation resourceRep : rep.getResources())
{
Resource resource = new Resource();
resource.setName(resourceRep.getName());
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
resource = identityManager.create(realm, resource);
if (resourceRep.getRoles() != null)
{
for (String role : resourceRep.getRoles())
{
Role r = identityManager.create(realm, resource, role);
}
}
if (resourceRep.getRoleMappings() != null)
{
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings())
{
RoleMapping roleMapping = createRoleMapping(userMap, mapping);
User user = userMap.get(mapping.getUsername());
identityManager.create(realm, resource, user, roleMapping);
}
}
if (resourceRep.getScopeMappings() != null)
{
for (ScopeMappingRepresentation mapping : resourceRep.getScopeMappings())
{
ScopeMapping scopeMapping = createScopeMapping(userMap, mapping);
User user = userMap.get(mapping.getUsername());
identityManager.create(realm, resource, user, scopeMapping);
}
}
}
}
return realm;
}
protected RoleMapping createRoleMapping(Map<String, User> userMap, RoleMappingRepresentation mapping)
{
RoleMapping roleMapping = new RoleMapping();
User user = userMap.get(mapping.getUsername());
roleMapping.setUserid(user.getId());
if (mapping.getSurrogates() != null)
{
for (String s : mapping.getSurrogates())
{
User surrogate = userMap.get(s);
roleMapping.getSurrogateIds().add(surrogate.getId());
}
}
for (String role : mapping.getRoles())
{
roleMapping.getRoles().add(role);
}
return roleMapping;
}
protected ScopeMapping createScopeMapping(Map<String, User> userMap, ScopeMappingRepresentation mapping)
{
ScopeMapping scopeMapping = new ScopeMapping();
User user = userMap.get(mapping.getUsername());
scopeMapping.setUserid(user.getId());
for (String role : mapping.getRoles())
{
scopeMapping.getRoles().add(role);
}
return scopeMapping;
}
protected void verifyRealmRepresentation(RealmRepresentation rep)
{
if (rep.getUsers() == null)
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noRealmAdminUsersDefined()).type("text/plain").build());
}
if (rep.getRequiredCredentials() == null)
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.realmCredentialRequirementsNotDefined()).type("text/plain").build());
}
if (rep.getRoleMappings() == null)
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noRealmAdminUsersDefined()).type("text/plain").build());
}
HashMap<String, UserRepresentation> userReps = new HashMap<String, UserRepresentation>();
for (UserRepresentation userRep : rep.getUsers()) userReps.put(userRep.getUsername(), userRep);
// make sure there is a user that has admin privileges for the realm
Set<UserRepresentation> admins = new HashSet<UserRepresentation>();
for (RoleMappingRepresentation mapping : rep.getRoleMappings())
{
if (!userReps.containsKey(mapping.getUsername()))
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noUsersDeclaredForRoleMapping()).type("text/plain").build());
}
for (String role : mapping.getRoles())
{
if (!role.equals("admin"))
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.thereIsOnlyAdminRole()).type("text/plain").build());
} else
{
admins.add(userReps.get(mapping.getUsername()));
}
}
}
if (admins.size() == 0)
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noRealmAdminUsersDefined()).type("text/plain").build());
}
// override enabled to false if user does not have at least all of browser or client credentials
for (UserRepresentation userRep : rep.getUsers())
{
if (!userRep.isEnabled())
{
admins.remove(userRep);
continue;
}
if (userRep.getCredentials() == null)
{
admins.remove(userRep);
userRep.setEnabled(false);
} else
{
boolean hasBrowserCredentials = true;
for (RequiredCredentialRepresentation credential : rep.getRequiredCredentials())
{
boolean hasCredential = false;
for (UserRepresentation.Credential cred : userRep.getCredentials())
{
if (cred.getType().equals(credential.getType()))
{
hasCredential = true;
break;
}
}
if (!hasCredential)
{
hasBrowserCredentials = false;
break;
}
}
if (!hasBrowserCredentials)
{
userRep.setEnabled(false);
admins.remove(userRep);
}
}
}
if (admins.size() == 0)
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noRealmAdminUsersEnabled()).type("text/plain").build());
}
if (rep.getResources() != null)
{
// check mappings
for (ResourceRepresentation resourceRep : rep.getResources())
{
if (resourceRep.getRoleMappings() != null)
{
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings())
{
if (!userReps.containsKey(mapping.getUsername()))
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noUsersDeclaredForRoleMapping()).type("text/plain").build());
}
if (mapping.getSurrogates() != null)
{
for (String surrogate : mapping.getSurrogates())
{
if (!userReps.containsKey(surrogate))
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noUsersDeclaredForRoleMappingSurrogate()).type("text/plain").build());
}
}
}
for (String role : mapping.getRoles())
{
if (!resourceRep.getRoles().contains(role))
{
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity(Messages.MESSAGES.noResourceRoleForRoleMapping()).type("text/plain").build());
}
}
}
}
}
}
}
}