retire Transaction

This commit is contained in:
Bill Burke 2013-09-11 09:28:19 -04:00
parent b38889f28c
commit b0bbbeaf7f
45 changed files with 1091 additions and 1326 deletions

View file

@ -29,15 +29,10 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>tjws</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View file

@ -24,8 +24,8 @@
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>

View file

@ -24,8 +24,8 @@
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>

View file

@ -11,6 +11,8 @@ import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.SaasService;
import org.keycloak.services.resources.SaasService;
import javax.servlet.ServletContext;
import javax.ws.rs.core.Context;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -20,8 +22,8 @@ import java.io.InputStream;
*/
public class DemoApplication extends KeycloakApplication {
public DemoApplication() {
super();
public DemoApplication(@Context ServletContext servletContext) {
super(servletContext);
KeycloakSession session = factory.createSession();
session.getTransaction().begin();
RealmManager realmManager = new RealmManager(session);

View file

@ -21,6 +21,16 @@
<async-supported>true</async-supported>
</servlet>
<filter>
<filter-name>Keycloak Session Management</filter-name>
<filter-class>org.keycloak.services.filters.KeycloakSessionServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Keycloak Session Management</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/rest/*</url-pattern>

View file

@ -33,7 +33,6 @@
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<version>1.0.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>

25
pom.xml
View file

@ -9,7 +9,8 @@
<packaging>pom</packaging>
<properties>
<resteasy.version>3.0.2.Final</resteasy.version>
<resteasy.version>3.0.4.Final</resteasy.version>
<undertow.version>1.0.0.Beta12</undertow.version>
<picketlink.version>2.5.0.Beta6</picketlink.version>
</properties>
@ -108,7 +109,21 @@
<groupId>org.jboss.resteasy</groupId>
<artifactId>tjws</artifactId>
<version>${resteasy.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-undertow</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<version>${undertow.version}</version>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>${undertow.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
@ -131,9 +146,9 @@
<version>1.9.12</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>

View file

@ -79,11 +79,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>tjws</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
@ -105,13 +100,18 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-undertow</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>tjws</artifactId>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
@ -124,6 +124,11 @@
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>

View file

@ -7,8 +7,6 @@ import org.keycloak.services.models.KeycloakSessionFactory;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import java.io.IOException;

View file

@ -0,0 +1,56 @@
package org.keycloak.services.filters;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.KeycloakTransaction;
import javax.servlet.*;
import java.io.IOException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakSessionServletFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
KeycloakSessionFactory factory = (KeycloakSessionFactory)servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
if (factory == null) throw new ServletException("Factory was null");
KeycloakSession session = factory.createSession();
ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
KeycloakTransaction tx = session.getTransaction();
ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
tx.begin();
try {
filterChain.doFilter(servletRequest, servletResponse);
if (tx.isActive()) {
if (tx.getRollbackOnly()) tx.rollback();
else tx.commit();
}
} catch (IOException ex) {
if (tx.isActive()) tx.rollback();
throw ex;
} catch (ServletException ex) {
if (tx.isActive()) tx.rollback();
throw ex;
}
catch (RuntimeException ex) {
if (tx.isActive()) tx.rollback();
throw ex;
} finally {
session.close();
ResteasyProviderFactory.clearContextData();
}
}
@Override
public void destroy() {
}
}

View file

@ -16,11 +16,7 @@ import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.SaasService;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.*;
import java.net.URI;
import java.util.HashSet;
import java.util.List;

View file

@ -7,7 +7,10 @@ import org.keycloak.services.models.*;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**

View file

@ -5,8 +5,8 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.TokenIdGenerator;
import org.keycloak.representations.idm.admin.LogoutAction;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.ApplicationModel;
import org.keycloak.services.models.RealmModel;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;

View file

@ -1,12 +1,7 @@
package org.keycloak.services.managers;
import org.keycloak.representations.idm.*;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.ApplicationModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>

View file

@ -5,8 +5,8 @@ import org.jboss.resteasy.jose.jws.JWSBuilder;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.keycloak.representations.SkeletonKeyScope;
import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.ApplicationModel;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel;

View file

@ -1,13 +1,7 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.*;
import java.util.Collection;
/**

View file

@ -1,13 +1,6 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.*;
import java.util.Collection;
/**

View file

@ -4,7 +4,6 @@ import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>

View file

@ -5,29 +5,16 @@ import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.security.PemUtils;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.ApplicationModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.keycloak.services.models.*;
import org.keycloak.services.models.picketlink.mappings.ApplicationData;
import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.keycloak.services.models.picketlink.relationships.*;
import org.keycloak.services.models.picketlink.relationships.RequiredApplicationCredentialRelationship;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.RelationshipManager;
import org.picketlink.idm.credential.Credentials;
import org.picketlink.idm.credential.Password;
import org.picketlink.idm.credential.TOTPCredential;
import org.picketlink.idm.credential.TOTPCredentials;
import org.picketlink.idm.credential.UsernamePasswordCredentials;
import org.picketlink.idm.credential.X509CertificateCredentials;
import org.picketlink.idm.credential.*;
import org.picketlink.idm.model.AttributedType;
import org.picketlink.idm.model.IdentityType;
import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.sample.Grant;
import org.picketlink.idm.model.sample.Role;
import org.picketlink.idm.model.sample.SampleModel;
@ -40,13 +27,7 @@ import java.io.StringWriter;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* Meant to be a per-request object

View file

@ -3,7 +3,6 @@ package org.keycloak.services.models.picketlink;
import org.keycloak.services.models.UserModel;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.sample.User;
import java.util.HashMap;

View file

@ -1,6 +1,5 @@
package org.keycloak.services.models.picketlink.mappings;
import org.picketlink.idm.jpa.annotations.AttributeValue;
import org.picketlink.idm.model.AbstractPartition;
import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.sample.User;

View file

@ -1,6 +1,5 @@
package org.keycloak.services.models.picketlink.mappings;
import org.picketlink.idm.jpa.annotations.AttributeValue;
import org.picketlink.idm.model.AbstractPartition;
import org.picketlink.idm.model.annotation.AttributeProperty;

View file

@ -1,10 +1,8 @@
package org.keycloak.services.models.picketlink.relationships;
import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.picketlink.idm.model.AbstractAttributedType;
import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.sample.User;
import org.picketlink.idm.query.AttributeParameter;
import org.picketlink.idm.query.RelationshipQueryParameter;

View file

@ -21,18 +21,6 @@
*/
package org.keycloak.services.resources;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.Status;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
@ -45,6 +33,13 @@ import org.keycloak.services.resources.flows.FormFlows;
import org.keycloak.services.validation.Validation;
import org.picketlink.idm.credential.util.TimeBasedOTP;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.Status;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@ -70,8 +65,6 @@ public class AccountService {
@Path("access")
@GET
public Response accessPage() {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
return Flows.forms(realm, request).setUser(user).forwardToAccess();
@ -79,15 +72,11 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
@Path("")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
user.setFirstName(formData.getFirst("firstName"));
@ -99,15 +88,11 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
@Path("totp")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
FormFlows forms = Flows.forms(realm, request);
@ -143,15 +128,11 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
@Path("password")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
FormFlows forms = Flows.forms(realm, request).setUser(user);
@ -187,14 +168,10 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
@Path("")
@GET
public Response accountPage() {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
return Flows.forms(realm, request).setUser(user).forwardToAccount();
@ -202,14 +179,10 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
@Path("social")
@GET
public Response socialPage() {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
return Flows.forms(realm, request).setUser(user).forwardToSocial();
@ -217,14 +190,10 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
@Path("totp")
@GET
public Response totpPage() {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
return Flows.forms(realm, request).setUser(user).forwardToTotp();
@ -232,14 +201,10 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
@Path("password")
@GET
public Response passwordPage() {
return new Transaction<Response>() {
protected Response callImpl() {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
return Flows.forms(realm, request).setUser(user).forwardToPassword();
@ -247,7 +212,4 @@ public class AccountService {
return Response.status(Status.FORBIDDEN).build();
}
}
}.call();
}
}

View file

@ -1,7 +1,6 @@
package org.keycloak.services.resources;
import org.keycloak.SkeletonKeyContextResolver;
import org.keycloak.services.filters.KeycloakSessionCleanupFilter;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSession;
@ -13,25 +12,15 @@ import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.config.IdentityConfigurationBuilder;
import org.picketlink.idm.internal.DefaultPartitionManager;
import org.picketlink.idm.jpa.internal.JPAContextInitializer;
import org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.*;
import javax.annotation.PreDestroy;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.ServletContext;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import java.util.HashSet;
import java.util.Set;
@ -45,10 +34,11 @@ public class KeycloakApplication extends Application {
protected KeycloakSessionFactory factory;
public KeycloakApplication() {
public KeycloakApplication(@Context ServletContext context) {
KeycloakSessionFactory f = createSessionFactory();
this.factory = f;
classes.add(KeycloakSessionCleanupFilter.class);
context.setAttribute(KeycloakSessionFactory.class.getName(), factory);
//classes.add(KeycloakSessionCleanupFilter.class);
TokenManager tokenManager = new TokenManager();
@ -56,6 +46,7 @@ public class KeycloakApplication extends Application {
singletons.add(new SocialResource(tokenManager, new SocialRequestManager()));
classes.add(SkeletonKeyContextResolver.class);
classes.add(SaasService.class);
}
protected KeycloakSessionFactory createSessionFactory() {

View file

@ -3,7 +3,6 @@ package org.keycloak.services.resources;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.PublishedRealmRepresentation;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import javax.ws.rs.GET;
@ -41,20 +40,14 @@ public class PublicRealmResource {
@NoCache
@Produces("application/json")
public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) {
return new Transaction<PublishedRealmRepresentation>() {
protected PublishedRealmRepresentation callImpl() {
return realmRep(realm, uriInfo);
}
}.call();
}
@GET
@NoCache
@Path("html")
@Produces("text/html")
public String getRealmHtml(@PathParam("realm") String id) {
return new Transaction<String>() {
protected String callImpl() {
StringBuffer html = new StringBuffer();
String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString();
@ -72,8 +65,6 @@ public class PublicRealmResource {
return html.toString();
}
}.call();
}
public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {

View file

@ -1,26 +1,17 @@
package org.keycloak.services.resources;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.social.SocialRequestManager;
import javax.ws.rs.Consumes;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@ -39,7 +30,10 @@ public class RealmsResource {
protected HttpHeaders headers;
@Context
ResourceContext resourceContext;
protected ResourceContext resourceContext;
@Context
protected KeycloakSession session;
protected TokenManager tokenManager;
@ -53,9 +47,6 @@ public class RealmsResource {
@Path("{realm}/tokens")
public TokenService getTokenService(final @PathParam("realm") String id) {
return new Transaction<TokenService>(false) {
@Override
protected TokenService callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealm(id);
if (realm == null) {
@ -66,15 +57,9 @@ public class RealmsResource {
resourceContext.initResource(tokenService);
return tokenService;
}
}.call();
}
@Path("{realm}/account")
public AccountService getAccountService(final @PathParam("realm") String id) {
return new Transaction<AccountService>(false) {
@Override
protected AccountService callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealm(id);
if (realm == null) {
@ -85,14 +70,9 @@ public class RealmsResource {
resourceContext.initResource(accountService);
return accountService;
}
}.call();
}
@Path("{realm}")
public PublicRealmResource getRealmResource(final @PathParam("realm") String id) {
return new Transaction<PublicRealmResource>(false) {
@Override
protected PublicRealmResource callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealm(id);
if (realm == null) {
@ -103,8 +83,6 @@ public class RealmsResource {
resourceContext.initResource(realmResource);
return realmResource;
}
}.call();
}
}

View file

@ -10,18 +10,14 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.*;
import org.keycloak.services.resources.admin.RealmsAdminResource;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.validation.Validation;
import javax.ws.rs.*;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.*;
import java.net.URI;
import java.util.LinkedList;
import java.util.List;
@ -44,7 +40,13 @@ public class SaasService {
protected HttpRequest request;
@Context
HttpResponse response;
protected HttpResponse response;
@Context
protected KeycloakSession session;
@Context
protected ResourceContext resourceContext;
protected String adminPath = "/saas/admin/index.html";
protected AuthenticationManager authManager = new AuthenticationManager();
@ -82,10 +84,7 @@ public class SaasService {
@GET
@NoCache
public Response keepalive(final @Context HttpHeaders headers) {
logger.info("keepalive");
return new Transaction<Response>() {
@Override
public Response callImpl() {
logger.debug("keepalive");
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.defaultRealm();
if (realm == null)
@ -97,17 +96,12 @@ public class SaasService {
NewCookie refreshCookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
return Response.noContent().cookie(refreshCookie).build();
}
}.call();
}
@Path("whoami")
@GET
@Produces("application/json")
@NoCache
public Response whoAmI(final @Context HttpHeaders headers) {
return new Transaction<Response>() {
@Override
public Response callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.defaultRealm();
if (realm == null)
@ -118,18 +112,13 @@ public class SaasService {
}
return Response.ok(new WhoAmI(user.getLoginName(), user.getFirstName() + " " + user.getLastName())).build();
}
}.call();
}
@Path("isLoggedIn.js")
@GET
@Produces("application/javascript")
@NoCache
public String isLoggedIn(final @Context HttpHeaders headers) {
return new Transaction<String>() {
@Override
public String callImpl() {
logger.info("WHOAMI Javascript start.");
logger.debug("WHOAMI Javascript start.");
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.defaultRealm();
if (realm == null) {
@ -140,11 +129,9 @@ public class SaasService {
if (user == null) {
return "var keycloakCookieLoggedIn = false;";
}
logger.info("WHOAMI: " + user.getLoginName());
logger.debug("WHOAMI: " + user.getLoginName());
return "var keycloakCookieLoggedIn = true;";
}
}.call();
}
public static UriBuilder contextRoot(UriInfo uriInfo) {
return UriBuilder.fromUri(uriInfo.getBaseUri()).replacePath("/auth-server");
@ -156,9 +143,6 @@ public class SaasService {
@Path("admin/realms")
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
return new Transaction<RealmsAdminResource>(false) {
@Override
protected RealmsAdminResource callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel saasRealm = realmManager.defaultRealm();
if (saasRealm == null)
@ -172,80 +156,57 @@ public class SaasService {
logger.warn("not a Realm creator");
throw new NotAuthorizedException("Bearer");
}
return new RealmsAdminResource(admin);
}
}.call();
RealmsAdminResource adminResource = new RealmsAdminResource(admin);
resourceContext.initResource(adminResource);
return adminResource;
}
@Path("login")
@GET
@NoCache
public void loginPage() {
new Transaction() {
@Override
protected void runImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.defaultRealm();
authManager.expireSaasIdentityCookie(uriInfo);
Flows.forms(realm, request).forwardToLogin();
}
}.run();
}
@Path("registrations")
@GET
@NoCache
public void registerPage() {
new Transaction() {
@Override
protected void runImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.defaultRealm();
authManager.expireSaasIdentityCookie(uriInfo);
Flows.forms(realm, request).forwardToRegistration();
}
}.run();
}
@Path("logout")
@GET
@NoCache
public void logout() {
new Transaction() {
@Override
protected void runImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.defaultRealm();
authManager.expireSaasIdentityCookie(uriInfo);
Flows.forms(realm, request).forwardToLogin();
}
}.run();
}
@Path("logout-cookie")
@GET
@NoCache
public void logoutCookie() {
logger.info("*** logoutCookie");
new Transaction() {
@Override
protected void runImpl() {
logger.debug("*** logoutCookie");
authManager.expireSaasIdentityCookie(uriInfo);
}
}.run();
}
@Path("login")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processLogin(final MultivaluedMap<String, String> formData) {
logger.info("processLogin start");
return new Transaction<Response>() {
@Override
protected Response callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.defaultRealm();
if (realm == null)
@ -280,16 +241,11 @@ public class SaasService {
NewCookie cookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
return Response.status(302).cookie(cookie).location(contextRoot(uriInfo).path(adminPath).build()).build();
}
}.call();
}
@Path("registrations")
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response register(final UserRepresentation newUser) {
return new Transaction<Response>() {
@Override
protected Response callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel defaultRealm = realmManager.defaultRealm();
UserModel user = registerMe(defaultRealm, newUser);
@ -299,16 +255,11 @@ public class SaasService {
URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
return Response.created(uri).build();
}
}.call();
}
@Path("registrations")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processRegister(final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
@Override
protected Response callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel defaultRealm = realmManager.defaultRealm();
@ -368,8 +319,6 @@ public class SaasService {
NewCookie cookie = authManager.createSaasIdentityCookie(defaultRealm, user, uriInfo);
return Response.status(302).location(contextRoot(uriInfo).path(adminPath).build()).cookie(cookie).build();
}
}.call();
}
protected UserModel registerMe(RealmModel defaultRealm, UserRepresentation newUser) {
if (!defaultRealm.isEnabled()) {

View file

@ -21,12 +21,19 @@
*/
package org.keycloak.services.resources;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.OAuthFlows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.social.*;
import javax.imageio.spi.ServiceRegistry;
import javax.ws.rs.GET;
@ -38,27 +45,12 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.OAuthFlows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.social.AuthCallback;
import org.keycloak.social.AuthRequest;
import org.keycloak.social.RequestDetails;
import org.keycloak.social.RequestDetailsBuilder;
import org.keycloak.social.SocialProvider;
import org.keycloak.social.SocialProviderConfig;
import org.keycloak.social.SocialProviderException;
import org.keycloak.social.SocialRequestManager;
import org.keycloak.social.SocialUser;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -77,11 +69,14 @@ public class SocialResource {
@Context
private HttpRequest request;
private SocialRequestManager socialRequestManager;
@Context
protected KeycloakSession session;
private TokenManager tokenManager;
protected SocialRequestManager socialRequestManager;
private AuthenticationManager authManager = new AuthenticationManager();
protected TokenManager tokenManager;
protected AuthenticationManager authManager = new AuthenticationManager();
public SocialResource(TokenManager tokenManager, SocialRequestManager socialRequestManager) {
this.tokenManager = tokenManager;
@ -91,8 +86,6 @@ public class SocialResource {
@GET
@Path("callback")
public Response callback() throws URISyntaxException {
return new Transaction<Response>() {
protected Response callImpl() {
Map<String, String[]> queryParams = getQueryParams();
RequestDetails requestData = getRequestDetails(queryParams);
@ -166,8 +159,6 @@ public class SocialResource {
return oauth.processAccessCode(scope, state, redirectUri, client, user);
}
}.call();
}
@GET
@Path("{realm}/login")

View file

@ -11,48 +11,18 @@ import org.jboss.resteasy.spi.HttpResponse;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.AccessCodeEntry;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.managers.*;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.*;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.OAuthFlows;
import org.keycloak.services.validation.Validation;
import org.picketlink.idm.credential.util.TimeBasedOTP;
import javax.ws.rs.Consumes;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.GET;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.Providers;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -68,16 +38,28 @@ public class TokenService {
@Context
protected Providers providers;
@Context
protected SecurityContext securityContext;
@Context
protected UriInfo uriInfo;
@Context
protected HttpHeaders headers;
@Context
HttpRequest request;
protected HttpRequest request;
@Context
HttpResponse response;
protected HttpResponse response;
@Context
protected KeycloakSession session;
@Context
protected KeycloakTransaction transaction;
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
@ -123,8 +105,6 @@ public class TokenService {
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response grantIdentityToken(final MultivaluedMap<String, String> form) {
return new Transaction<Response>() {
protected Response callImpl() {
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
if (username == null) {
throw new NotAuthorizedException("No user");
@ -148,16 +128,12 @@ public class TokenService {
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
}.call();
}
@Path("grants/access")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response grantAccessToken(final MultivaluedMap<String, String> form) {
return new Transaction<Response>() {
protected Response callImpl() {
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
if (username == null) {
throw new NotAuthorizedException("No user");
@ -180,9 +156,6 @@ public class TokenService {
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
}.call();
}
@Path("auth/request/login")
@POST
@ -190,8 +163,6 @@ public class TokenService {
public Response processLogin(@QueryParam("client_id") final String clientId, @QueryParam("scope") final String scopeParam,
@QueryParam("state") final String state, @QueryParam("redirect_uri") final String redirect,
final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
protected Response callImpl() {
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
if (!realm.isEnabled()) {
@ -237,8 +208,6 @@ public class TokenService {
return oauth.processAccessCode(scopeParam, state, redirect, client, user);
}
}.call();
}
@Path("registrations")
@POST
@ -246,9 +215,6 @@ public class TokenService {
public Response processRegister(@QueryParam("client_id") final String clientId,
@QueryParam("scope") final String scopeParam, @QueryParam("state") final String state,
@QueryParam("redirect_uri") final String redirect, final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
@Override
protected Response callImpl() {
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
if (!realm.isEnabled()) {
@ -326,15 +292,11 @@ public class TokenService {
return processLogin(clientId, scopeParam, state, redirect, formData);
}
}.call();
}
@Path("access/codes")
@POST
@Produces("application/json")
public Response accessCodeToToken(final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
protected Response callImpl() {
logger.info("accessRequest <---");
if (!realm.isEnabled()) {
throw new NotAuthorizedException("Realm not enabled");
@ -429,9 +391,6 @@ public class TokenService {
AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken());
return Response.ok(res).build();
}
}.call();
}
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
byte[] tokenBytes = null;
@ -461,8 +420,6 @@ public class TokenService {
public Response loginPage(final @QueryParam("response_type") String responseType,
final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) {
return new Transaction<Response>() {
protected Response callImpl() {
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
if (!realm.isEnabled()) {
@ -501,16 +458,12 @@ public class TokenService {
return Flows.forms(realm, request).forwardToLogin();
}
}.call();
}
@Path("registrations")
@GET
public Response registerPage(final @QueryParam("response_type") String responseType,
final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) {
return new Transaction<Response>() {
protected Response callImpl() {
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
if (!realm.isEnabled()) {
@ -533,15 +486,11 @@ public class TokenService {
return Flows.forms(realm, request).forwardToRegistration();
}
}.call();
}
@Path("logout")
@GET
@NoCache
public Response logout(final @QueryParam("redirect_uri") String redirectUri) {
return new Transaction<Response>() {
protected Response callImpl() {
// todo do we care if anybody can trigger this?
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
@ -553,15 +502,11 @@ public class TokenService {
// todo manage legal redirects
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
}
}.call();
}
@Path("oauth/grant")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processOAuth(final MultivaluedMap<String, String> formData) {
return new Transaction<Response>() {
protected Response callImpl() {
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
String code = formData.getFirst("code");
@ -590,8 +535,6 @@ public class TokenService {
return oauth.redirectAccessCode(accessCodeEntry, state, redirect);
}
}.call();
}
protected Response redirectAccessDenied(String redirect, String state) {
UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam("error", "access_denied");

View file

@ -2,17 +2,15 @@ package org.keycloak.services.resources;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.KeycloakTransaction;
import javax.ws.rs.core.Application;
/**
* Meant to be used as an inner class wrapper (I forget the pattern name, its been awhile).
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Deprecated
public class Transaction<T> {
protected KeycloakSession session;
protected KeycloakTransaction transaction;
@ -36,6 +34,8 @@ public class Transaction<T> {
*/
public Transaction(boolean close) {
this.session = ResteasyProviderFactory.getContextData(KeycloakSession.class);
this.transaction = session.getTransaction();
/*
if (session == null) {
KeycloakApplication app = (KeycloakApplication)ResteasyProviderFactory.getContextData(Application.class);
session = app.getFactory().createSession();
@ -44,18 +44,8 @@ public class Transaction<T> {
}
transaction = session.getTransaction();
closeSession = close;
}
/**
* Creates and manages its own session.
*
* @param factory
*/
public Transaction(KeycloakSessionFactory factory) {
this.closeSession = true;
this.session = factory.createSession();
this.transaction = session.getTransaction();
}
protected void runImpl() {
@ -67,20 +57,20 @@ public class Transaction<T> {
*
*/
public void run() {
boolean wasActive = transaction.isActive();
if (!wasActive) transaction.begin();
try {
// boolean wasActive = transaction.isActive();
// if (!wasActive) transaction.begin();
// try {
runImpl();
if (!wasActive && transaction.isActive()) transaction.commit();
} catch (RuntimeException e) {
if (!wasActive && transaction.isActive()) transaction.rollback();
if (created) closeSession = true;
throw e;
} finally {
if (!wasActive && closeSession) {
session.close();
}
}
// if (!wasActive && transaction.isActive()) transaction.commit();
// } catch (RuntimeException e) {
// if (!wasActive && transaction.isActive()) transaction.rollback();
// if (created) closeSession = true;
// throw e;
// } finally {
// if (!wasActive && closeSession) {
// session.close();
// }
// }
}
protected T callImpl() {
@ -92,18 +82,18 @@ public class Transaction<T> {
*
*/
public T call() {
boolean wasActive = transaction.isActive();
if (!wasActive) transaction.begin();
try {
// boolean wasActive = transaction.isActive();
// if (!wasActive) transaction.begin();
// try {
T rtn = callImpl();
if (!wasActive && transaction.isActive()) transaction.commit();
// if (!wasActive && transaction.isActive()) transaction.commit();
return rtn;
} catch (RuntimeException e) {
if (!wasActive && transaction.isActive()) transaction.rollback();
if (created) closeSession = true; // close if there was a failure
throw e;
} finally {
if (!wasActive && closeSession) session.close();
}
// } catch (RuntimeException e) {
// if (!wasActive && transaction.isActive()) transaction.rollback();
// if (created) closeSession = true; // close if there was a failure
// throw e;
// } finally {
// if (!wasActive && closeSession) session.close();
// }
}
}

View file

@ -5,16 +5,13 @@ import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.ApplicationModel;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.resources.Transaction;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
/**
@ -27,6 +24,9 @@ public class ApplicationResource {
protected RealmModel realm;
protected ApplicationModel applicationModel;
@Context
protected KeycloakSession session;
public ApplicationResource(UserModel admin, RealmModel realm, ApplicationModel applicationModel) {
this.admin = admin;
this.realm = realm;
@ -36,26 +36,16 @@ public class ApplicationResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void update(final ApplicationRepresentation rep) {
new Transaction<Void>() {
@Override
protected void runImpl() {
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
resourceManager.updateResource(rep, applicationModel);
}
}.run();
}
@GET
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public ApplicationRepresentation getResource(final @PathParam("id") String id) {
return new Transaction<ApplicationRepresentation>() {
@Override
protected ApplicationRepresentation callImpl() {
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
return resourceManager.toRepresentation(applicationModel);
}
}.call();
}
}

View file

@ -5,18 +5,13 @@ import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.ApplicationModel;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.resources.Transaction;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.*;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ -33,6 +28,12 @@ public class ApplicationsResource {
protected UserModel admin;
protected RealmModel realm;
@Context
protected ResourceContext resourceContext;
@Context
protected KeycloakSession session;
public ApplicationsResource(UserModel admin, RealmModel realm) {
this.admin = admin;
this.realm = realm;
@ -42,9 +43,6 @@ public class ApplicationsResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<ApplicationRepresentation> getResources() {
return new Transaction<List<ApplicationRepresentation>>() {
@Override
protected List<ApplicationRepresentation> callImpl() {
List<ApplicationRepresentation> rep = new ArrayList<ApplicationRepresentation>();
List<ApplicationModel> applicationModels = realm.getApplications();
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
@ -53,35 +51,24 @@ public class ApplicationsResource {
}
return rep;
}
}.call();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createResource(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
return new Transaction<Response>() {
@Override
protected Response callImpl() {
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
ApplicationModel applicationModel = resourceManager.createResource(realm, rep);
return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getId()).build()).build();
}
}.call();
}
@Path("{id}")
public ApplicationResource getResource(final @PathParam("id") String id) {
return new Transaction<ApplicationResource>(false) {
@Override
protected ApplicationResource callImpl() {
ApplicationModel applicationModel = realm.getApplicationById(id);
if (applicationModel == null) {
throw new NotFoundException();
}
return new ApplicationResource(admin, realm, applicationModel);
}
}.call();
ApplicationResource applicationResource = new ApplicationResource(admin, realm, applicationModel);
resourceContext.initResource(applicationResource);
return applicationResource;
}
}

View file

@ -6,20 +6,13 @@ import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.resources.Transaction;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.*;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@ -35,6 +28,12 @@ public class RealmAdminResource {
protected UserModel admin;
protected RealmModel realm;
@Context
protected ResourceContext resourceContext;
@Context
protected KeycloakSession session;
public RealmAdminResource(UserModel admin, RealmModel realm) {
this.admin = admin;
this.realm = realm;
@ -42,20 +41,17 @@ public class RealmAdminResource {
@Path("applications")
public ApplicationsResource getResources() {
return new ApplicationsResource(admin, realm);
ApplicationsResource applicationsResource = new ApplicationsResource(admin, realm);
resourceContext.initResource(applicationsResource);
return applicationsResource;
}
@GET
@NoCache
@Produces("application/json")
public RealmRepresentation getRealm() {
return new Transaction<RealmRepresentation>() {
@Override
protected RealmRepresentation callImpl() {
return new RealmManager(session).toRepresentation(realm);
}
}.call();
}
@Path("roles")
@ -63,9 +59,6 @@ public class RealmAdminResource {
@NoCache
@Produces("application/json")
public List<RoleRepresentation> getRoles() {
return new Transaction<List<RoleRepresentation>>() {
@Override
protected List<RoleRepresentation> callImpl() {
List<RoleModel> roleModels = realm.getRoles();
List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roleModels) {
@ -74,30 +67,19 @@ public class RealmAdminResource {
}
return roles;
}
}.call();
}
@PUT
@Consumes("application/json")
public void updateRealm(final RealmRepresentation rep) {
new Transaction() {
@Override
protected void runImpl() {
logger.info("updating realm: " + rep.getRealm());
new RealmManager(session).updateRealm(rep, realm);
}
}.run();
}
@Path("roles/{id}")
@GET
@NoCache
@Produces("application/json")
public RoleRepresentation getRole(final @PathParam("id") String id) {
return new Transaction<RoleRepresentation>() {
@Override
protected RoleRepresentation callImpl() {
RoleModel roleModel = realm.getRoleById(id);
if (roleModel == null) {
throw new NotFoundException();
@ -106,17 +88,12 @@ public class RealmAdminResource {
rep.setId(roleModel.getId());
return rep;
}
}.call();
}
@Path("roles/{id}")
@PUT
@Consumes("application/json")
public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) {
new Transaction() {
@Override
protected void runImpl() {
RoleModel role = realm.getRoleById(id);
if (role == null) {
throw new NotFoundException();
@ -124,17 +101,11 @@ public class RealmAdminResource {
role.setName(rep.getName());
role.setDescription(rep.getDescription());
}
}.run();
}
@Path("roles")
@POST
@Consumes("application/json")
public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
return new Transaction<Response>() {
@Override
protected Response callImpl() {
if (realm.getRole(rep.getName()) != null) {
throw new InternalServerErrorException(); // todo appropriate status here.
}
@ -145,9 +116,6 @@ public class RealmAdminResource {
role.setDescription(rep.getDescription());
return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build();
}
}.call();
}
@Path("users")

View file

@ -4,34 +4,17 @@ import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.resources.PublicRealmResource;
import org.keycloak.services.resources.SaasService;
import org.keycloak.services.resources.Transaction;
import javax.ws.rs.Consumes;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.GET;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
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 javax.ws.rs.*;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -50,13 +33,16 @@ public class RealmsAdminResource {
noCache.setNoCache(true);
}
@Context
protected ResourceContext resourceContext;
@Context
protected KeycloakSession session;
@GET
@NoCache
@Produces("application/json")
public List<RealmRepresentation> getRealms() {
return new Transaction<List<RealmRepresentation>>() {
@Override
protected List<RealmRepresentation> callImpl() {
logger.info(("getRealms()"));
RealmManager realmManager = new RealmManager(session);
List<RealmModel> realms = session.getRealms(admin);
@ -66,8 +52,6 @@ public class RealmsAdminResource {
}
return reps;
}
}.call();
}
public static UriBuilder realmUrl(UriInfo uriInfo) {
return realmsUrl(uriInfo).path("{id}");
@ -81,24 +65,16 @@ public class RealmsAdminResource {
@Consumes("application/json")
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
logger.info("importRealm: " + rep.getRealm());
return new Transaction<Response>() {
@Override
protected Response callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.importRealm(rep, admin);
URI location = realmUrl(uriInfo).build(realm.getId());
logger.info("imported realm success, sending back: " + location.toString());
return Response.created(location).build();
}
}.call();
}
@Path("{id}")
public RealmAdminResource getRealmAdmin(@Context final HttpHeaders headers,
@PathParam("id") final String id) {
return new Transaction<RealmAdminResource>(false) {
@Override
protected RealmAdminResource callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealm(id);
if (realm == null) throw new NotFoundException();
@ -106,9 +82,9 @@ public class RealmsAdminResource {
throw new ForbiddenException();
}
return new RealmAdminResource(admin, realm);
}
}.call();
RealmAdminResource adminResource = new RealmAdminResource(admin, realm);
resourceContext.initResource(adminResource);
return adminResource;
}

View file

@ -21,13 +21,13 @@
*/
package org.keycloak.services.resources.flows;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.RealmModel;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/

View file

@ -21,14 +21,14 @@
*/
package org.keycloak.services.resources.flows;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserModel;
import org.picketlink.idm.model.sample.Realm;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/

View file

@ -21,10 +21,6 @@
*/
package org.keycloak.services.resources.flows;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.services.managers.AccessCodeEntry;
@ -36,6 +32,10 @@ import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.resources.TokenService;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -21,12 +21,12 @@
*/
package org.keycloak.services.resources.flows;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.services.JspRequestParameters;
import javax.ws.rs.core.Response;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/

View file

@ -21,15 +21,10 @@
*/
package org.keycloak.services.resources.flows;
import java.net.URI;
import org.keycloak.services.resources.*;
import javax.ws.rs.core.UriBuilder;
import org.keycloak.services.resources.AccountService;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.SaasService;
import org.keycloak.services.resources.SocialResource;
import org.keycloak.services.resources.TokenService;
import java.net.URI;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -1,12 +1,11 @@
package org.keycloak.services.validation;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.messages.Messages;
import javax.ws.rs.core.MultivaluedMap;
import java.util.List;
public class Validation {
public static String validateRegistrationForm(MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes) {

View file

@ -0,0 +1,70 @@
package org.keycloak.test;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.FilterInfo;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
import org.jboss.resteasy.spi.ResteasyDeployment;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.keycloak.SkeletonKeyContextResolver;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.filters.KeycloakSessionServletFilter;
import org.keycloak.services.resources.KeycloakApplication;
import javax.servlet.DispatcherType;
import javax.ws.rs.client.Client;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AbstractKeycloakServerTest {
public static UndertowJaxrsServer server;
public static ResteasyDeployment deployment;
public static Client client;
public static KeycloakApplication application;
@BeforeClass
public static void undertowSetup() throws Exception {
deployment = new ResteasyDeployment();
deployment.setApplicationClass(KeycloakApplication.class.getName());
server = new UndertowJaxrsServer().start();
DeploymentInfo di = server.undertowDeployment(deployment);
di.setClassLoader(AbstractKeycloakServerTest.class.getClassLoader());
di.setContextPath("/");
di.setDeploymentName("Keycloak");
FilterInfo filter = Servlets.filter("SessionFilter", KeycloakSessionServletFilter.class);
di.addFilter(filter);
di.addFilterUrlMapping("SessionFilter", "/*", DispatcherType.REQUEST);
server.deploy(di);
application = (KeycloakApplication) deployment.getApplication();
client = new ResteasyClientBuilder().connectionPoolSize(10).build();
client.register(SkeletonKeyContextResolver.class);
}
@AfterClass
public static void undertowShutdown() throws Exception {
server.stop();
}
public static RealmRepresentation loadJson(String path) throws IOException {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
ByteArrayOutputStream os = new ByteArrayOutputStream();
int c;
while ((c = is.read()) != -1) {
os.write(c);
}
byte[] bytes = os.toByteArray();
System.out.println(new String(bytes));
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
}
}

View file

@ -64,7 +64,7 @@ public class ImportTest {
UserModel admin = defaultRealm.addUser("admin");
defaultRealm.grantRole(admin, role);
RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm.json");
RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm.json");
RealmModel realm = manager.createRealm("demo", rep.getRealm());
manager.importRealm(rep, realm);
realm.addRealmAdmin(admin);
@ -112,7 +112,7 @@ public class ImportTest {
UserModel admin = defaultRealm.addUser("admin");
defaultRealm.grantRole(admin, role);
RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm-demo.json");
RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm-demo.json");
RealmModel realm = manager.createRealm("demo", rep.getRealm());
manager.importRealm(rep, realm);
realm.addRealmAdmin(admin);

View file

@ -1,31 +0,0 @@
package org.keycloak.test;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.jboss.resteasy.test.BaseResourceTest;
import org.keycloak.representations.idm.RealmRepresentation;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakTestBase extends BaseResourceTest
{
public static RealmRepresentation loadJson(String path) throws IOException
{
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
ByteArrayOutputStream os = new ByteArrayOutputStream();
int c;
while ( (c = is.read()) != -1)
{
os.write(c);
}
byte[] bytes = os.toByteArray();
System.out.println(new String(bytes));
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
}
}

View file

@ -1,12 +1,8 @@
package org.keycloak.test;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.spi.ResteasyDeployment;
import org.jboss.resteasy.test.EmbeddedContainer;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.keycloak.SkeletonKeyContextResolver;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
@ -15,10 +11,8 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.resources.KeycloakApplication;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
@ -31,30 +25,16 @@ import static org.jboss.resteasy.test.TestPortProvider.generateURL;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmCreationTest {
private static ResteasyDeployment deployment;
private static Client client;
public class RealmCreationTest extends AbstractKeycloakServerTest {
@BeforeClass
public static void before() throws Exception {
deployment = new ResteasyDeployment();
deployment.setApplicationClass(KeycloakApplication.class.getName());
EmbeddedContainer.start(deployment);
KeycloakApplication application = (KeycloakApplication) deployment.getApplication();
KeycloakSession session = application.getFactory().createSession();
session.getTransaction().begin();
RealmManager manager = new RealmManager(session);
new InstallationManager().install(manager);
session.getTransaction().commit();
session.close();
client = new ResteasyClientBuilder().build();
client.register(SkeletonKeyContextResolver.class);
}
public static void after() throws Exception {
client.close();
EmbeddedContainer.stop();
}
@Test
@ -86,7 +66,7 @@ public class RealmCreationTest {
System.out.println(tokenResponse.getToken());
//
RealmRepresentation realm = KeycloakTestBase.loadJson("testrealm.json");
RealmRepresentation realm = loadJson("testrealm.json");
response = target.path("saas/admin/realms").request().header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenResponse.getToken()).post(Entity.json(realm));
Assert.assertEquals(201, response.getStatus());
response.close();