merge conflicts
This commit is contained in:
commit
c14d3d7963
608 changed files with 23984 additions and 3992 deletions
|
@ -240,6 +240,7 @@ public class SAMLEndpoint {
|
|||
.relayState(relayState);
|
||||
if (config.isWantAuthnRequestsSigned()) {
|
||||
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
|
||||
.signatureAlgorithm(provider.getSignatureAlgorithm())
|
||||
.signDocument();
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
|
|||
import org.keycloak.saml.SAML2AuthnRequestBuilder;
|
||||
import org.keycloak.saml.SAML2LogoutRequestBuilder;
|
||||
import org.keycloak.saml.SAML2NameIDPolicyBuilder;
|
||||
import org.keycloak.saml.SignatureAlgorithm;
|
||||
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
|
||||
|
@ -108,6 +109,7 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
KeyPair keypair = new KeyPair(publicKey, privateKey);
|
||||
|
||||
binding.signWith(keypair);
|
||||
binding.signatureAlgorithm(getSignatureAlgorithm());
|
||||
binding.signDocument();
|
||||
}
|
||||
|
||||
|
@ -201,6 +203,7 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
.relayState(userSession.getId());
|
||||
if (getConfig().isWantAuthnRequestsSigned()) {
|
||||
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
|
||||
.signatureAlgorithm(getSignatureAlgorithm())
|
||||
.signDocument();
|
||||
}
|
||||
return binding;
|
||||
|
@ -250,4 +253,14 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
"</EntityDescriptor>\n";
|
||||
return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
|
||||
}
|
||||
|
||||
public SignatureAlgorithm getSignatureAlgorithm() {
|
||||
String alg = getConfig().getSignatureAlgorithm();
|
||||
if (alg != null) {
|
||||
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
|
||||
if (algorithm != null) return algorithm;
|
||||
}
|
||||
return SignatureAlgorithm.RSA_SHA256;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -87,6 +87,14 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
|
|||
getConfig().put("wantAuthnRequestsSigned", String.valueOf(wantAuthnRequestsSigned));
|
||||
}
|
||||
|
||||
public String getSignatureAlgorithm() {
|
||||
return getConfig().get("signatureAlgorithm");
|
||||
}
|
||||
|
||||
public void setSignatureAlgorithm(String signatureAlgorithm) {
|
||||
getConfig().put("signatureAlgorithm", signatureAlgorithm);
|
||||
}
|
||||
|
||||
public String getEncryptionPublicKey() {
|
||||
return getConfig().get("encryptionPublicKey");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
<changeSet author="mposolda@redhat.com" id="1.6.0">
|
||||
|
||||
<addColumn tableName="KEYCLOAK_ROLE">
|
||||
<column name="SCOPE_PARAM_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
|
||||
<createTable tableName="OFFLINE_USER_SESSION">
|
||||
<column name="USER_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USER_SESSION_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="DATA" type="CLOB"/>
|
||||
</createTable>
|
||||
|
||||
<createTable tableName="OFFLINE_CLIENT_SESSION">
|
||||
<column name="USER_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="CLIENT_SESSION_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USER_SESSION_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="CLIENT_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="DATA" type="CLOB"/>
|
||||
</createTable>
|
||||
|
||||
<addPrimaryKey columnNames="USER_SESSION_ID" constraintName="CONSTRAINT_OFFLINE_US_SES_PK" tableName="OFFLINE_USER_SESSION"/>
|
||||
<addPrimaryKey columnNames="CLIENT_SESSION_ID" constraintName="CONSTRAINT_OFFLINE_CL_SES_PK" tableName="OFFLINE_CLIENT_SESSION"/>
|
||||
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="OFFLINE_USER_SESSION" constraintName="FK_OFFLINE_US_SES_USER" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
|
||||
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="OFFLINE_CLIENT_SESSION" constraintName="FK_OFFLINE_CL_SES_USER" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
|
||||
<addForeignKeyConstraint baseColumnNames="USER_SESSION_ID" baseTableName="OFFLINE_CLIENT_SESSION" constraintName="FK_OFFLINE_CL_US_SES" referencedColumnNames="USER_SESSION_ID" referencedTableName="OFFLINE_USER_SESSION"/>
|
||||
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
|
@ -9,4 +9,5 @@
|
|||
<include file="META-INF/jpa-changelog-1.3.0.xml"/>
|
||||
<include file="META-INF/jpa-changelog-1.4.0.xml"/>
|
||||
<include file="META-INF/jpa-changelog-1.5.0.xml"/>
|
||||
<include file="META-INF/jpa-changelog-1.6.0.xml"/>
|
||||
</databaseChangeLog>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||
<artifactId>${hibernate.javax.persistence.artifactId}</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
<class>org.keycloak.models.jpa.entities.AuthenticationExecutionEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.AuthenticatorConfigEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.RequiredActionProviderEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.OfflineUserSessionEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.OfflineClientSessionEntity</class>
|
||||
|
||||
<!-- JpaAuditProviders -->
|
||||
<class>org.keycloak.events.jpa.EventEntity</class>
|
||||
|
|
|
@ -48,6 +48,8 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
|
|||
"org.keycloak.models.entities.AuthenticationFlowEntity",
|
||||
"org.keycloak.models.entities.AuthenticatorConfigEntity",
|
||||
"org.keycloak.models.entities.RequiredActionProviderEntity",
|
||||
"org.keycloak.models.entities.OfflineUserSessionEntity",
|
||||
"org.keycloak.models.entities.OfflineClientSessionEntity",
|
||||
};
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
|
||||
|
|
|
@ -29,27 +29,22 @@
|
|||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
|
|
@ -38,6 +38,9 @@ public interface OAuth2Constants {
|
|||
// https://tools.ietf.org/html/draft-jones-oauth-jwt-bearer-03#section-2.2
|
||||
String CLIENT_ASSERTION_TYPE_JWT = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
||||
|
||||
// http://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
|
||||
String OFFLINE_ACCESS = "offline_access";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.keycloak.representations;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.keycloak.util.RefreshTokenUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -11,9 +12,8 @@ import java.util.Map;
|
|||
*/
|
||||
public class RefreshToken extends AccessToken {
|
||||
|
||||
|
||||
private RefreshToken() {
|
||||
type("REFRESH");
|
||||
type(RefreshTokenUtil.TOKEN_TYPE_REFRESH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Comparator;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AuthenticationExecutionRepresentation implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String authenticatorConfig;
|
||||
private String authenticator;
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.List;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AuthenticationFlowRepresentation implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String alias;
|
||||
private String description;
|
||||
|
|
|
@ -9,7 +9,6 @@ import java.util.Map;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AuthenticatorConfigRepresentation implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String alias;
|
||||
private Map<String, String> config = new HashMap<String, String>();
|
||||
|
|
|
@ -12,6 +12,7 @@ public class RoleRepresentation {
|
|||
protected String id;
|
||||
protected String name;
|
||||
protected String description;
|
||||
protected Boolean scopeParamRequired;
|
||||
protected boolean composite;
|
||||
protected Composites composites;
|
||||
|
||||
|
@ -46,9 +47,10 @@ public class RoleRepresentation {
|
|||
public RoleRepresentation() {
|
||||
}
|
||||
|
||||
public RoleRepresentation(String name, String description) {
|
||||
public RoleRepresentation(String name, String description, boolean scopeParamRequired) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.scopeParamRequired = scopeParamRequired;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -75,6 +77,14 @@ public class RoleRepresentation {
|
|||
this.description = description;
|
||||
}
|
||||
|
||||
public Boolean isScopeParamRequired() {
|
||||
return scopeParamRequired;
|
||||
}
|
||||
|
||||
public void setScopeParamRequired(Boolean scopeParamRequired) {
|
||||
this.scopeParamRequired = scopeParamRequired;
|
||||
}
|
||||
|
||||
public Composites getComposites() {
|
||||
return composites;
|
||||
}
|
||||
|
|
62
core/src/main/java/org/keycloak/util/RefreshTokenUtil.java
Normal file
62
core/src/main/java/org/keycloak/util/RefreshTokenUtil.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package org.keycloak.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class RefreshTokenUtil {
|
||||
|
||||
public static final String TOKEN_TYPE_REFRESH = "REFRESH";
|
||||
|
||||
public static final String TOKEN_TYPE_OFFLINE = "OFFLINE";
|
||||
|
||||
public static boolean isOfflineTokenRequested(String scopeParam) {
|
||||
if (scopeParam == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] scopes = scopeParam.split(" ");
|
||||
for (String scope : scopes) {
|
||||
if (OAuth2Constants.OFFLINE_ACCESS.equals(scope)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return refresh token or offline otkne
|
||||
*
|
||||
* @param decodedToken
|
||||
* @return
|
||||
*/
|
||||
public static RefreshToken getRefreshToken(byte[] decodedToken) throws IOException {
|
||||
return JsonSerialization.readValue(decodedToken, RefreshToken.class);
|
||||
}
|
||||
|
||||
private static RefreshToken getRefreshToken(String refreshToken) throws IOException {
|
||||
byte[] decodedToken = Base64Url.decode(refreshToken);
|
||||
return getRefreshToken(decodedToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if given refreshToken represents offline token
|
||||
*
|
||||
* @param refreshToken
|
||||
* @return
|
||||
*/
|
||||
public static boolean isOfflineToken(String refreshToken) {
|
||||
try {
|
||||
RefreshToken token = getRefreshToken(refreshToken);
|
||||
return token.getType().equals(TOKEN_TYPE_OFFLINE);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -14,10 +14,38 @@
|
|||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-dependencies-server-all</artifactId>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>keycloak-docs-${project.version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<minmemory>128m</minmemory>
|
||||
<maxmemory>1024m</maxmemory>
|
||||
<dependencySourceIncludes>
|
||||
<dependencySourceInclude>org.keycloak:*</dependencySourceInclude>
|
||||
</dependencySourceIncludes>
|
||||
<includeDependencySources>true</includeDependencySources>
|
||||
<includeTransitiveDependencySources>true</includeTransitiveDependencySources>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>aggregate-javadoc</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>javadoc</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
|
|
|
@ -898,7 +898,7 @@ public class SecretQuestionRequiredActionFactory implements RequiredActionFactor
|
|||
}
|
||||
]]></programlisting>
|
||||
|
||||
where the <literal>mysecret</literal> needs to be replaced with the real value of client secret. You can obtain it from client admin console.
|
||||
where the <literal>mysecret</literal> needs to be replaced with the real value of client secret. You can obtain it from admin console from client configuration.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -906,7 +906,7 @@ public class SecretQuestionRequiredActionFactory implements RequiredActionFactor
|
|||
<term>Authentication with signed JWT</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This is based on the <ulink url="https://tools.ietf.org/html/draft-jones-oauth-jwt-bearer-03">JWT Bearer Token Profiles for OAuth 2.0</ulink> specification.
|
||||
This is based on the <ulink url="https://tools.ietf.org/html/rfc7523">JWT Bearer Token Profiles for OAuth 2.0</ulink> specification.
|
||||
The client/adapter generates the <ulink url="https://tools.ietf.org/html/rfc7519">JWT</ulink> and signs it with his private key.
|
||||
The Keycloak then verifies the signed JWT with the client's public key and authenticates client based on it.
|
||||
</para>
|
||||
|
|
|
@ -20,6 +20,7 @@ public interface Details {
|
|||
String REMEMBER_ME = "remember_me";
|
||||
String TOKEN_ID = "token_id";
|
||||
String REFRESH_TOKEN_ID = "refresh_token_id";
|
||||
String REFRESH_TOKEN_TYPE = "refresh_token_type";
|
||||
String VALIDATE_ACCESS_TOKEN = "validate_access_token";
|
||||
String UPDATED_REFRESH_TOKEN_ID = "updated_refresh_token_id";
|
||||
String NODE_HOST = "node_host";
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||
<artifactId>${hibernate.javax.persistence.artifactId}</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -4,7 +4,6 @@ import javax.xml.ws.WebFault;
|
|||
|
||||
@WebFault(name = "UnknownProductFault")
|
||||
public class UnknownProductFault extends Exception {
|
||||
public static final long serialVersionUID = 20081110144906L;
|
||||
|
||||
private org.keycloak.example.ws.types.UnknownProductFault unknownProductFault;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.keycloak.account.freemarker.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -11,6 +12,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.services.offline.OfflineTokenUtils;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
/**
|
||||
|
@ -21,6 +23,9 @@ public class ApplicationsBean {
|
|||
private List<ApplicationEntry> applications = new LinkedList<ApplicationEntry>();
|
||||
|
||||
public ApplicationsBean(RealmModel realm, UserModel user) {
|
||||
|
||||
Set<ClientModel> offlineClients = OfflineTokenUtils.findClientsWithOfflineToken(realm, user);
|
||||
|
||||
List<ClientModel> realmClients = realm.getClients();
|
||||
for (ClientModel client : realmClients) {
|
||||
// Don't show bearerOnly clients
|
||||
|
@ -28,7 +33,7 @@ public class ApplicationsBean {
|
|||
continue;
|
||||
}
|
||||
|
||||
Set<RoleModel> availableRoles = TokenManager.getAccess(null, client, user);
|
||||
Set<RoleModel> availableRoles = TokenManager.getAccess(null, false, client, user);
|
||||
// Don't show applications, which user doesn't have access into (any available roles)
|
||||
if (availableRoles.isEmpty()) {
|
||||
continue;
|
||||
|
@ -52,7 +57,13 @@ public class ApplicationsBean {
|
|||
}
|
||||
}
|
||||
|
||||
ApplicationEntry appEntry = new ApplicationEntry(realmRolesAvailable, resourceRolesAvailable, realmRolesGranted, resourceRolesGranted, client, claimsGranted);
|
||||
List<String> additionalGrants = new ArrayList<>();
|
||||
if (offlineClients.contains(client)) {
|
||||
additionalGrants.add("${offlineToken}");
|
||||
}
|
||||
|
||||
ApplicationEntry appEntry = new ApplicationEntry(realmRolesAvailable, resourceRolesAvailable, realmRolesGranted, resourceRolesGranted, client,
|
||||
claimsGranted, additionalGrants);
|
||||
applications.add(appEntry);
|
||||
}
|
||||
}
|
||||
|
@ -82,16 +93,18 @@ public class ApplicationsBean {
|
|||
private final MultivaluedHashMap<String, ClientRoleEntry> resourceRolesGranted;
|
||||
private final ClientModel client;
|
||||
private final List<String> claimsGranted;
|
||||
private final List<String> additionalGrants;
|
||||
|
||||
public ApplicationEntry(List<RoleModel> realmRolesAvailable, MultivaluedHashMap<String, ClientRoleEntry> resourceRolesAvailable,
|
||||
List<RoleModel> realmRolesGranted, MultivaluedHashMap<String, ClientRoleEntry> resourceRolesGranted,
|
||||
ClientModel client, List<String> claimsGranted) {
|
||||
ClientModel client, List<String> claimsGranted, List<String> additionalGrants) {
|
||||
this.realmRolesAvailable = realmRolesAvailable;
|
||||
this.resourceRolesAvailable = resourceRolesAvailable;
|
||||
this.realmRolesGranted = realmRolesGranted;
|
||||
this.resourceRolesGranted = resourceRolesGranted;
|
||||
this.client = client;
|
||||
this.claimsGranted = claimsGranted;
|
||||
this.additionalGrants = additionalGrants;
|
||||
}
|
||||
|
||||
public List<RoleModel> getRealmRolesAvailable() {
|
||||
|
@ -118,6 +131,9 @@ public class ApplicationsBean {
|
|||
return claimsGranted;
|
||||
}
|
||||
|
||||
public List<String> getAdditionalGrants() {
|
||||
return additionalGrants;
|
||||
}
|
||||
}
|
||||
|
||||
// Same class used in OAuthGrantBean as well. Maybe should be merged into common-freemarker...
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<td>${msg("availablePermissions")}</td>
|
||||
<td>${msg("grantedPermissions")}</td>
|
||||
<td>${msg("grantedPersonalInfo")}</td>
|
||||
<td>${msg("additionalGrants")}</td>
|
||||
<td>${msg("action")}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -76,7 +77,13 @@
|
|||
</td>
|
||||
|
||||
<td>
|
||||
<#if application.client.consentRequired && application.claimsGranted?has_content>
|
||||
<#list application.additionalGrants as grant>
|
||||
${advancedMsg(grant)}<#if grant_has_next>, </#if>
|
||||
</#list>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<#if (application.client.consentRequired && application.claimsGranted?has_content) || application.additionalGrants?has_content>
|
||||
<button type='submit' class='${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!}' id='revoke-${application.client.clientId}' name='clientId' value="${application.client.id}">${msg("revoke")}</button>
|
||||
</#if>
|
||||
</td>
|
||||
|
|
|
@ -52,6 +52,7 @@ role_manage-events=Manage events
|
|||
role_view-profile=View profile
|
||||
role_manage-account=Manage account
|
||||
role_read-token=Read token
|
||||
role_offline-access=Offline access
|
||||
client_account=Account
|
||||
client_security-admin-console=Security Admin Console
|
||||
client_realm-management=Realm Management
|
||||
|
@ -85,9 +86,11 @@ application=Application
|
|||
availablePermissions=Available Permissions
|
||||
grantedPermissions=Granted Permissions
|
||||
grantedPersonalInfo=Granted Personal Info
|
||||
additionalGrants=Additional Grants
|
||||
action=Action
|
||||
inResource=in
|
||||
fullAccess=Full Access
|
||||
offlineToken=Offline Token
|
||||
revoke=Revoke Grant
|
||||
|
||||
configureAuthenticators=Configured Authenticators
|
||||
|
|
|
@ -2036,3 +2036,26 @@ module.directive( 'kcOpen', function ( $location ) {
|
|||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.directive('kcOnReadFile', function ($parse) {
|
||||
console.debug('kcOnReadFile');
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: false,
|
||||
link: function(scope, element, attrs) {
|
||||
var fn = $parse(attrs.kcOnReadFile);
|
||||
|
||||
element.on('change', function(onChangeEvent) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function(onLoadEvent) {
|
||||
scope.$apply(function() {
|
||||
fn(scope, {$fileContent:onLoadEvent.target.result});
|
||||
});
|
||||
};
|
||||
|
||||
reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -155,7 +155,7 @@ module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $l
|
|||
}
|
||||
});
|
||||
|
||||
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, Dialog, Notifications, Auth) {
|
||||
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, $route, Dialog, Notifications, Auth, $modal) {
|
||||
console.log('RealmCreateCtrl');
|
||||
|
||||
Current.realm = null;
|
||||
|
@ -169,55 +169,21 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
|
||||
var oldCopy = angular.copy($scope.realm);
|
||||
|
||||
$scope.onFileSelect = function($files) {
|
||||
$scope.files = $files;
|
||||
$scope.importFile = function($fileContent){
|
||||
$scope.realm = angular.copy(JSON.parse($fileContent));
|
||||
$scope.importing = true;
|
||||
};
|
||||
|
||||
$scope.clearFileSelect = function() {
|
||||
$scope.files = null;
|
||||
$scope.viewImportDetails = function() {
|
||||
$modal.open({
|
||||
templateUrl: resourceUrl + '/partials/modal/view-object.html',
|
||||
controller: 'ObjectModalCtrl',
|
||||
resolve: {
|
||||
object: function () {
|
||||
return $scope.realm;
|
||||
}
|
||||
|
||||
$scope.uploadFile = function() {
|
||||
//$files: an array of files selected, each file has name, size, and type.
|
||||
for (var i = 0; i < $scope.files.length; i++) {
|
||||
var $file = $scope.files[i];
|
||||
$scope.upload = $upload.upload({
|
||||
url: authUrl + '/admin/realms', //upload.php script, node.js route, or servlet url
|
||||
// method: POST or PUT,
|
||||
// headers: {'headerKey': 'headerValue'}, withCredential: true,
|
||||
data: {myObj: ""},
|
||||
file: $file
|
||||
/* set file formData name for 'Content-Desposition' header. Default: 'file' */
|
||||
//fileFormDataName: myFile,
|
||||
/* customize how data is added to formData. See #40#issuecomment-28612000 for example */
|
||||
//formDataAppender: function(formData, key, val){}
|
||||
}).progress(function(evt) {
|
||||
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
|
||||
}).success(function(data, status, headers) {
|
||||
Realm.query(function(data) {
|
||||
Current.realms = data;
|
||||
|
||||
|
||||
WhoAmI.get(function(user) {
|
||||
Auth.user = user;
|
||||
|
||||
Notifications.success("The realm has been uploaded.");
|
||||
|
||||
var location = headers('Location');
|
||||
if (location) {
|
||||
$location.url("/realms/" + location.substring(location.lastIndexOf('/') + 1));
|
||||
} else {
|
||||
$location.url("/realms");
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
.error(function() {
|
||||
Notifications.error("The realm can not be uploaded. Please verify the file.");
|
||||
|
||||
});
|
||||
//.then(success, error, progress);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('realm', function() {
|
||||
|
@ -226,6 +192,12 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
}
|
||||
}, true);
|
||||
|
||||
$scope.$watch('realm.realm', function() {
|
||||
if (create) {
|
||||
$scope.realm.id = $scope.realm.realm;
|
||||
}
|
||||
}, true);
|
||||
|
||||
$scope.save = function() {
|
||||
var realmCopy = angular.copy($scope.realm);
|
||||
Realm.create(realmCopy, function() {
|
||||
|
@ -243,10 +215,17 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
window.history.back();
|
||||
$location.url("/");
|
||||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
$route.reload();
|
||||
}
|
||||
});
|
||||
|
||||
module.controller('ObjectModalCtrl', function($scope, object) {
|
||||
$scope.object = object;
|
||||
});
|
||||
|
||||
module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, WhoAmI, Auth) {
|
||||
$scope.createRealm = !realm.realm;
|
||||
|
@ -693,10 +672,17 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
|
|||
|
||||
}
|
||||
];
|
||||
$scope.signatureAlgorithms = [
|
||||
"RSA_SHA1",
|
||||
"RSA_SHA256",
|
||||
"RSA_SHA512",
|
||||
"DSA_SHA1"
|
||||
];
|
||||
if (instance && instance.alias) {
|
||||
|
||||
} else {
|
||||
$scope.identityProvider.config.nameIDPolicyFormat = $scope.nameIdFormats[0].format;
|
||||
$scope.identityProvider.config.signatureAlgorithm = $scope.signatureAlgorithms[1];
|
||||
$scope.identityProvider.updateProfileFirstLoginMode = "off";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,13 @@
|
|||
required> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="scopeParamRequired">Scope Param Required </label>
|
||||
<kc-tooltip>This role will be granted just if scope parameter with role name is used during authorization/token request.</kc-tooltip>
|
||||
<div class="col-md-6">
|
||||
<input ng-model="role.scopeParamRequired" name="scopeParamRequired" id="scopeParamRequired" onoffswitch />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group clearfix block" data-ng-hide="create">
|
||||
<label class="col-md-2 control-label" for="compositeSwitch" class="control-label">Composite Roles</label>
|
||||
<div class="col-md-6">
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<div style="padding: 20px 20px 10px 20px">
|
||||
<pre ng-bind = "{{object}} | json"></pre>
|
||||
</div>
|
|
@ -34,7 +34,7 @@
|
|||
placeholder="No value assigned" min="1" required>
|
||||
</td>
|
||||
<td class="kc-action-cell">
|
||||
<button class="btn btn-default btn-block btn-sm" ng-click="removePolicy($index)">Delete</button>
|
||||
<button type="button" class="btn btn-default btn-block btn-sm" ng-click="removePolicy($index)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -1,29 +1,22 @@
|
|||
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<fieldset>
|
||||
<legend><span class="text">Import Realm</span></legend>
|
||||
<div class="form-group">
|
||||
<label for="import-file" class="col-sm-2 control-label">Import JSON File </label>
|
||||
<div class="col-md-6">
|
||||
<div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
|
||||
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
|
||||
<input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
|
||||
</div>
|
||||
<span class="kc-uploaded-file" data-ng-show="files.length > 0">{{files[0].name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-10 col-md-offset-2">
|
||||
<button type="submit" data-ng-disabled="files.length == 0" data-ng-click="uploadFile()" class="btn btn-primary">Upload</button>
|
||||
<button type="submit" data-ng-disabled="files.length == 0" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<fieldset>
|
||||
<legend><span class="text">Create Realm</span></legend>
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">Import</label>
|
||||
|
||||
<div class="col-md-6" data-ng-hide="importing">
|
||||
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
|
||||
<input id="import-file" type="file" class="hidden" kc-on-read-file="importFile($fileContent)">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6" data-ng-show="importing">
|
||||
<button class="btn btn-default" data-ng-click="viewImportDetails()">View details</button>
|
||||
<button class="btn btn-default" data-ng-click="reset()">Clear import</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">Name <span class="required">*</span></label>
|
||||
|
||||
|
@ -42,6 +35,7 @@
|
|||
<div class="form-group">
|
||||
<div class="col-md-10 col-md-offset-2">
|
||||
<button kc-save data-ng-disabled="!changed">Create</button>
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -135,6 +135,18 @@
|
|||
</div>
|
||||
<kc-tooltip> Indicates whether the identity provider expects signed a AuthnRequest.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group" data-ng-show="identityProvider.config.wantAuthnRequestsSigned == 'true'">
|
||||
<label class="col-md-2 control-label" for="signatureAlgorithm">Signature Algorithm</label>
|
||||
<div class="col-sm-6">
|
||||
<div>
|
||||
<select class="form-control" id="signatureAlgorithm"
|
||||
ng-model="identityProvider.config.signatureAlgorithm"
|
||||
ng-options="alg for alg in signatureAlgorithms">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<kc-tooltip>The signature algorithm to use to sign documents.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="forceAuthn">Force Authentication</label>
|
||||
<div class="col-md-6">
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
<textarea class="form-control" rows="5" cols="50" id="description" name="description" data-ng-model="role.description"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="scopeParamRequired">Scope Param Required </label>
|
||||
<kc-tooltip>This role will be granted just if scope parameter with role name is used during authorization/token request.</kc-tooltip>
|
||||
<div class="col-md-6">
|
||||
<input ng-model="role.scopeParamRequired" name="scopeParamRequired" id="scopeParamRequired" onoffswitch />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" data-ng-hide="create">
|
||||
<label class="col-md-2 control-label" for="compositeSwitch" class="control-label">Composite Roles</label>
|
||||
<div class="col-md-6">
|
||||
|
|
|
@ -6,6 +6,16 @@
|
|||
${msg("loginProfileTitle")}
|
||||
<#elseif section = "form">
|
||||
<form id="kc-update-profile-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||
<#if realm.editUsernameAllowed>
|
||||
<div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('username',properties.kcFormGroupErrorClass!)}">
|
||||
<div class="${properties.kcLabelWrapperClass!}">
|
||||
<label for="username" class="${properties.kcLabelClass!}">${msg("username")}</label>
|
||||
</div>
|
||||
<div class="${properties.kcInputWrapperClass!}">
|
||||
<input type="text" id="username" name="username" value="${(user.username!'')?html}" class="${properties.kcInputClass!}"/>
|
||||
</div>
|
||||
</div>
|
||||
</#if>
|
||||
<div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('email',properties.kcFormGroupErrorClass!)}">
|
||||
<div class="${properties.kcLabelWrapperClass!}">
|
||||
<label for="email" class="${properties.kcLabelClass!}">${msg("email")}</label>
|
||||
|
|
|
@ -104,6 +104,7 @@ role_manage-events=Manage events
|
|||
role_view-profile=View profile
|
||||
role_manage-account=Manage account
|
||||
role_read-token=Read token
|
||||
role_offline-access=Offline access
|
||||
client_account=Account
|
||||
client_security-admin-console=Security Admin Console
|
||||
client_realm-management=Realm Management
|
||||
|
|
|
@ -70,6 +70,8 @@ public class ProfileBean {
|
|||
|
||||
}
|
||||
|
||||
public String getUsername() { return formData != null ? formData.getFirst("username") : user.getUsername(); }
|
||||
|
||||
public String getFirstName() {
|
||||
return formData != null ? formData.getFirst("firstName") : user.getFirstName();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,10 @@ public class RealmBean {
|
|||
return realm.isInternationalizationEnabled();
|
||||
}
|
||||
|
||||
public boolean isEditUsernameAllowed() {
|
||||
return realm.isEditUsernameAllowed();
|
||||
}
|
||||
|
||||
public boolean isPassword() {
|
||||
for (RequiredCredentialModel r : realm.getRequiredCredentials()) {
|
||||
if (r.getType().equals(CredentialRepresentation.PASSWORD)) {
|
||||
|
|
|
@ -134,6 +134,9 @@ public class OAuthRequestAuthenticator {
|
|||
String idpHint = getQueryParamValue(AdapterConstants.KC_IDP_HINT);
|
||||
url = UriUtils.stripQueryParam(url, AdapterConstants.KC_IDP_HINT);
|
||||
|
||||
String scope = getQueryParamValue(OAuth2Constants.SCOPE);
|
||||
url = UriUtils.stripQueryParam(url, OAuth2Constants.SCOPE);
|
||||
|
||||
KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
|
||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
||||
|
@ -146,6 +149,9 @@ public class OAuthRequestAuthenticator {
|
|||
if (idpHint != null && idpHint.length() > 0) {
|
||||
redirectUriBuilder.queryParam(AdapterConstants.KC_IDP_HINT,idpHint);
|
||||
}
|
||||
if (scope != null && scope.length() > 0) {
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
||||
}
|
||||
|
||||
return redirectUriBuilder.build().toString();
|
||||
}
|
||||
|
|
|
@ -117,7 +117,12 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext
|
|||
}
|
||||
|
||||
this.token = token;
|
||||
if (response.getRefreshToken() != null) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Setup new refresh token to the security context");
|
||||
}
|
||||
this.refreshToken = response.getRefreshToken();
|
||||
}
|
||||
this.tokenString = tokenString;
|
||||
tokenStore.refreshCallback(this);
|
||||
return true;
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.keycloak.adapters.KeycloakDeployment;
|
|||
*
|
||||
* You must specify a file
|
||||
* META-INF/services/org.keycloak.adapters.authentication.ClientCredentialsProvider in the WAR that this class is contained in (or in the JAR that is attached to the WEB-INF/lib or as jboss module
|
||||
* if you want to share the implementation among more WARs). This file must have the fully qualified class name of all your ClientAuthenticatorFactory classes
|
||||
* if you want to share the implementation among more WARs).
|
||||
*
|
||||
* NOTE: The SPI is not finished and method signatures are still subject to change in future versions (for example to support
|
||||
* authentication with client certificate)
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.keycloak.util.Time;
|
|||
|
||||
/**
|
||||
* Client authentication based on JWT signed by client private key .
|
||||
* See <a href="https://tools.ietf.org/html/draft-jones-oauth-jwt-bearer-03">specs</a> for more details.
|
||||
* See <a href="https://tools.ietf.org/html/rfc7519">specs</a> for more details.
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.security.Principal;
|
|||
*/
|
||||
public class RolePrincipal implements Principal, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5538962177019315447L;
|
||||
private String roleName = null;
|
||||
|
||||
public RolePrincipal(String roleName) {
|
||||
|
|
|
@ -164,6 +164,10 @@
|
|||
url += '&kc_idp_hint=' + options.idpHint;
|
||||
}
|
||||
|
||||
if (options && options.scope) {
|
||||
url += '&scope=' + options.scope;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
public class SimpleGroup extends SimplePrincipal implements Group {
|
||||
private static final long serialVersionUID = 3273437693505893786L;
|
||||
private final Set<Principal> members = new HashSet<Principal>();
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.security.Principal;
|
|||
public class SimplePrincipal implements Principal, Serializable {
|
||||
|
||||
/** SimplePrincipal.java */
|
||||
private static final long serialVersionUID = -5645357206342793145L;
|
||||
|
||||
/** The unique identifier for this principal. */
|
||||
private final String name;
|
||||
|
|
|
@ -7,31 +7,21 @@
|
|||
|
||||
## Release
|
||||
|
||||
*Releasing currently requires using JDK 7 due to a bug in JAX-RS Doclets*
|
||||
|
||||
### Clone from GitHub
|
||||
|
||||
# git clone https://github.com/keycloak/keycloak.git
|
||||
# cd keycloak
|
||||
|
||||
### Update version
|
||||
### Prepare the release
|
||||
|
||||
# mvn versions:set -DnewVersion=$VERSION -DgenerateBackupPoms=false -Pjboss-release
|
||||
# mvn -Pjboss-release release:prepare
|
||||
|
||||
### Build
|
||||
### Perform the release
|
||||
|
||||
# mvn install install -Pdistribution
|
||||
# mvn install -Pjboss-release -DskipTests
|
||||
|
||||
### Tag
|
||||
|
||||
# git tag $VERSION
|
||||
# git push --tags
|
||||
# mvn -Pjboss-release release:perform
|
||||
|
||||
### Deploy to Nexus
|
||||
|
||||
# mvn deploy -DskipTests -Pjboss-release
|
||||
|
||||
Then login to Nexus and release the maven uploads in the staging area. Artifacts will eventually be synced to Maven Central, but this can take up to 24 hours.
|
||||
|
||||
### Upload
|
||||
|
@ -51,7 +41,6 @@ Upload all artifacts to downloads.jboss.org (see https://mojo.redhat.com/docs/DO
|
|||
# git tag $VERSION
|
||||
# git push --tags
|
||||
|
||||
|
||||
## After Release
|
||||
|
||||
### Update Bower
|
||||
|
|
|
@ -11,7 +11,7 @@ public interface MigrationModel {
|
|||
/**
|
||||
* Must have the form of major.minor.micro as the version is parsed and numbers are compared
|
||||
*/
|
||||
public static final String LATEST_VERSION = "1.5.0";
|
||||
public static final String LATEST_VERSION = "1.6.0";
|
||||
|
||||
String getStoredVersion();
|
||||
void setStoredVersion(String version);
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.jboss.logging.Logger;
|
|||
import org.keycloak.migration.migrators.MigrateTo1_3_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo1_4_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo1_5_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo1_6_0;
|
||||
import org.keycloak.migration.migrators.MigrationTo1_2_0_CR1;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
|
@ -47,6 +48,12 @@ public class MigrationModelManager {
|
|||
}
|
||||
new MigrateTo1_5_0().migrate(session);
|
||||
}
|
||||
if (stored == null || stored.lessThan(MigrateTo1_6_0.VERSION)) {
|
||||
if (stored != null) {
|
||||
logger.debug("Migrating older model to 1.6.0 updates");
|
||||
}
|
||||
new MigrateTo1_6_0().migrate(session);
|
||||
}
|
||||
|
||||
model.setStoredVersion(MigrationModel.LATEST_VERSION);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package org.keycloak.migration.migrators;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.migration.ModelVersion;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class MigrateTo1_6_0 {
|
||||
|
||||
public static final ModelVersion VERSION = new ModelVersion("1.6.0");
|
||||
|
||||
public void migrate(KeycloakSession session) {
|
||||
List<RealmModel> realms = session.realms().getRealms();
|
||||
for (RealmModel realm : realms) {
|
||||
KeycloakModelUtils.setupOfflineTokens(realm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ import org.keycloak.models.ClientModel;
|
|||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -26,7 +27,9 @@ public class MigrationTo1_2_0_CR1 {
|
|||
client.setFullScopeAllowed(false);
|
||||
|
||||
for (String role : Constants.BROKER_SERVICE_ROLES) {
|
||||
client.addRole(role).setDescription("${role_"+ role.toLowerCase().replaceAll("_", "-") +"}");
|
||||
RoleModel roleModel = client.addRole(role);
|
||||
roleModel.setDescription("${role_" + role.toLowerCase().replaceAll("_", "-") + "}");
|
||||
roleModel.setScopeParamRequired(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.io.Serializable;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AuthenticationExecutionModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static class ExecutionComparator implements Comparator<AuthenticationExecutionModel> {
|
||||
public static final ExecutionComparator SINGLETON = new ExecutionComparator();
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.io.Serializable;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AuthenticationFlowModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
private String alias;
|
||||
|
|
|
@ -9,7 +9,6 @@ import java.util.Map;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AuthenticatorConfigModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
private String alias;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
@ -16,4 +18,5 @@ public interface Constants {
|
|||
String INSTALLED_APP_URL = "http://localhost";
|
||||
String READ_TOKEN_ROLE = "read-token";
|
||||
String[] BROKER_SERVICE_ROLES = {READ_TOKEN_ROLE};
|
||||
String OFFLINE_ACCESS_ROLE = OAuth2Constants.OFFLINE_ACCESS;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Map;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class IdentityProviderMapperModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String id;
|
||||
protected String name;
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
|||
* @author Pedro Igor
|
||||
*/
|
||||
public class IdentityProviderModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String internalId;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ public class ImpersonationConstants {
|
|||
if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
|
||||
RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
|
||||
impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
|
||||
impersonationRole.setScopeParamRequired(false);
|
||||
adminRole.addCompositeRole(impersonationRole);
|
||||
}
|
||||
|
||||
|
@ -36,6 +37,7 @@ public class ImpersonationConstants {
|
|||
if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
|
||||
RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
|
||||
impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
|
||||
impersonationRole.setScopeParamRequired(false);
|
||||
RoleModel adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
|
||||
adminRole.addCompositeRole(impersonationRole);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class OfflineClientSessionModel {
|
||||
|
||||
private String clientSessionId;
|
||||
private String userSessionId;
|
||||
private String clientId;
|
||||
private String data;
|
||||
|
||||
public String getClientSessionId() {
|
||||
return clientSessionId;
|
||||
}
|
||||
|
||||
public void setClientSessionId(String clientSessionId) {
|
||||
this.clientSessionId = clientSessionId;
|
||||
}
|
||||
|
||||
public String getUserSessionId() {
|
||||
return userSessionId;
|
||||
}
|
||||
|
||||
public void setUserSessionId(String userSessionId) {
|
||||
this.userSessionId = userSessionId;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class OfflineUserSessionModel {
|
||||
|
||||
private String userSessionId;
|
||||
private String data;
|
||||
|
||||
public String getUserSessionId() {
|
||||
return userSessionId;
|
||||
}
|
||||
|
||||
public void setUserSessionId(String userSessionId) {
|
||||
this.userSessionId = userSessionId;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@ import java.util.regex.Pattern;
|
|||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class PasswordPolicy implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final String INVALID_PASSWORD_MIN_LENGTH_MESSAGE = "invalidPasswordMinLengthMessage";
|
||||
public static final String INVALID_PASSWORD_MIN_DIGITS_MESSAGE = "invalidPasswordMinDigitsMessage";
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Map;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ProtocolMapperModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String id;
|
||||
protected String name;
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Map;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RequiredCredentialModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String type;
|
||||
protected boolean input;
|
||||
|
|
|
@ -17,6 +17,10 @@ public interface RoleModel {
|
|||
|
||||
void setName(String name);
|
||||
|
||||
boolean isScopeParamRequired();
|
||||
|
||||
void setScopeParamRequired(boolean scopeParamRequired);
|
||||
|
||||
boolean isComposite();
|
||||
|
||||
void addCompositeRole(RoleModel role);
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.Map;
|
|||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class UserFederationMapperModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String id;
|
||||
protected String name;
|
||||
|
|
|
@ -11,7 +11,6 @@ import java.util.Map;
|
|||
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
|
||||
*/
|
||||
public class UserFederationProviderModel implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
private String providerName;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -113,6 +114,15 @@ public interface UserModel {
|
|||
void updateConsent(UserConsentModel consent);
|
||||
boolean revokeConsentForClient(String clientInternalId);
|
||||
|
||||
void addOfflineUserSession(OfflineUserSessionModel offlineUserSession);
|
||||
OfflineUserSessionModel getOfflineUserSession(String userSessionId);
|
||||
Collection<OfflineUserSessionModel> getOfflineUserSessions();
|
||||
boolean removeOfflineUserSession(String userSessionId);
|
||||
void addOfflineClientSession(OfflineClientSessionModel offlineClientSession);
|
||||
OfflineClientSessionModel getOfflineClientSession(String clientSessionId);
|
||||
Collection<OfflineClientSessionModel> getOfflineClientSessions();
|
||||
boolean removeOfflineClientSession(String clientSessionId);
|
||||
|
||||
public static enum RequiredAction {
|
||||
VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public interface UserSessionModel {
|
|||
public String getNote(String name);
|
||||
public void setNote(String name, String value);
|
||||
public void removeNote(String name);
|
||||
public Map<String, String> getNotes();
|
||||
|
||||
State getState();
|
||||
void setState(State state);
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.keycloak.models.entities;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class OfflineClientSessionEntity {
|
||||
|
||||
private String clientSessionId;
|
||||
private String clientId;
|
||||
private String data;
|
||||
|
||||
public String getClientSessionId() {
|
||||
return clientSessionId;
|
||||
}
|
||||
|
||||
public void setClientSessionId(String clientSessionId) {
|
||||
this.clientSessionId = clientSessionId;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.keycloak.models.entities;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class OfflineUserSessionEntity {
|
||||
|
||||
private String userSessionId;
|
||||
private String data;
|
||||
private List<OfflineClientSessionEntity> offlineClientSessions;
|
||||
|
||||
public String getUserSessionId() {
|
||||
return userSessionId;
|
||||
}
|
||||
|
||||
public void setUserSessionId(String userSessionId) {
|
||||
this.userSessionId = userSessionId;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public List<OfflineClientSessionEntity> getOfflineClientSessions() {
|
||||
return offlineClientSessions;
|
||||
}
|
||||
|
||||
public void setOfflineClientSessions(List<OfflineClientSessionEntity> offlineClientSessions) {
|
||||
this.offlineClientSessions = offlineClientSessions;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ public class RoleEntity extends AbstractIdentifiableEntity {
|
|||
|
||||
private String name;
|
||||
private String description;
|
||||
private boolean scopeParamRequired;
|
||||
|
||||
private List<String> compositeRoleIds;
|
||||
|
||||
|
@ -31,6 +32,14 @@ public class RoleEntity extends AbstractIdentifiableEntity {
|
|||
this.description = description;
|
||||
}
|
||||
|
||||
public boolean isScopeParamRequired() {
|
||||
return scopeParamRequired;
|
||||
}
|
||||
|
||||
public void setScopeParamRequired(boolean scopeParamRequired) {
|
||||
this.scopeParamRequired = scopeParamRequired;
|
||||
}
|
||||
|
||||
public List<String> getCompositeRoleIds() {
|
||||
return compositeRoleIds;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ public class UserEntity extends AbstractIdentifiableEntity {
|
|||
private List<FederatedIdentityEntity> federatedIdentities;
|
||||
private String federationLink;
|
||||
private String serviceAccountClientLink;
|
||||
private List<OfflineUserSessionEntity> offlineUserSessions;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
|
@ -157,5 +158,13 @@ public class UserEntity extends AbstractIdentifiableEntity {
|
|||
public void setServiceAccountClientLink(String serviceAccountClientLink) {
|
||||
this.serviceAccountClientLink = serviceAccountClientLink;
|
||||
}
|
||||
|
||||
public List<OfflineUserSessionEntity> getOfflineUserSessions() {
|
||||
return offlineUserSessions;
|
||||
}
|
||||
|
||||
public void setOfflineUserSessions(List<OfflineUserSessionEntity> offlineUserSessions) {
|
||||
this.offlineUserSessions = offlineUserSessions;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bouncycastle.openssl.PEMWriter;
|
|||
import org.keycloak.constants.KerberosConstants;
|
||||
import org.keycloak.constants.ServiceAccountConstants;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.KeycloakSessionTask;
|
||||
|
@ -360,4 +361,13 @@ public final class KeycloakModelUtils {
|
|||
public static String toLowerCaseSafe(String str) {
|
||||
return str==null ? null : str.toLowerCase();
|
||||
}
|
||||
|
||||
public static void setupOfflineTokens(RealmModel realm) {
|
||||
if (realm.getRole(Constants.OFFLINE_ACCESS_ROLE) == null) {
|
||||
RoleModel role = realm.addRole(Constants.OFFLINE_ACCESS_ROLE);
|
||||
role.setDescription("${role_offline-access}");
|
||||
role.setScopeParamRequired(true);
|
||||
realm.addDefaultRole(Constants.OFFLINE_ACCESS_ROLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ public class ModelToRepresentation {
|
|||
rep.setId(role.getId());
|
||||
rep.setName(role.getName());
|
||||
rep.setDescription(role.getDescription());
|
||||
rep.setScopeParamRequired(role.isScopeParamRequired());
|
||||
rep.setComposite(role.isComposite());
|
||||
return rep;
|
||||
}
|
||||
|
|
|
@ -181,6 +181,8 @@ public class RepresentationToModel {
|
|||
// Application role may already exists (for example if it is defaultRole)
|
||||
RoleModel role = roleRep.getId()!=null ? client.addRole(roleRep.getId(), roleRep.getName()) : client.addRole(roleRep.getName());
|
||||
role.setDescription(roleRep.getDescription());
|
||||
boolean scopeParamRequired = roleRep.isScopeParamRequired()==null ? false : roleRep.isScopeParamRequired();
|
||||
role.setScopeParamRequired(scopeParamRequired);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -633,6 +635,8 @@ public class RepresentationToModel {
|
|||
public static void createRole(RealmModel newRealm, RoleRepresentation roleRep) {
|
||||
RoleModel role = roleRep.getId()!=null ? newRealm.addRole(roleRep.getId(), roleRep.getName()) : newRealm.addRole(roleRep.getName());
|
||||
if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
|
||||
boolean scopeParamRequired = roleRep.isScopeParamRequired() == null ? false : roleRep.isScopeParamRequired();
|
||||
role.setScopeParamRequired(scopeParamRequired);
|
||||
}
|
||||
|
||||
private static void addComposites(RoleModel role, RoleRepresentation roleRep, RealmModel realm) {
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package org.keycloak.models.utils;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.OfflineClientSessionModel;
|
||||
import org.keycloak.models.OfflineUserSessionModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -255,4 +258,44 @@ public class UserModelDelegate implements UserModel {
|
|||
public void setCreatedTimestamp(Long timestamp){
|
||||
delegate.setCreatedTimestamp(timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineUserSession(OfflineUserSessionModel userSession) {
|
||||
delegate.addOfflineUserSession(userSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineUserSessionModel getOfflineUserSession(String userSessionId) {
|
||||
return delegate.getOfflineUserSession(userSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineUserSessionModel> getOfflineUserSessions() {
|
||||
return delegate.getOfflineUserSessions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineUserSession(String userSessionId) {
|
||||
return delegate.removeOfflineUserSession(userSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineClientSession(OfflineClientSessionModel clientSession) {
|
||||
delegate.addOfflineClientSession(clientSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineClientSessionModel getOfflineClientSession(String clientSessionId) {
|
||||
return delegate.getOfflineClientSession(clientSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineClientSessionModel> getOfflineClientSessions() {
|
||||
return delegate.getOfflineClientSessions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineClientSession(String clientSessionId) {
|
||||
return delegate.removeOfflineClientSession(clientSessionId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,6 +88,16 @@ public class RoleAdapter implements RoleModel {
|
|||
role.setDescription(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScopeParamRequired() {
|
||||
return role.isScopeParamRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScopeParamRequired(boolean scopeParamRequired) {
|
||||
role.setScopeParamRequired(scopeParamRequired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComposite() {
|
||||
return role.getCompositeRoleIds() != null && role.getCompositeRoleIds().size() > 0;
|
||||
|
|
|
@ -22,7 +22,10 @@ import org.keycloak.models.ClientModel;
|
|||
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
||||
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.OTPPolicy;
|
||||
import org.keycloak.models.OfflineClientSessionModel;
|
||||
import org.keycloak.models.OfflineUserSessionModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -32,6 +35,8 @@ import org.keycloak.models.UserCredentialValueModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.entities.CredentialEntity;
|
||||
import org.keycloak.models.entities.FederatedIdentityEntity;
|
||||
import org.keycloak.models.entities.OfflineClientSessionEntity;
|
||||
import org.keycloak.models.entities.OfflineUserSessionEntity;
|
||||
import org.keycloak.models.entities.RoleEntity;
|
||||
import org.keycloak.models.entities.UserEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
@ -39,6 +44,7 @@ import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
|||
import org.keycloak.util.Time;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
@ -216,7 +222,7 @@ public class UserAdapter implements UserModel, Comparable {
|
|||
|
||||
@Override
|
||||
public Map<String, List<String>> getAttributes() {
|
||||
return user.getAttributes()==null ? Collections.<String, List<String>>emptyMap() : Collections.unmodifiableMap((Map)user.getAttributes());
|
||||
return user.getAttributes()==null ? Collections.<String, List<String>>emptyMap() : Collections.unmodifiableMap((Map) user.getAttributes());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -568,6 +574,142 @@ public class UserAdapter implements UserModel, Comparable {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineUserSession(OfflineUserSessionModel userSession) {
|
||||
if (user.getOfflineUserSessions() == null) {
|
||||
user.setOfflineUserSessions(new ArrayList<OfflineUserSessionEntity>());
|
||||
}
|
||||
|
||||
if (getUserSessionEntityById(userSession.getUserSessionId()) != null) {
|
||||
throw new ModelDuplicateException("User session already exists with id " + userSession.getUserSessionId() + " for user " + user.getUsername());
|
||||
}
|
||||
|
||||
OfflineUserSessionEntity entity = new OfflineUserSessionEntity();
|
||||
entity.setUserSessionId(userSession.getUserSessionId());
|
||||
entity.setData(userSession.getData());
|
||||
entity.setOfflineClientSessions(new ArrayList<OfflineClientSessionEntity>());
|
||||
user.getOfflineUserSessions().add(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineUserSessionModel getOfflineUserSession(String userSessionId) {
|
||||
OfflineUserSessionEntity entity = getUserSessionEntityById(userSessionId);
|
||||
return entity==null ? null : toModel(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineUserSessionModel> getOfflineUserSessions() {
|
||||
if (user.getOfflineUserSessions()==null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
List<OfflineUserSessionModel> result = new ArrayList<>();
|
||||
for (OfflineUserSessionEntity entity : user.getOfflineUserSessions()) {
|
||||
result.add(toModel(entity));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private OfflineUserSessionModel toModel(OfflineUserSessionEntity entity) {
|
||||
OfflineUserSessionModel model = new OfflineUserSessionModel();
|
||||
model.setUserSessionId(entity.getUserSessionId());
|
||||
model.setData(entity.getData());
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineUserSession(String userSessionId) {
|
||||
OfflineUserSessionEntity entity = getUserSessionEntityById(userSessionId);
|
||||
if (entity != null) {
|
||||
user.getOfflineUserSessions().remove(entity);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private OfflineUserSessionEntity getUserSessionEntityById(String userSessionId) {
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity entity : user.getOfflineUserSessions()) {
|
||||
if (entity.getUserSessionId().equals(userSessionId)) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineClientSession(OfflineClientSessionModel clientSession) {
|
||||
OfflineUserSessionEntity userSessionEntity = getUserSessionEntityById(clientSession.getUserSessionId());
|
||||
if (userSessionEntity == null) {
|
||||
throw new ModelException("OfflineUserSession with ID " + clientSession.getUserSessionId() + " doesn't exist for user " + user.getUsername());
|
||||
}
|
||||
|
||||
OfflineClientSessionEntity clEntity = new OfflineClientSessionEntity();
|
||||
clEntity.setClientSessionId(clientSession.getClientSessionId());
|
||||
clEntity.setClientId(clientSession.getClientId());
|
||||
clEntity.setData(clientSession.getData());
|
||||
|
||||
userSessionEntity.getOfflineClientSessions().add(clEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineClientSessionModel getOfflineClientSession(String clientSessionId) {
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity userSession : user.getOfflineUserSessions()) {
|
||||
for (OfflineClientSessionEntity clSession : userSession.getOfflineClientSessions()) {
|
||||
if (clSession.getClientSessionId().equals(clientSessionId)) {
|
||||
return toModel(clSession, userSession.getUserSessionId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private OfflineClientSessionModel toModel(OfflineClientSessionEntity cls, String userSessionId) {
|
||||
OfflineClientSessionModel model = new OfflineClientSessionModel();
|
||||
model.setClientSessionId(cls.getClientSessionId());
|
||||
model.setClientId(cls.getClientId());
|
||||
model.setData(cls.getData());
|
||||
model.setUserSessionId(userSessionId);
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineClientSessionModel> getOfflineClientSessions() {
|
||||
List<OfflineClientSessionModel> result = new ArrayList<>();
|
||||
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity userSession : user.getOfflineUserSessions()) {
|
||||
for (OfflineClientSessionEntity clSession : userSession.getOfflineClientSessions()) {
|
||||
result.add(toModel(clSession, userSession.getUserSessionId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineClientSession(String clientSessionId) {
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity userSession : user.getOfflineUserSessions()) {
|
||||
for (OfflineClientSessionEntity clSession : userSession.getOfflineClientSessions()) {
|
||||
if (clSession.getClientSessionId().equals(clientSessionId)) {
|
||||
userSession.getOfflineClientSessions().remove(clSession);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -319,6 +319,7 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
|
|||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, ClientModel client) {
|
||||
realmInvalidations.add(realm.getId()); // easier to just invalidate whole realm
|
||||
getDelegate().preRemove(realm, client);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,18 @@ public class RoleAdapter implements RoleModel {
|
|||
updated.setDescription(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScopeParamRequired() {
|
||||
if (updated != null) return updated.isScopeParamRequired();
|
||||
return cached.isScopeParamRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScopeParamRequired(boolean scopeParamRequired) {
|
||||
getDelegateForUpdate();
|
||||
updated.setScopeParamRequired(scopeParamRequired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
if (updated != null) return updated.getId();
|
||||
|
|
|
@ -348,4 +348,52 @@ public class UserAdapter implements UserModel {
|
|||
getDelegateForUpdate();
|
||||
return updated.revokeConsentForClient(clientId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineUserSession(OfflineUserSessionModel userSession) {
|
||||
getDelegateForUpdate();
|
||||
updated.addOfflineUserSession(userSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineUserSessionModel getOfflineUserSession(String userSessionId) {
|
||||
if (updated != null) return updated.getOfflineUserSession(userSessionId);
|
||||
return cached.getOfflineUserSessions().get(userSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineUserSessionModel> getOfflineUserSessions() {
|
||||
if (updated != null) return updated.getOfflineUserSessions();
|
||||
return cached.getOfflineUserSessions().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineUserSession(String userSessionId) {
|
||||
getDelegateForUpdate();
|
||||
return updated.removeOfflineUserSession(userSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineClientSession(OfflineClientSessionModel clientSession) {
|
||||
getDelegateForUpdate();
|
||||
updated.addOfflineClientSession(clientSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineClientSessionModel getOfflineClientSession(String clientSessionId) {
|
||||
if (updated != null) return updated.getOfflineClientSession(clientSessionId);
|
||||
return cached.getOfflineClientSessions().get(clientSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineClientSessionModel> getOfflineClientSessions() {
|
||||
if (updated != null) return updated.getOfflineClientSessions();
|
||||
return cached.getOfflineClientSessions().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineClientSession(String clientSessionId) {
|
||||
getDelegateForUpdate();
|
||||
return updated.removeOfflineClientSession(clientSessionId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.util.TreeMap;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CachedClient implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
private String clientId;
|
||||
|
|
|
@ -9,8 +9,6 @@ import org.keycloak.models.RoleModel;
|
|||
*/
|
||||
public class CachedClientRole extends CachedRole {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String idClient;
|
||||
|
||||
public CachedClientRole(String idClient, RoleModel model, RealmModel realm) {
|
||||
|
|
|
@ -33,7 +33,6 @@ import java.util.Set;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CachedRealm implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
|
|
|
@ -13,12 +13,11 @@ import java.util.Set;
|
|||
*/
|
||||
public class CachedRole implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
final protected String id;
|
||||
final protected String name;
|
||||
final protected String realm;
|
||||
final protected String description;
|
||||
final protected Boolean scopeParamRequired;
|
||||
final protected boolean composite;
|
||||
final protected Set<String> composites = new HashSet<String>();
|
||||
|
||||
|
@ -27,6 +26,7 @@ public class CachedRole implements Serializable {
|
|||
description = model.getDescription();
|
||||
id = model.getId();
|
||||
name = model.getName();
|
||||
scopeParamRequired = model.isScopeParamRequired();
|
||||
this.realm = realm.getId();
|
||||
if (composite) {
|
||||
for (RoleModel child : model.getComposites()) {
|
||||
|
@ -52,6 +52,10 @@ public class CachedRole implements Serializable {
|
|||
return description;
|
||||
}
|
||||
|
||||
public Boolean isScopeParamRequired() {
|
||||
return scopeParamRequired;
|
||||
}
|
||||
|
||||
public boolean isComposite() {
|
||||
return composite;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.models.cache.entities;
|
||||
|
||||
import org.keycloak.models.OfflineClientSessionModel;
|
||||
import org.keycloak.models.OfflineUserSessionModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
|
@ -7,9 +9,11 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -33,6 +37,8 @@ public class CachedUser implements Serializable {
|
|||
private MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
|
||||
private Set<String> requiredActions = new HashSet<>();
|
||||
private Set<String> roleMappings = new HashSet<String>();
|
||||
private Map<String, OfflineUserSessionModel> offlineUserSessions = new HashMap<>();
|
||||
private Map<String, OfflineClientSessionModel> offlineClientSessions = new HashMap<>();
|
||||
|
||||
public CachedUser(RealmModel realm, UserModel user) {
|
||||
this.id = user.getId();
|
||||
|
@ -53,6 +59,12 @@ public class CachedUser implements Serializable {
|
|||
for (RoleModel role : user.getRoleMappings()) {
|
||||
roleMappings.add(role.getId());
|
||||
}
|
||||
for (OfflineUserSessionModel offlineSession : user.getOfflineUserSessions()) {
|
||||
offlineUserSessions.put(offlineSession.getUserSessionId(), offlineSession);
|
||||
}
|
||||
for (OfflineClientSessionModel offlineSession : user.getOfflineClientSessions()) {
|
||||
offlineClientSessions.put(offlineSession.getClientSessionId(), offlineSession);
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -118,4 +130,12 @@ public class CachedUser implements Serializable {
|
|||
public String getServiceAccountClientLink() {
|
||||
return serviceAccountClientLink;
|
||||
}
|
||||
|
||||
public Map<String, OfflineUserSessionModel> getOfflineUserSessions() {
|
||||
return offlineUserSessions;
|
||||
}
|
||||
|
||||
public Map<String, OfflineClientSessionModel> getOfflineClientSessions() {
|
||||
return offlineClientSessions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,17 +17,14 @@
|
|||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
|
@ -44,18 +41,15 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
<artifactId>${hibernate.javax.persistence.artifactId}</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>log4j</groupId>
|
||||
|
|
|
@ -169,6 +169,10 @@ public class JpaUserProvider implements UserProvider {
|
|||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteUserAttributesByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteOfflineClientSessionsByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteOfflineUserSessionsByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteUsersByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
}
|
||||
|
@ -195,6 +199,14 @@ public class JpaUserProvider implements UserProvider {
|
|||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
num = em.createNamedQuery("deleteOfflineClientSessionsByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
num = em.createNamedQuery("deleteOfflineUserSessionsByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
num = em.createNamedQuery("deleteUsersByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
|
@ -212,6 +224,8 @@ public class JpaUserProvider implements UserProvider {
|
|||
em.createNamedQuery("deleteUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
|
||||
em.createNamedQuery("deleteUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
|
||||
em.createNamedQuery("deleteUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
|
||||
em.createNamedQuery("deleteOfflineClientSessionsByClient").setParameter("clientId", client.getId()).executeUpdate();
|
||||
em.createNamedQuery("deleteDetachedOfflineUserSessions").executeUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -49,6 +49,16 @@ public class RoleAdapter implements RoleModel {
|
|||
role.setDescription(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScopeParamRequired() {
|
||||
return role.isScopeParamRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScopeParamRequired(boolean scopeParamRequired) {
|
||||
role.setScopeParamRequired(scopeParamRequired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return role.getId();
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.keycloak.models.jpa;
|
|||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.OTPPolicy;
|
||||
import org.keycloak.models.OfflineClientSessionModel;
|
||||
import org.keycloak.models.OfflineUserSessionModel;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
|
@ -14,6 +16,8 @@ import org.keycloak.models.UserCredentialModel;
|
|||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.jpa.entities.CredentialEntity;
|
||||
import org.keycloak.models.jpa.entities.OfflineClientSessionEntity;
|
||||
import org.keycloak.models.jpa.entities.OfflineUserSessionEntity;
|
||||
import org.keycloak.models.jpa.entities.UserConsentEntity;
|
||||
import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
|
||||
import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
|
||||
|
@ -37,6 +41,7 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -750,6 +755,124 @@ public class UserAdapter implements UserModel {
|
|||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineUserSession(OfflineUserSessionModel offlineSession) {
|
||||
OfflineUserSessionEntity entity = new OfflineUserSessionEntity();
|
||||
entity.setUser(user);
|
||||
entity.setUserSessionId(offlineSession.getUserSessionId());
|
||||
entity.setData(offlineSession.getData());
|
||||
em.persist(entity);
|
||||
user.getOfflineUserSessions().add(entity);
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineUserSessionModel getOfflineUserSession(String userSessionId) {
|
||||
for (OfflineUserSessionEntity entity : user.getOfflineUserSessions()) {
|
||||
if (entity.getUserSessionId().equals(userSessionId)) {
|
||||
return toModel(entity);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private OfflineUserSessionModel toModel(OfflineUserSessionEntity entity) {
|
||||
OfflineUserSessionModel model = new OfflineUserSessionModel();
|
||||
model.setUserSessionId(entity.getUserSessionId());
|
||||
model.setData(entity.getData());
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineUserSessionModel> getOfflineUserSessions() {
|
||||
List<OfflineUserSessionModel> result = new LinkedList<>();
|
||||
for (OfflineUserSessionEntity entity : user.getOfflineUserSessions()) {
|
||||
result.add(toModel(entity));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineUserSession(String userSessionId) {
|
||||
OfflineUserSessionEntity found = null;
|
||||
for (OfflineUserSessionEntity session : user.getOfflineUserSessions()) {
|
||||
if (session.getUserSessionId().equals(userSessionId)) {
|
||||
found = session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == null) {
|
||||
return false;
|
||||
} else {
|
||||
user.getOfflineUserSessions().remove(found);
|
||||
em.remove(found);
|
||||
em.flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineClientSession(OfflineClientSessionModel clientSession) {
|
||||
OfflineClientSessionEntity entity = new OfflineClientSessionEntity();
|
||||
entity.setUser(user);
|
||||
entity.setClientSessionId(clientSession.getClientSessionId());
|
||||
entity.setUserSessionId(clientSession.getUserSessionId());
|
||||
entity.setClientId(clientSession.getClientId());
|
||||
entity.setData(clientSession.getData());
|
||||
em.persist(entity);
|
||||
user.getOfflineClientSessions().add(entity);
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineClientSessionModel getOfflineClientSession(String clientSessionId) {
|
||||
for (OfflineClientSessionEntity entity : user.getOfflineClientSessions()) {
|
||||
if (entity.getClientSessionId().equals(clientSessionId)) {
|
||||
return toModel(entity);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private OfflineClientSessionModel toModel(OfflineClientSessionEntity entity) {
|
||||
OfflineClientSessionModel model = new OfflineClientSessionModel();
|
||||
model.setClientSessionId(entity.getClientSessionId());
|
||||
model.setClientId(entity.getClientId());
|
||||
model.setUserSessionId(entity.getUserSessionId());
|
||||
model.setData(entity.getData());
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineClientSessionModel> getOfflineClientSessions() {
|
||||
List<OfflineClientSessionModel> result = new LinkedList<>();
|
||||
for (OfflineClientSessionEntity entity : user.getOfflineClientSessions()) {
|
||||
result.add(toModel(entity));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineClientSession(String clientSessionId) {
|
||||
OfflineClientSessionEntity found = null;
|
||||
for (OfflineClientSessionEntity session : user.getOfflineClientSessions()) {
|
||||
if (session.getClientSessionId().equals(clientSessionId)) {
|
||||
found = session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == null) {
|
||||
return false;
|
||||
} else {
|
||||
user.getOfflineClientSessions().remove(found);
|
||||
em.remove(found);
|
||||
em.flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="deleteOfflineClientSessionsByRealm", query="delete from OfflineClientSessionEntity sess where sess.user IN (select u from UserEntity u where u.realmId=:realmId)"),
|
||||
@NamedQuery(name="deleteOfflineClientSessionsByRealmAndLink", query="delete from OfflineClientSessionEntity sess where sess.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
|
||||
@NamedQuery(name="deleteOfflineClientSessionsByClient", query="delete from OfflineClientSessionEntity sess where sess.clientId=:clientId")
|
||||
})
|
||||
@Table(name="OFFLINE_CLIENT_SESSION")
|
||||
@Entity
|
||||
public class OfflineClientSessionEntity {
|
||||
|
||||
@Id
|
||||
@Column(name="CLIENT_SESSION_ID", length = 36)
|
||||
protected String clientSessionId;
|
||||
|
||||
@Column(name="USER_SESSION_ID", length = 36)
|
||||
protected String userSessionId;
|
||||
|
||||
@Column(name="CLIENT_ID", length = 36)
|
||||
protected String clientId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name="USER_ID")
|
||||
protected UserEntity user;
|
||||
|
||||
@Column(name="DATA")
|
||||
protected String data;
|
||||
|
||||
public String getClientSessionId() {
|
||||
return clientSessionId;
|
||||
}
|
||||
|
||||
public void setClientSessionId(String clientSessionId) {
|
||||
this.clientSessionId = clientSessionId;
|
||||
}
|
||||
|
||||
public String getUserSessionId() {
|
||||
return userSessionId;
|
||||
}
|
||||
|
||||
public void setUserSessionId(String userSessionId) {
|
||||
this.userSessionId = userSessionId;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public UserEntity getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserEntity user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="deleteOfflineUserSessionsByRealm", query="delete from OfflineUserSessionEntity sess where sess.user IN (select u from UserEntity u where u.realmId=:realmId)"),
|
||||
@NamedQuery(name="deleteOfflineUserSessionsByRealmAndLink", query="delete from OfflineUserSessionEntity sess where sess.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
|
||||
@NamedQuery(name="deleteDetachedOfflineUserSessions", query="delete from OfflineUserSessionEntity sess where sess.userSessionId NOT IN (select c.userSessionId from OfflineClientSessionEntity c)")
|
||||
})
|
||||
@Table(name="OFFLINE_USER_SESSION")
|
||||
@Entity
|
||||
public class OfflineUserSessionEntity {
|
||||
|
||||
@Id
|
||||
@Column(name="USER_SESSION_ID", length = 36)
|
||||
protected String userSessionId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name="USER_ID")
|
||||
protected UserEntity user;
|
||||
|
||||
@Column(name="DATA")
|
||||
protected String data;
|
||||
|
||||
public String getUserSessionId() {
|
||||
return userSessionId;
|
||||
}
|
||||
|
||||
public void setUserSessionId(String userSessionId) {
|
||||
this.userSessionId = userSessionId;
|
||||
}
|
||||
|
||||
public UserEntity getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserEntity user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
|
@ -37,6 +37,8 @@ public class RoleEntity {
|
|||
private String name;
|
||||
@Column(name = "DESCRIPTION")
|
||||
private String description;
|
||||
@Column(name = "SCOPE_PARAM_REQUIRED")
|
||||
private boolean scopeParamRequired;
|
||||
|
||||
// hax! couldn't get constraint to work properly
|
||||
@Column(name = "REALM_ID")
|
||||
|
@ -93,6 +95,14 @@ public class RoleEntity {
|
|||
this.description = description;
|
||||
}
|
||||
|
||||
public boolean isScopeParamRequired() {
|
||||
return scopeParamRequired;
|
||||
}
|
||||
|
||||
public void setScopeParamRequired(boolean scopeParamRequired) {
|
||||
this.scopeParamRequired = scopeParamRequired;
|
||||
}
|
||||
|
||||
public Collection<RoleEntity> getCompositeRoles() {
|
||||
return compositeRoles;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,13 @@ package org.keycloak.models.jpa.entities;
|
|||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
|
@ -14,6 +18,8 @@ import javax.persistence.UniqueConstraint;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -83,6 +89,12 @@ public class UserEntity {
|
|||
@Column(name="SERVICE_ACCOUNT_CLIENT_LINK")
|
||||
protected String serviceAccountClientLink;
|
||||
|
||||
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
|
||||
protected Collection<OfflineUserSessionEntity> offlineUserSessions = new ArrayList<>();
|
||||
|
||||
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
|
||||
protected Collection<OfflineClientSessionEntity> offlineClientSessions = new ArrayList<>();
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -212,6 +224,22 @@ public class UserEntity {
|
|||
this.serviceAccountClientLink = serviceAccountClientLink;
|
||||
}
|
||||
|
||||
public Collection<OfflineUserSessionEntity> getOfflineUserSessions() {
|
||||
return offlineUserSessions;
|
||||
}
|
||||
|
||||
public void setOfflineUserSessions(Collection<OfflineUserSessionEntity> offlineUserSessions) {
|
||||
this.offlineUserSessions = offlineUserSessions;
|
||||
}
|
||||
|
||||
public Collection<OfflineClientSessionEntity> getOfflineClientSessions() {
|
||||
return offlineClientSessions;
|
||||
}
|
||||
|
||||
public void setOfflineClientSessions(Collection<OfflineClientSessionEntity> offlineClientSessions) {
|
||||
this.offlineClientSessions = offlineClientSessions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -19,6 +19,8 @@ import org.keycloak.models.UserFederationProviderModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.entities.FederatedIdentityEntity;
|
||||
import org.keycloak.models.entities.OfflineClientSessionEntity;
|
||||
import org.keycloak.models.entities.OfflineUserSessionEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
|
||||
import org.keycloak.models.utils.CredentialValidation;
|
||||
|
@ -399,6 +401,36 @@ public class MongoUserProvider implements UserProvider {
|
|||
.and("clientId").is(client.getId())
|
||||
.get();
|
||||
getMongoStore().removeEntities(MongoUserConsentEntity.class, query, false, invocationContext);
|
||||
|
||||
// Remove all offlineClientSessions
|
||||
query = new QueryBuilder()
|
||||
.and("offlineUserSessions.offlineClientSessions.clientId").is(client.getId())
|
||||
.get();
|
||||
List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, query, invocationContext);
|
||||
for (MongoUserEntity user : users) {
|
||||
boolean anyRemoved = false;
|
||||
for (OfflineUserSessionEntity userSession : user.getOfflineUserSessions()) {
|
||||
for (OfflineClientSessionEntity clientSession : userSession.getOfflineClientSessions()) {
|
||||
if (clientSession.getClientId().equals(client.getId())) {
|
||||
userSession.getOfflineClientSessions().remove(clientSession);
|
||||
anyRemoved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it was last clientSession. Then remove userSession too
|
||||
if (userSession.getOfflineClientSessions().size() == 0) {
|
||||
user.getOfflineUserSessions().remove(userSession);
|
||||
anyRemoved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyRemoved) {
|
||||
getMongoStore().updateEntity(user, invocationContext);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -68,6 +68,17 @@ public class RoleAdapter extends AbstractMongoAdapter<MongoRoleEntity> implement
|
|||
updateRole();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScopeParamRequired() {
|
||||
return role.isScopeParamRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScopeParamRequired(boolean scopeParamRequired) {
|
||||
role.setScopeParamRequired(scopeParamRequired);
|
||||
updateRole();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComposite() {
|
||||
return role.getCompositeRoleIds() != null && role.getCompositeRoleIds().size() > 0;
|
||||
|
|
|
@ -8,6 +8,8 @@ import com.mongodb.QueryBuilder;
|
|||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.OTPPolicy;
|
||||
import org.keycloak.models.OfflineClientSessionModel;
|
||||
import org.keycloak.models.OfflineUserSessionModel;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -20,6 +22,8 @@ import org.keycloak.models.UserCredentialModel;
|
|||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.entities.CredentialEntity;
|
||||
import org.keycloak.models.entities.OfflineClientSessionEntity;
|
||||
import org.keycloak.models.entities.OfflineUserSessionEntity;
|
||||
import org.keycloak.models.entities.UserConsentEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
|
||||
|
@ -30,6 +34,7 @@ import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
|||
import org.keycloak.util.Time;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
@ -627,6 +632,145 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
|
|||
return getMongoStore().removeEntity(entity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineUserSession(OfflineUserSessionModel userSession) {
|
||||
if (user.getOfflineUserSessions() == null) {
|
||||
user.setOfflineUserSessions(new ArrayList<OfflineUserSessionEntity>());
|
||||
}
|
||||
|
||||
if (getUserSessionEntityById(userSession.getUserSessionId()) != null) {
|
||||
throw new ModelDuplicateException("User session already exists with id " + userSession.getUserSessionId() + " for user " + getMongoEntity().getUsername());
|
||||
}
|
||||
|
||||
OfflineUserSessionEntity entity = new OfflineUserSessionEntity();
|
||||
entity.setUserSessionId(userSession.getUserSessionId());
|
||||
entity.setData(userSession.getData());
|
||||
entity.setOfflineClientSessions(new ArrayList<OfflineClientSessionEntity>());
|
||||
user.getOfflineUserSessions().add(entity);
|
||||
updateUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineUserSessionModel getOfflineUserSession(String userSessionId) {
|
||||
OfflineUserSessionEntity entity = getUserSessionEntityById(userSessionId);
|
||||
return entity==null ? null : toModel(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineUserSessionModel> getOfflineUserSessions() {
|
||||
if (user.getOfflineUserSessions()==null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
List<OfflineUserSessionModel> result = new ArrayList<>();
|
||||
for (OfflineUserSessionEntity entity : user.getOfflineUserSessions()) {
|
||||
result.add(toModel(entity));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private OfflineUserSessionModel toModel(OfflineUserSessionEntity entity) {
|
||||
OfflineUserSessionModel model = new OfflineUserSessionModel();
|
||||
model.setUserSessionId(entity.getUserSessionId());
|
||||
model.setData(entity.getData());
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineUserSession(String userSessionId) {
|
||||
OfflineUserSessionEntity entity = getUserSessionEntityById(userSessionId);
|
||||
if (entity != null) {
|
||||
user.getOfflineUserSessions().remove(entity);
|
||||
updateUser();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private OfflineUserSessionEntity getUserSessionEntityById(String userSessionId) {
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity entity : user.getOfflineUserSessions()) {
|
||||
if (entity.getUserSessionId().equals(userSessionId)) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOfflineClientSession(OfflineClientSessionModel clientSession) {
|
||||
OfflineUserSessionEntity userSessionEntity = getUserSessionEntityById(clientSession.getUserSessionId());
|
||||
if (userSessionEntity == null) {
|
||||
throw new ModelException("OfflineUserSession with ID " + clientSession.getUserSessionId() + " doesn't exist for user " + getMongoEntity().getUsername());
|
||||
}
|
||||
|
||||
OfflineClientSessionEntity clEntity = new OfflineClientSessionEntity();
|
||||
clEntity.setClientSessionId(clientSession.getClientSessionId());
|
||||
clEntity.setClientId(clientSession.getClientId());
|
||||
clEntity.setData(clientSession.getData());
|
||||
|
||||
userSessionEntity.getOfflineClientSessions().add(clEntity);
|
||||
updateUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineClientSessionModel getOfflineClientSession(String clientSessionId) {
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity userSession : user.getOfflineUserSessions()) {
|
||||
for (OfflineClientSessionEntity clSession : userSession.getOfflineClientSessions()) {
|
||||
if (clSession.getClientSessionId().equals(clientSessionId)) {
|
||||
return toModel(clSession, userSession.getUserSessionId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private OfflineClientSessionModel toModel(OfflineClientSessionEntity cls, String userSessionId) {
|
||||
OfflineClientSessionModel model = new OfflineClientSessionModel();
|
||||
model.setClientSessionId(cls.getClientSessionId());
|
||||
model.setClientId(cls.getClientId());
|
||||
model.setData(cls.getData());
|
||||
model.setUserSessionId(userSessionId);
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OfflineClientSessionModel> getOfflineClientSessions() {
|
||||
List<OfflineClientSessionModel> result = new ArrayList<>();
|
||||
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity userSession : user.getOfflineUserSessions()) {
|
||||
for (OfflineClientSessionEntity clSession : userSession.getOfflineClientSessions()) {
|
||||
result.add(toModel(clSession, userSession.getUserSessionId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOfflineClientSession(String clientSessionId) {
|
||||
if (user.getOfflineUserSessions() != null) {
|
||||
for (OfflineUserSessionEntity userSession : user.getOfflineUserSessions()) {
|
||||
for (OfflineClientSessionEntity clSession : userSession.getOfflineClientSessions()) {
|
||||
if (clSession.getClientSessionId().equals(clientSessionId)) {
|
||||
userSession.getOfflineClientSessions().remove(clSession);
|
||||
updateUser();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -17,22 +17,18 @@
|
|||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-connections-infinispan</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.infinispan</groupId>
|
||||
<artifactId>infinispan-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
@ -109,6 +110,11 @@ public class UserSessionAdapter implements UserSessionModel {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getNotes() {
|
||||
return entity.getNotes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
return entity.getState();
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.keycloak.models.sessions.infinispan.compat.entities.UserSessionEntity
|
|||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
@ -144,5 +145,8 @@ public class UserSessionAdapter implements UserSessionModel {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, String> getNotes() {
|
||||
return entity.getNotes();
|
||||
}
|
||||
}
|
||||
|
|
112
pom.xml
112
pom.xml
|
@ -39,6 +39,7 @@
|
|||
<io.netty.version>4.0.26.Final</io.netty.version>
|
||||
<xnio.netty.netty-xnio-transport.version>0.1.1.Final</xnio.netty.netty-xnio-transport.version>
|
||||
<hibernate.javax.persistence.version>1.0.0.Final</hibernate.javax.persistence.version>
|
||||
<hibernate.javax.persistence.artifactId>hibernate-jpa-2.1-api</hibernate.javax.persistence.artifactId>
|
||||
<hibernate.entitymanager.version>4.3.10.Final</hibernate.entitymanager.version>
|
||||
<h2.version>1.4.187</h2.version>
|
||||
<mysql.version>5.1.29</mysql.version>
|
||||
|
@ -322,7 +323,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||
<artifactId>${hibernate.javax.persistence.artifactId}</artifactId>
|
||||
<version>${hibernate.javax.persistence.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -1253,6 +1254,15 @@
|
|||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<tagNameFormat>@{project.version}</tagNameFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
|
@ -1349,6 +1359,48 @@
|
|||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>distribution</id>
|
||||
<modules>
|
||||
<module>distribution</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>jboss-release</id>
|
||||
<modules>
|
||||
<module>docbook</module>
|
||||
<module>distribution</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>doclint-java8-disable</id>
|
||||
<activation>
|
||||
<jdk>[1.8,)</jdk>
|
||||
</activation>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>arquillian-integration-tests</id>
|
||||
<modules>
|
||||
<module>distribution</module>
|
||||
<module>testsuite/integration-arquillian</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<!-- Configure the JBoss Early Access Maven repository -->
|
||||
<profile>
|
||||
<id>jboss-earlyaccess-repository</id>
|
||||
|
@ -1382,63 +1434,5 @@
|
|||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>distribution</id>
|
||||
<modules>
|
||||
<module>distribution</module>
|
||||
<module>testsuite/integration-arquillian</module>
|
||||
</modules>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>jboss-release</id>
|
||||
<modules>
|
||||
<module>docbook</module>
|
||||
<module>distribution</module>
|
||||
<module>testsuite/integration-arquillian</module>
|
||||
</modules>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>aggregate</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>aggregate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minmemory>128m</minmemory>
|
||||
<maxmemory>1024m</maxmemory>
|
||||
<aggregate>true</aggregate>
|
||||
<excludePackageNames>
|
||||
se.unlogic.*:com.restfully.*:org.jboss.resteasy.examples.*:org.jboss.resteasy.tests.*
|
||||
</excludePackageNames>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>doclint-java8-disable</id>
|
||||
<activation>
|
||||
<jdk>[1.8,)</jdk>
|
||||
</activation>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
|
@ -27,8 +27,6 @@ import java.io.Serializable;
|
|||
*/
|
||||
public class CommonActionType implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String namespace;
|
||||
|
||||
protected String value;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue