diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/email-verification.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/email-verification.ftl
new file mode 100644
index 0000000000..eb7682a272
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/email-verification.ftl
@@ -0,0 +1,5 @@
+
+
+${msg("emailVerificationBodyHtml",link, linkExpiration, realmName)}
+
+
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-login_error.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-login_error.ftl
new file mode 100644
index 0000000000..d31410307c
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-login_error.ftl
@@ -0,0 +1,5 @@
+
+
+${msg("eventLoginErrorBodyHtml",event.date,event.ipAddress)}
+
+
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-remove_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-remove_totp.ftl
new file mode 100644
index 0000000000..91699ea349
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-remove_totp.ftl
@@ -0,0 +1,5 @@
+
+
+${msg("eventRemoveTotpBodyHtml",event.date, event.ipAddress)}
+
+
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_password.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_password.ftl
new file mode 100644
index 0000000000..8a6da60a50
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_password.ftl
@@ -0,0 +1,5 @@
+
+
+${msg("eventUpdatePasswordBodyHtml",event.date, event.ipAddress)}
+
+
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_totp.ftl
new file mode 100644
index 0000000000..c0190c7278
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_totp.ftl
@@ -0,0 +1,5 @@
+
+
+${msg("eventUpdateTotpBodyHtml",event.date, event.ipAddress)}
+
+
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/password-reset.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/password-reset.ftl
new file mode 100644
index 0000000000..846b45dafd
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/password-reset.ftl
@@ -0,0 +1,5 @@
+
+
+${msg("passwordResetBodyHtml",link, linkExpiration, realmName)}
+
+
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
index 0256640286..91337c4ee8 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
@@ -1,12 +1,18 @@
emailVerificationSubject=E-Mail verifizieren
passwordResetSubject=Passwort zur\u00FCckzusetzen
passwordResetBody=Jemand hat angefordert Ihr {2} Passwort zur\u00FCckzusetzen. Falls das Sie waren, dann klicken Sie auf den folgenden Link um das Passwort zur\u00FCckzusetzen.\n\n{0}\n\nDieser Link wird in {1} Minuten ablaufen.\n\nFalls Sie das Passwort nicht zur\u00FCcksetzen m\u00F6chten, dann k\u00F6nnen Sie diese E-Mail ignorieren.
+passwordResetBodyHtml=
Jemand hat angefordert Ihr {2} Passwort zur\u00FCckzusetzen. Falls das Sie waren, dann klicken Sie auf den folgenden Link um das Passwort zur\u00FCckzusetzen.
{0}
Dieser Link wird in {1} Minuten ablaufen.
Falls Sie das Passwort nicht zur\u00FCcksetzen m\u00F6chten, dann k\u00F6nnen Sie diese E-Mail ignorieren.
emailVerificationBody=Jemand hat ein {2} Konto mit dieser E-Mail Adresse erstellt. Fall das Sie waren, dann klicken Sie auf den Link um die E-Mail Adresse zu verifizieren.\n\n{0}\n\nDieser Link wird in {1} Minuten ablaufen.\n\nFalls Sie dieses Konto nicht erstellt haben, dann k\u00F6nnen sie diese Nachricht ignorieren.
+emailVerificationBodyHtml=
Jemand hat ein {2} Konto mit dieser E-Mail Adresse erstellt. Fall das Sie waren, dann klicken Sie auf den Link um die E-Mail Adresse zu verifizieren.
{0}
Dieser Link wird in {1} Minuten ablaufen.
Falls Sie dieses Konto nicht erstellt haben, dann k\u00F6nnen sie diese Nachricht ignorieren.
eventLoginErrorSubject=Fehlgeschlagene Anmeldung
eventLoginErrorBody=Jemand hat um {0} von {1} versucht sich mit ihrem Konto anzumelden. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventLoginErrorBodyHtml=
Jemand hat um {0} von {1} versucht sich mit ihrem Konto anzumelden. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
eventRemoveTotpSubject=TOTP Entfernt
eventRemoveTotpBody=TOTP wurde von ihrem Konto am {0} von {1} entfernt. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventRemoveTotpBodyHtml=
TOTP wurde von ihrem Konto am {0} von {1} entfernt. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
eventUpdatePasswordSubject=Passwort Aktualisiert
eventUpdatePasswordBody=Ihr Passwort wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventUpdatePasswordBodyHtml=
Ihr Passwort wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
eventUpdateTotpSubject=TOTP Aktualisiert
eventUpdateTotpBody=TOTP wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventUpdateTotpBodyHtml=
TOTP wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
index c0afc9ca91..7a3ac65499 100755
--- a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
@@ -1,12 +1,18 @@
emailVerificationSubject=Verify email
emailVerificationBody=Someone has created a {2} account with this email address. If this was you, click the link below to verify your email address\n\n{0}\n\nThis link will expire within {1} minutes.\n\nIf you didn''t create this account, just ignore this message.
+emailVerificationBodyHtml=
Someone has created a {2} account with this email address. If this was you, click the link below to verify your email address
{0}
This link will expire within {1} minutes.
If you didn''t create this account, just ignore this message.
passwordResetSubject=Reset password
passwordResetBody=Someone just requested to change your {2} account''s password. If this was you, click on the link below to set a new password\n\n{0}\n\nThis link will expire within {1} minutes.\n\nIf you don''t want to reset your password, just ignore this message and nothing will be changed.
+passwordResetBodyHtml=
Someone just requested to change your {2} account''s password. If this was you, click on the link below to set a new password
{0}
This link will expire within {1} minutes.
If you don''t want to reset your password, just ignore this message and nothing will be changed.
eventLoginErrorSubject=Login error
-eventLoginErrorBody=A failed login attempt was dettected to your account on {0} from {1}. If this was not you, please contact an admin.
+eventLoginErrorBody=A failed login attempt was detected to your account on {0} from {1}. If this was not you, please contact an admin.
+eventLoginErrorBodyHtml=
A failed login attempt was detected to your account on {0} from {1}. If this was not you, please contact an admin.
eventRemoveTotpSubject=Remove TOTP
eventRemoveTotpBody=TOTP was removed from your account on {0} from {1}. If this was not you, please contact an admin.
+eventRemoveTotpBodyHtml=
TOTP was removed from your account on {0} from {1}. If this was not you, please contact an admin.
eventUpdatePasswordSubject=Update password
eventUpdatePasswordBody=Your password was changed on {0} from {1}. If this was not you, please contact an admin.
+eventUpdatePasswordBodyHtml=
Your password was changed on {0} from {1}. If this was not you, please contact an admin.
eventUpdateTotpSubject=Update TOTP
-eventUpdateTotpBody=TOTP was updated for your account on {0} from {1}. If this was not you, please contact an admin.
\ No newline at end of file
+eventUpdateTotpBody=TOTP was updated for your account on {0} from {1}. If this was not you, please contact an admin.
+eventUpdateTotpBodyHtml=
TOTP was updated for your account on {0} from {1}. If this was not you, please contact an admin.
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties
index 0316e19009..fff7e10475 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties
@@ -1,12 +1,18 @@
emailVerificationSubject=Verifica\u00E7\u00E3o de e-mail
emailVerificationBody=Algu\u00E9m criou uma conta {2} com este endere\u00E7o de e-mail. Se foi voc\u00EA, clique no link abaixo para verificar o seu endere\u00E7o de email\n\n{0}\n\nEste link ir\u00E1 expirar dentro de {1} minutos.\n\nSe n\u00E3o foi voc\u00EA que criou esta conta, basta ignorar esta mensagem.
+emailVerificationBodyHtml=
Algu\u00E9m criou uma conta {2} com este endere\u00E7o de e-mail. Se foi voc\u00EA, clique no link abaixo para verificar o seu endere\u00E7o de email
{0}
Este link ir\u00E1 expirar dentro de {1} minutos.
Se n\u00E3o foi voc\u00EA que criou esta conta, basta ignorar esta mensagem.
passwordResetSubject=Redefini\u00E7\u00E3o de senha
passwordResetBody=Algu\u00E9m pediu para mudar a senha de sua conta {2}. Se foi voc\u00EA, clique no link abaixo para definir uma nova senha\n\n{0}\n\nEste link ir\u00E1 expirar dentro de {1} minutos.\n\nSe voc\u00EA n\u00E3o deseja redefinir sua senha, basta ignorar esta mensagem e nada ser\u00E1 mudado.
+passwordResetBodyHtml=
Algu\u00E9m pediu para mudar a senha de sua conta {2}. Se foi voc\u00EA, clique no link abaixo para definir uma nova senha
{0}
Este link ir\u00E1 expirar dentro de {1} minutos.
Se voc\u00EA n\u00E3o deseja redefinir sua senha, basta ignorar esta mensagem e nada ser\u00E1 mudado.
eventLoginErrorSubject=Erro de login
eventLoginErrorBody=Uma tentativa de login mal sucedida para a sua conta foi detectada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventLoginErrorBodyHtml=
Uma tentativa de login mal sucedida para a sua conta foi detectada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
eventRemoveTotpSubject=Remover TOTP
eventRemoveTotpBody=TOTP foi removido da sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventRemoveTotpBodyHtml=
TOTP foi removido da sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
eventUpdatePasswordSubject=Atualiza\u00E7\u00E3o de senha
eventUpdatePasswordBody=Sua senha foi alterada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventUpdatePasswordBodyHtml=
Sua senha foi alterada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
eventUpdateTotpSubject=Atualiza\u00E7\u00E3o TOTP
eventUpdateTotpBody=TOTP foi atualizado para a sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventUpdateTotpBodyHtml=
TOTP foi atualizado para a sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/email-verification.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/text/email-verification.ftl
similarity index 100%
rename from forms/common-themes/src/main/resources/theme/keycloak/email/email-verification.ftl
rename to forms/common-themes/src/main/resources/theme/keycloak/email/text/email-verification.ftl
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-login_error.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/text/event-login_error.ftl
similarity index 100%
rename from forms/common-themes/src/main/resources/theme/keycloak/email/event-login_error.ftl
rename to forms/common-themes/src/main/resources/theme/keycloak/email/text/event-login_error.ftl
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-remove_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/text/event-remove_totp.ftl
similarity index 100%
rename from forms/common-themes/src/main/resources/theme/keycloak/email/event-remove_totp.ftl
rename to forms/common-themes/src/main/resources/theme/keycloak/email/text/event-remove_totp.ftl
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_password.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/text/event-update_password.ftl
similarity index 100%
rename from forms/common-themes/src/main/resources/theme/keycloak/email/event-update_password.ftl
rename to forms/common-themes/src/main/resources/theme/keycloak/email/text/event-update_password.ftl
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/text/event-update_totp.ftl
similarity index 100%
rename from forms/common-themes/src/main/resources/theme/keycloak/email/event-update_totp.ftl
rename to forms/common-themes/src/main/resources/theme/keycloak/email/text/event-update_totp.ftl
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/password-reset.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/text/password-reset.ftl
similarity index 100%
rename from forms/common-themes/src/main/resources/theme/keycloak/email/password-reset.ftl
rename to forms/common-themes/src/main/resources/theme/keycloak/email/text/password-reset.ftl
diff --git a/forms/email-api/src/main/java/org/keycloak/email/EmailSpi.java b/forms/email-api/src/main/java/org/keycloak/email/EmailSpi.java
index cde73cec0f..8d085336c6 100644
--- a/forms/email-api/src/main/java/org/keycloak/email/EmailSpi.java
+++ b/forms/email-api/src/main/java/org/keycloak/email/EmailSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class EmailSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java b/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
index 95f55f3674..79080de2c2 100755
--- a/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
+++ b/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
@@ -1,11 +1,28 @@
package org.keycloak.email.freemarker;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.mail.Message;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
import org.jboss.logging.Logger;
import org.keycloak.email.EmailException;
import org.keycloak.email.EmailProvider;
import org.keycloak.email.freemarker.beans.EventBean;
import org.keycloak.events.Event;
import org.keycloak.events.EventType;
+import org.keycloak.freemarker.FreeMarkerException;
import org.keycloak.freemarker.FreeMarkerUtil;
import org.keycloak.freemarker.LocaleHelper;
import org.keycloak.freemarker.Theme;
@@ -15,14 +32,6 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
-import javax.mail.Message;
-import javax.mail.Session;
-import javax.mail.Transport;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-import java.text.MessageFormat;
-import java.util.*;
-
/**
* @author
Stian Thorgersen
*/
@@ -93,16 +102,29 @@ public class FreeMarkerEmailProvider implements EmailProvider {
Properties rb = theme.getMessages(locale);
attributes.put("msg", new MessageFormatterMethod(locale, rb));
String subject = new MessageFormat(rb.getProperty(subjectKey,subjectKey),locale).format(new Object[0]);
- String body = freeMarker.processTemplate(attributes, template, theme);
+ String textTemplate = String.format("text/%s", template);
+ String textBody;
+ try {
+ textBody = freeMarker.processTemplate(attributes, textTemplate, theme);
+ } catch (final FreeMarkerException e ) {
+ textBody = null;
+ }
+ String htmlTemplate = String.format("html/%s", template);
+ String htmlBody;
+ try {
+ htmlBody = freeMarker.processTemplate(attributes, htmlTemplate, theme);
+ } catch (final FreeMarkerException e ) {
+ htmlBody = null;
+ }
- send(subject, body);
+ send(subject, textBody, htmlBody);
} catch (Exception e) {
throw new EmailException("Failed to template email", e);
}
}
- private void send(String subject, String body) throws EmailException {
+ private void send(String subject, String textBody, String htmlBody) throws EmailException {
try {
String address = user.getEmail();
Map
config = realm.getSmtpConfig();
@@ -135,11 +157,25 @@ public class FreeMarkerEmailProvider implements EmailProvider {
Session session = Session.getInstance(props);
+ Multipart multipart = new MimeMultipart("alternative");
+
+ if(textBody != null) {
+ MimeBodyPart textPart = new MimeBodyPart();
+ textPart.setText(textBody, "UTF-8");
+ multipart.addBodyPart(textPart);
+ }
+
+ if(htmlBody != null) {
+ MimeBodyPart htmlPart = new MimeBodyPart();
+ htmlPart.setContent(htmlBody, "text/html; charset=UTF-8");
+ multipart.addBodyPart(htmlPart);
+ }
+
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.setHeader("To", address);
msg.setSubject(subject);
- msg.setText(body);
+ msg.setContent(multipart);
msg.saveChanges();
msg.setSentDate(new Date());
diff --git a/forms/login-api/src/main/java/org/keycloak/login/LoginFormsSpi.java b/forms/login-api/src/main/java/org/keycloak/login/LoginFormsSpi.java
index f99292aeb1..dc18703b70 100644
--- a/forms/login-api/src/main/java/org/keycloak/login/LoginFormsSpi.java
+++ b/forms/login-api/src/main/java/org/keycloak/login/LoginFormsSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class LoginFormsSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
index a1a68dfce9..1ff7b15415 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
@@ -136,7 +136,7 @@ public class BearerTokenRequestAuthenticator {
return new AuthChallenge() {
@Override
public boolean errorPage() {
- return false;
+ return true;
}
@Override
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java
index 7f86d7981b..8f3a59d641 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java
@@ -14,14 +14,8 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-
package org.keycloak.subsystem.server.extension;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
-
/**
* This service keeps track of the entire Keycloak management model so as to provide
* adapter configuration to each deployment at deploy time.
@@ -30,37 +24,25 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD
*/
public final class KeycloakAdapterConfigService {
- private static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
+ static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
- public static KeycloakAdapterConfigService getInstance() {
- return INSTANCE;
- }
-
- // key=auth-server deployment name; value=web-context
- private final Map webContexts = new HashMap();
+ static final String DEPLOYMENT_NAME = "keycloak-server";
+ private String webContext;
private KeycloakAdapterConfigService() {
}
- public void addServerDeployment(String deploymentName, String webContext) {
- this.webContexts.put(deploymentName, webContext);
+ void setWebContext(String webContext) {
+ this.webContext = webContext;
}
- public String getWebContext(String deploymentName) {
- return webContexts.get(deploymentName);
+ String getWebContext() {
+ return webContext;
}
- public void removeServerDeployment(String deploymentName) {
- this.webContexts.remove(deploymentName);
- }
-
- public boolean isWebContextUsed(String webContext) {
- return webContexts.containsValue(webContext);
- }
-
- public boolean isKeycloakServerDeployment(String deploymentName) {
- return this.webContexts.containsKey(deploymentName);
+ boolean isKeycloakServerDeployment(String deploymentName) {
+ return DEPLOYMENT_NAME.equals(deploymentName);
}
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java
index 145b475653..cf1a4d7326 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java
@@ -24,11 +24,9 @@ import org.jboss.as.controller.ResourceDefinition;
import org.jboss.as.controller.SubsystemRegistration;
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
import org.jboss.as.controller.parsing.ExtensionParsingContext;
-import org.jboss.as.controller.registry.ManagementResourceRegistration;
-import org.keycloak.subsystem.server.extension.authserver.AuthServerDefinition;
-import org.keycloak.subsystem.server.logging.KeycloakLogger;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
+import static org.keycloak.subsystem.server.logging.KeycloakLogger.ROOT_LOGGER;
/**
@@ -38,17 +36,16 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUB
*/
public class KeycloakExtension implements Extension {
- public static final String SUBSYSTEM_NAME = "keycloak-server";
- public static final String NAMESPACE = "urn:jboss:domain:keycloak-server:1.1";
- private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
+ static final String SUBSYSTEM_NAME = "keycloak-server";
+ static final String NAMESPACE = "urn:jboss:domain:keycloak-server:1.1";
static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
- private static final String RESOURCE_NAME = KeycloakExtension.class.getPackage().getName() + ".LocalDescriptions";
- private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1,1,0);
- static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
- private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
- static final AuthServerDefinition AUTH_SERVER_DEFINITION = new AuthServerDefinition();
- public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
+ private static final String RESOURCE_NAME = KeycloakExtension.class.getPackage().getName() + ".LocalDescriptions";
+ private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
+ private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
+ private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1,1,0);
+
+ static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
for (String kp : keyPrefix) {
prefix.append('.').append(kp);
@@ -61,7 +58,7 @@ public class KeycloakExtension implements Extension {
*/
@Override
public void initializeParsers(final ExtensionParsingContext context) {
- context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakExtension.NAMESPACE, PARSER);
+ context.setSubsystemXmlMapping(SUBSYSTEM_NAME, NAMESPACE, PARSER);
}
/**
@@ -69,11 +66,10 @@ public class KeycloakExtension implements Extension {
*/
@Override
public void initialize(final ExtensionContext context) {
- KeycloakLogger.ROOT_LOGGER.debug("Activating Keycloak Extension");
+ ROOT_LOGGER.debug("Activating Keycloak Extension");
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, MGMT_API_VERSION);
- ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
- registration.registerSubModel(AUTH_SERVER_DEFINITION);
+ subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
subsystem.registerXMLElementWriter(PARSER);
}
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/KeycloakServerDeploymentProcessor.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
similarity index 81%
rename from integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/KeycloakServerDeploymentProcessor.java
rename to integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
index 80401cc795..e951c7fd6b 100644
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/KeycloakServerDeploymentProcessor.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
@@ -14,14 +14,13 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.keycloak.subsystem.server.extension.authserver;
+package org.keycloak.subsystem.server.extension;
import org.jboss.as.ee.component.EEModuleDescription;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
-import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
/**
* DUP responsible for setting the web context of a Keycloak auth server.
@@ -33,22 +32,22 @@ public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcesso
@Override
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
+ KeycloakAdapterConfigService config = KeycloakAdapterConfigService.INSTANCE;
String deploymentName = deploymentUnit.getName();
- KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
- if (!service.isKeycloakServerDeployment(deploymentName)) {
+
+ if (!config.isKeycloakServerDeployment(deploymentName)) {
return;
}
final EEModuleDescription description = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
- String webContext = service.getWebContext(deploymentName);
+ String webContext = config.getWebContext();
if (webContext == null) {
- throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Auth Server");
+ throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Server");
}
description.setModuleName(webContext);
}
@Override
public void undeploy(DeploymentUnit du) {
-
}
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java
index 4f0dde9c78..7038408f3b 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java
@@ -17,13 +17,18 @@
package org.keycloak.subsystem.server.extension;
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
+import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.registry.Resource;
import org.jboss.as.server.AbstractDeploymentChainStep;
import org.jboss.as.server.DeploymentProcessorTarget;
import org.jboss.as.server.deployment.Phase;
import org.jboss.dmr.ModelNode;
-import org.keycloak.subsystem.server.extension.authserver.KeycloakServerDeploymentProcessor;
+import static org.keycloak.subsystem.server.extension.KeycloakExtension.SUBSYSTEM_NAME;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.ALL_ATTRIBUTES;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.WEB_CONTEXT;
/**
* The Keycloak subsystem add update handler.
@@ -35,15 +40,44 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
static final KeycloakSubsystemAdd INSTANCE = new KeycloakSubsystemAdd();
@Override
- protected void performBoottime(final OperationContext context, ModelNode operation, final ModelNode model) {
+ protected void performBoottime(final OperationContext context, final ModelNode operation, final ModelNode model) {
context.addStep(new AbstractDeploymentChainStep() {
@Override
protected void execute(DeploymentProcessorTarget processorTarget) {
- processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME,
+ processorTarget.addDeploymentProcessor(SUBSYSTEM_NAME,
Phase.POST_MODULE, // PHASE
Phase.POST_MODULE_VALIDATOR_FACTORY - 1, // PRIORITY
new KeycloakServerDeploymentProcessor());
}
}, OperationContext.Stage.RUNTIME);
}
+
+ protected void populateModel(final OperationContext context, final ModelNode operation, final Resource resource) throws OperationFailedException {
+ ModelNode model = resource.getModel();
+
+ // set attribute values from parsed model
+ for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
+ attrDef.validateAndSet(operation, model);
+ }
+
+ // returns early if on domain controller
+ if (!requiresRuntime(context)) {
+ return;
+ }
+
+ // don't want to try to start server on host controller
+ if (!context.isNormalServer()) {
+ return;
+ }
+
+ ModelNode webContextNode = resource.getModel().get(WEB_CONTEXT.getName());
+ if (!webContextNode.isDefined()) {
+ webContextNode = WEB_CONTEXT.getDefaultValue();
+ }
+ String webContext = webContextNode.asString();
+
+ ServerUtil serverUtil = new ServerUtil(operation);
+ serverUtil.addStepToUploadServerWar(context);
+ KeycloakAdapterConfigService.INSTANCE.setWebContext(webContext);
+ }
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java
index f553188251..25ed28a24c 100644
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java
@@ -14,25 +14,56 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-
package org.keycloak.subsystem.server.extension;
-import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
import org.jboss.as.controller.SimpleResourceDefinition;
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
- * Definition of subsystem=keycloak.
+ * Definition of subsystem=keycloak-server.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
*/
public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
+
+ static final SimpleAttributeDefinition WEB_CONTEXT =
+ new SimpleAttributeDefinitionBuilder("web-context", ModelType.STRING, true)
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode("auth"))
+ .setRestartAllServices()
+ .build();
+
+ static final List ALL_ATTRIBUTES = new ArrayList();
+
+ static {
+ ALL_ATTRIBUTES.add(WEB_CONTEXT);
+ }
+
+ private static final Map DEFINITION_LOOKUP = new HashMap();
+ static {
+ for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
+ DEFINITION_LOOKUP.put(def.getXmlName(), def);
+ }
+ }
+
+ private static KeycloakSubsystemWriteAttributeHandler attrHandler = new KeycloakSubsystemWriteAttributeHandler(ALL_ATTRIBUTES);
+
protected KeycloakSubsystemDefinition() {
- super(KeycloakExtension.SUBSYSTEM_PATH,
- KeycloakExtension.getResourceDescriptionResolver("subsystem"),
- KeycloakSubsystemAdd.INSTANCE,
- ReloadRequiredRemoveStepHandler.INSTANCE
+ super(KeycloakExtension.PATH_SUBSYSTEM,
+ KeycloakExtension.getResourceDescriptionResolver("subsystem"),
+ KeycloakSubsystemAdd.INSTANCE,
+ KeycloakSubsystemRemoveHandler.INSTANCE
);
}
@@ -42,4 +73,15 @@ public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
}
+ @Override
+ public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+ super.registerAttributes(resourceRegistration);
+ for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
+ resourceRegistration.registerReadWriteAttribute(attrDef, null, attrHandler);
+ }
+ }
+
+ public static SimpleAttributeDefinition lookup(String name) {
+ return DEFINITION_LOOKUP.get(name);
+ }
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java
index 921c576dd6..53d35db779 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java
@@ -16,17 +16,11 @@
*/
package org.keycloak.subsystem.server.extension;
-import org.keycloak.subsystem.server.extension.authserver.AuthServerDefinition;
-import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.PathAddress;
-import org.jboss.as.controller.PathElement;
-import org.jboss.as.controller.SimpleAttributeDefinition;
-import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.controller.parsing.ParseUtils;
import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
import org.jboss.dmr.ModelNode;
-import org.jboss.dmr.Property;
import org.jboss.staxmapper.XMLElementReader;
import org.jboss.staxmapper.XMLElementWriter;
import org.jboss.staxmapper.XMLExtendedStreamReader;
@@ -34,9 +28,11 @@ import org.jboss.staxmapper.XMLExtendedStreamWriter;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
-import java.util.Collections;
import java.util.List;
+import static org.keycloak.subsystem.server.extension.KeycloakExtension.PATH_SUBSYSTEM;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.WEB_CONTEXT;
+
/**
* The subsystem parser, which uses stax to read and write to and from xml
*/
@@ -49,12 +45,14 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader list) throws XMLStreamException {
// Require no attributes
ParseUtils.requireNoAttributes(reader);
- ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(KeycloakExtension.PATH_SUBSYSTEM));
+ ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(PATH_SUBSYSTEM));
list.add(addKeycloakSub);
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
- if (reader.getLocalName().equals(AuthServerDefinition.TAG_NAME)) {
- readAuthServer(reader, list);
+ if (reader.getLocalName().equals(WEB_CONTEXT.getXmlName())) {
+ WEB_CONTEXT.parseAndSetParameter(reader.getElementText(), addKeycloakSub, reader);
+ } else {
+ throw new XMLStreamException("Unknown keycloak-server subsystem tag: " + reader.getLocalName());
}
}
}
@@ -64,64 +62,21 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader list) throws XMLStreamException {
- String authServerName = readNameAttribute(reader);
- ModelNode addAuthServer = new ModelNode();
- addAuthServer.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
- PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
- PathElement.pathElement(AuthServerDefinition.TAG_NAME, authServerName));
- addAuthServer.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
-
- while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
- String tagName = reader.getLocalName();
- SimpleAttributeDefinition def = AuthServerDefinition.lookup(tagName);
- if (def == null) throw new XMLStreamException("Unknown auth-server tag " + tagName);
- def.parseAndSetParameter(reader.getElementText(), addAuthServer, reader);
- }
-
- list.add(addAuthServer);
- }
-
- // expects that the current tag will have one single attribute called "name"
- private String readNameAttribute(XMLExtendedStreamReader reader) throws XMLStreamException {
- String name = null;
- for (int i = 0; i < reader.getAttributeCount(); i++) {
- String attr = reader.getAttributeLocalName(i);
- if (attr.equals("name")) {
- name = reader.getAttributeValue(i);
- continue;
- }
- throw ParseUtils.unexpectedAttribute(reader, i);
- }
- if (name == null) {
- throw ParseUtils.missingRequired(reader, Collections.singleton("name"));
- }
- return name;
- }
-
/**
* {@inheritDoc}
*/
@Override
public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
context.startSubsystemElement(KeycloakExtension.NAMESPACE, false);
- writeAuthServers(writer, context);
+ writeWebContext(writer, context);
writer.writeEndElement();
}
- private void writeAuthServers(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
- if (!context.getModelNode().get(AuthServerDefinition.TAG_NAME).isDefined()) {
+ private void writeWebContext(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
+ if (!context.getModelNode().get(WEB_CONTEXT.getName()).isDefined()) {
return;
}
- for (Property authServer : context.getModelNode().get(AuthServerDefinition.TAG_NAME).asPropertyList()) {
- writer.writeStartElement(AuthServerDefinition.TAG_NAME);
- writer.writeAttribute("name", authServer.getName());
- ModelNode authServerElements = authServer.getValue();
- for (AttributeDefinition element : AuthServerDefinition.ALL_ATTRIBUTES) {
- element.marshallAsElement(authServerElements, writer);
- }
- writer.writeEndElement();
- }
+ WEB_CONTEXT.marshallAsElement(context.getModelNode(), writer);
}
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerRemoveHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemRemoveHandler.java
similarity index 76%
rename from integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerRemoveHandler.java
rename to integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemRemoveHandler.java
index 05695ca582..4a1bdfcc40 100644
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerRemoveHandler.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemRemoveHandler.java
@@ -14,18 +14,16 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
+package org.keycloak.subsystem.server.extension;
-package org.keycloak.subsystem.server.extension.authserver;
-
-import org.jboss.as.controller.AbstractRemoveStepHandler;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationStepHandler;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.dmr.ModelNode;
-import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
@@ -36,25 +34,25 @@ import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
*
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
*/
-public final class AuthServerRemoveHandler extends AbstractRemoveStepHandler {
+public final class KeycloakSubsystemRemoveHandler extends ReloadRequiredRemoveStepHandler {
- public static AuthServerRemoveHandler INSTANCE = new AuthServerRemoveHandler();
+ static KeycloakSubsystemRemoveHandler INSTANCE = new KeycloakSubsystemRemoveHandler();
- private AuthServerRemoveHandler() {}
+ private KeycloakSubsystemRemoveHandler() {}
@Override
protected void performRemove(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
- String deploymentName = AuthServerUtil.getDeploymentName(operation);
- KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName);
+ String deploymentName = ServerUtil.getDeploymentName(operation);
+ KeycloakAdapterConfigService.INSTANCE.setWebContext(null);
if (requiresRuntime(context)) { // don't do this on a domain controller
- addStepToRemoveAuthServer(context, deploymentName);
+ addStepToRemoveServerWar(context, deploymentName);
}
super.performRemove(context, operation, model);
}
- private void addStepToRemoveAuthServer(OperationContext context, String deploymentName) {
+ private void addStepToRemoveServerWar(OperationContext context, String deploymentName) {
PathAddress deploymentAddress = PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName));
ModelNode op = Util.createOperation(REMOVE, deploymentAddress);
context.addStep(op, getRemoveHandler(context, deploymentAddress), OperationContext.Stage.MODEL);
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerWriteAttributeHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemWriteAttributeHandler.java
similarity index 55%
rename from integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerWriteAttributeHandler.java
rename to integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemWriteAttributeHandler.java
index 3fd16cc6fc..ecba429323 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerWriteAttributeHandler.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemWriteAttributeHandler.java
@@ -14,8 +14,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-
-package org.keycloak.subsystem.server.extension.authserver;
+package org.keycloak.subsystem.server.extension;
import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.SimpleAttributeDefinition;
@@ -26,20 +25,19 @@ import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.registry.Resource;
import org.jboss.dmr.ModelNode;
-import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
/**
* Update an attribute on an Auth Server.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
*/
-public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHandler { //extends ReloadRequiredWriteAttributeHandler {
+public class KeycloakSubsystemWriteAttributeHandler extends ModelOnlyWriteAttributeHandler { //extends ReloadRequiredWriteAttributeHandler {
- public AuthServerWriteAttributeHandler(List definitions) {
+ public KeycloakSubsystemWriteAttributeHandler(List definitions) {
this(definitions.toArray(new AttributeDefinition[definitions.size()]));
}
- public AuthServerWriteAttributeHandler(AttributeDefinition... definitions) {
+ public KeycloakSubsystemWriteAttributeHandler(AttributeDefinition... definitions) {
super(definitions);
}
@@ -50,34 +48,24 @@ public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHand
return;
}
- boolean isEnabled = AuthServerDefinition.ENABLED.resolveModelAttribute(context, model.getModel()).asBoolean();
- String deploymentName = AuthServerUtil.getDeploymentName(operation);
+ String deploymentName = ServerUtil.getDeploymentName(operation);
- if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) {
-
- KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName);
- KeycloakAdapterConfigService.getInstance().addServerDeployment(deploymentName, newValue.asString());
- if (isEnabled) {
- AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
- }
- }
-
- if (attributeName.equals(AuthServerDefinition.ENABLED.getName())) {
- if (!isEnabled) { // we are disabling
- AuthServerUtil.addStepToUndeployAuthServer(context, deploymentName);
- } else { // we are enabling
- AuthServerUtil.addStepToDeployAuthServer(context, deploymentName);
- }
+ if (attributeName.equals(KeycloakSubsystemDefinition.WEB_CONTEXT.getName())) {
+ KeycloakAdapterConfigService.INSTANCE.setWebContext(newValue.asString());
+ ServerUtil.addStepToRedeployServerWar(context, deploymentName);
}
super.finishModelStage(context, operation, attributeName, newValue, oldValue, model);
}
private boolean attribNotChanging(String attributeName, ModelNode newValue, ModelNode oldValue) {
- SimpleAttributeDefinition attribDef = AuthServerDefinition.lookup(attributeName);
- if (!oldValue.isDefined()) oldValue = attribDef.getDefaultValue();
- if (!newValue.isDefined()) newValue = attribDef.getDefaultValue();
+ SimpleAttributeDefinition attribDef = KeycloakSubsystemDefinition.lookup(attributeName);
+ if (!oldValue.isDefined()) {
+ oldValue = attribDef.getDefaultValue();
+ }
+ if (!newValue.isDefined()) {
+ newValue = attribDef.getDefaultValue();
+ }
return newValue.equals(oldValue);
}
-
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerUtil.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ServerUtil.java
similarity index 64%
rename from integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerUtil.java
rename to integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ServerUtil.java
index 6814aa7df1..2911afe10f 100644
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerUtil.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ServerUtil.java
@@ -14,7 +14,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.keycloak.subsystem.server.extension.authserver;
+package org.keycloak.subsystem.server.extension;
import java.io.File;
import java.net.URI;
@@ -29,50 +29,42 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ARCHIVE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOY;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PERSISTENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REDEPLOY;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNTIME_NAME;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.UNDEPLOY;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
-import org.jboss.as.controller.registry.Resource;
+
import org.jboss.dmr.ModelNode;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
-import org.keycloak.subsystem.server.extension.KeycloakExtension;
/**
* Utility methods that help assemble and start an auth server.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
*/
-public class AuthServerUtil {
+public class ServerUtil {
private static final ModuleIdentifier KEYCLOAK_SUBSYSTEM = ModuleIdentifier.create("org.keycloak.keycloak-server-subsystem");
private final String deploymentName;
private final Module subsysModule;
private final String keycloakVersion;
- private final boolean isAuthServerExploded;
- private final URI authServerUri;
+ private final boolean isServerWarExploded;
+ private final URI serverWar;
- AuthServerUtil(ModelNode operation) {
+ ServerUtil(ModelNode operation) {
this.deploymentName = getDeploymentName(operation);
this.subsysModule = findSubsysModule();
this.keycloakVersion = subsysModule.getProperty("keycloak-version");
- this.isAuthServerExploded = Boolean.parseBoolean(subsysModule.getProperty("auth-server-exploded"));
- this.authServerUri = findAuthServerUri();
- }
-
- String getDeploymentName() {
- return this.deploymentName;
+ this.isServerWarExploded = Boolean.parseBoolean(subsysModule.getProperty("server-war-exploded"));
+ this.serverWar = findServerWarUri();
}
private Module findSubsysModule() {
@@ -83,15 +75,15 @@ public class AuthServerUtil {
}
}
- private URI findAuthServerUri() throws IllegalStateException {
+ private URI findServerWarUri() throws IllegalStateException {
try {
URL subsysResource = this.subsysModule.getExportedResource("module.xml");
File subsysDir = new File(subsysResource.toURI()).getParentFile();
- File authServerDir = new File(subsysDir, "auth-server");
- if (this.isAuthServerExploded) {
- return authServerDir.toURI();
+ File serverWarDir = new File(subsysDir, "server-war");
+ if (this.isServerWarExploded) {
+ return serverWarDir.toURI();
} else {
- return new File(authServerDir, "keycloak-server-" + keycloakVersion + ".war").toURI();
+ return new File(serverWarDir, "keycloak-server-" + keycloakVersion + ".war").toURI();
}
} catch (URISyntaxException e) {
throw new IllegalStateException(e);
@@ -100,17 +92,21 @@ public class AuthServerUtil {
}
}
- void addStepToUploadAuthServer(OperationContext context, boolean isEnabled) throws OperationFailedException {
+ void addStepToUploadServerWar(OperationContext context) throws OperationFailedException {
PathAddress deploymentAddress = deploymentAddress(deploymentName);
ModelNode op = Util.createOperation(ADD, deploymentAddress);
- op.get(ENABLED).set(isEnabled);
- op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml
+
+ // this is required for deployment to take place
+ op.get(ENABLED).set(true);
+
+ // prevents writing this deployment out to standalone.xml
+ op.get(PERSISTENT).set(false);
// Owner attribute is valid starting with WidlFly 9. Ignored in WildFly 8
op.get("owner").set(new ModelNode().add("subsystem", KeycloakExtension.SUBSYSTEM_NAME));
- if (authServerUri == null) {
- throw new OperationFailedException("Keycloak Auth Server WAR not found in keycloak-server-subsystem module");
+ if (serverWar == null) {
+ throw new OperationFailedException("Keycloak Server WAR not found in keycloak-server-subsystem module");
}
op.get(CONTENT).add(makeContentItem());
@@ -121,32 +117,26 @@ public class AuthServerUtil {
private ModelNode makeContentItem() throws OperationFailedException {
ModelNode contentItem = new ModelNode();
- if (this.isAuthServerExploded) {
- String urlString = new File(authServerUri).getAbsolutePath();
+ if (this.isServerWarExploded) {
+ String urlString = new File(serverWar).getAbsolutePath();
contentItem.get(PATH).set(urlString);
contentItem.get(ARCHIVE).set(false);
} else {
- String urlString = authServerUri.toString();
+ String urlString = serverWar.toString();
contentItem.get(URL).set(urlString);
}
return contentItem;
}
- static void addStepToRedeployAuthServer(OperationContext context, String deploymentName) {
+ static void addStepToRedeployServerWar(OperationContext context, String deploymentName) {
addDeploymentAction(context, REDEPLOY, deploymentName);
}
- static void addStepToUndeployAuthServer(OperationContext context, String deploymentName) {
- addDeploymentAction(context, UNDEPLOY, deploymentName);
- }
-
- static void addStepToDeployAuthServer(OperationContext context, String deploymentName) {
- addDeploymentAction(context, DEPLOY, deploymentName);
- }
-
private static void addDeploymentAction(OperationContext context, String operation, String deploymentName) {
- if (!context.isNormalServer()) return;
+ if (!context.isNormalServer()) {
+ return;
+ }
PathAddress deploymentAddress = deploymentAddress(deploymentName);
ModelNode op = Util.createOperation(operation, deploymentAddress);
op.get(RUNTIME_NAME).set(deploymentName);
@@ -170,27 +160,4 @@ public class AuthServerUtil {
return deploymentName;
}
-
- static String getAuthServerName(ModelNode operation) {
- PathAddress pathAddr = getPathAddress(operation);
- return pathAddr.getElement(pathAddr.size() - 1).getValue();
- }
-
- static PathAddress getPathAddress(ModelNode operation) {
- return PathAddress.pathAddress(operation.get(ADDRESS));
- }
-
- static PathAddress getOverlayAddress(String overlayName) {
- return PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT_OVERLAY, overlayName));
- }
-
- static String getOverlayName(ModelNode operation) {
- return AuthServerUtil.getAuthServerName(operation) + "-keycloak-overlay";
- }
-
- static boolean isOverlayExists(OperationContext context, String overlayName, PathAddress address) {
- Resource resource = context.readResourceFromRoot(address);
- return resource.getChildrenNames(DEPLOYMENT_OVERLAY).contains(overlayName);
- }
-
}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AbstractAddOverlayHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AbstractAddOverlayHandler.java
deleted file mode 100644
index 7bf620f3d9..0000000000
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AbstractAddOverlayHandler.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.keycloak.subsystem.server.extension.authserver;
-
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
-
-import java.util.Set;
-
-import org.jboss.as.controller.AbstractAddStepHandler;
-import org.jboss.as.controller.OperationContext;
-import org.jboss.as.controller.OperationFailedException;
-import org.jboss.as.controller.PathAddress;
-import org.jboss.as.controller.ProcessType;
-import org.jboss.as.controller.SimpleAttributeDefinition;
-import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
-import org.jboss.as.controller.operations.common.Util;
-import org.jboss.as.controller.registry.Resource;
-import org.jboss.dmr.ModelNode;
-import org.jboss.dmr.ModelType;
-
-/**
- * Base class for operations that create overlays for an auth server.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- */
-public abstract class AbstractAddOverlayHandler extends AbstractAddStepHandler{
-
- protected static final String UPLOADED_FILE_OP_NAME = "uploaded-file-name";
- protected static final SimpleAttributeDefinition UPLOADED_FILE_NAME =new SimpleAttributeDefinitionBuilder(UPLOADED_FILE_OP_NAME, ModelType.STRING, false)
- .setAllowExpression(false)
- .setAllowNull(false)
- .build();
-
- protected static final SimpleAttributeDefinition BYTES_TO_UPLOAD= new SimpleAttributeDefinitionBuilder("bytes-to-upload", ModelType.BYTES, false)
- .setAllowExpression(false)
- .build();
-
- static final SimpleAttributeDefinition REDEPLOY_SERVER =
- new SimpleAttributeDefinitionBuilder("redeploy", ModelType.BOOLEAN, true)
- .setAllowExpression(true)
- .setDefaultValue(new ModelNode(false))
- .build();
-
- protected static final SimpleAttributeDefinition OVERWRITE =
- new SimpleAttributeDefinitionBuilder("overwrite", ModelType.BOOLEAN, true)
- .setAllowExpression(true)
- .setDefaultValue(new ModelNode(false))
- .build();
-
- public AbstractAddOverlayHandler() {
- super(AddProviderHandler.DEFINITION.getParameters());
- }
-
- @Override
- protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
- final String uploadFileName = UPLOADED_FILE_NAME.resolveModelAttribute(context, model).asString();
- final boolean isRedeploy = isRedeploy(context, operation);
- final boolean isOverwrite = OVERWRITE.resolveModelAttribute(context, model).asBoolean();
-
- String overlayPath = getOverlayPath(uploadFileName);
- String overlayName = AuthServerUtil.getOverlayName(operation);
- PathAddress overlayAddress = AuthServerUtil.getOverlayAddress(overlayName);
- String deploymentName = AuthServerUtil.getDeploymentName(operation);
-
- boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
- if (!isOverlayExists) {
- addOverlay(context, overlayAddress);
- if (!isHostController(context)) {
- addDeploymentToOverlay(context, overlayAddress, deploymentName);
- }
- }
-
- if (isHostController(context)) {
- addOverlayToServerGroups(context, overlayAddress, operation, overlayName);
- }
-
- if (isOverlayExists && isContentExists(context, overlayAddress, overlayPath)) {
- if (isOverwrite) {
- removeContent(context, overlayAddress, overlayPath);
- } else {
- throw new OperationFailedException(pathExistsMessage(overlayAddress, overlayPath));
- }
- }
-
- addContent(context, overlayAddress, BYTES_TO_UPLOAD.resolveModelAttribute(context, model).asBytes(), overlayPath);
-
- if (isRedeploy) { AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName); }
- if (!isRedeploy) { context.restartRequired(); }
- context.completeStep(OperationContext.ResultHandler.NOOP_RESULT_HANDLER);
- }
-
- static void removeContent(OperationContext context, PathAddress overlayAddress, String overlayPath) {
- PathAddress contentAddress = overlayAddress.append("content", overlayPath);
- ModelNode operation = Util.createRemoveOperation(contentAddress);
- context.addStep(operation, AuthServerUtil.getHandler(context, contentAddress, REMOVE), OperationContext.Stage.MODEL);
- }
-
- static boolean isRedeploy(OperationContext context, ModelNode model) throws OperationFailedException {
- return isAuthServerEnabled(context) && REDEPLOY_SERVER.resolveModelAttribute(context, model).asBoolean();
- }
-
- private boolean isHostController(OperationContext context) {
- return context.getProcessType() == ProcessType.HOST_CONTROLLER;
- }
-
- private String pathExistsMessage(PathAddress overlayAddress, String overlayPath) {
- PathAddress contentAddress = overlayAddress.append("content", overlayPath);
- String msg = "Can not update overlay at " + contentAddress.toCLIStyleString();
- msg += " You may try your request again using the " + OVERWRITE.getName() + " attribute.";
- return msg;
- }
-
- private boolean isContentExists(OperationContext context, PathAddress overlayAddress, String overlayPath) {
- Resource resource = context.readResourceFromRoot(overlayAddress);
- return resource.getChildrenNames("content").contains(overlayPath);
- }
-
- private void addOverlay(OperationContext context, PathAddress overlayAddress) {
- ModelNode op = Util.createAddOperation(overlayAddress);
- doAddStep(context, overlayAddress, op);
- }
-
- private void addDeploymentToOverlay(OperationContext context, PathAddress overlayAddress, String deploymentName) {
- PathAddress deploymentAddress = overlayAddress.append("deployment", deploymentName);
- ModelNode op = Util.createAddOperation(deploymentAddress);
- doAddStep(context, deploymentAddress, op);
- }
-
- // only call this if context.getProcessType() == ProcessType.HOST_CONTROLLER
- private void addOverlayToServerGroups(OperationContext context, PathAddress overlayAddress, ModelNode operation, String overlayName) {
- String myProfile = context.getCurrentAddressValue();
- for (String serverGroup : getServerGroupNames(context)) {
- PathAddress address = PathAddress.pathAddress("server-group", serverGroup);
- ModelNode serverGroupModel = context.readResourceFromRoot(address).getModel();
- if (serverGroupModel.get("profile").asString().equals(myProfile)) {
- PathAddress serverGroupOverlayAddress = address.append(overlayAddress);
- boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, address);
- if (!isOverlayExists) {
- addOverlay(context, serverGroupOverlayAddress);
- addDeploymentToOverlay(context, serverGroupOverlayAddress, AuthServerUtil.getDeploymentName(operation));
- }
- }
- }
- }
-
- private Set getServerGroupNames(OperationContext context) {
- return context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS).getChildrenNames("server-group");
- }
-
- private void addContent(OperationContext context, PathAddress overlayAddress, byte[] bytes, String overlayPath) throws OperationFailedException {
- PathAddress contentAddress = overlayAddress.append("content", overlayPath);
- ModelNode op = Util.createAddOperation(contentAddress);
-
- ModelNode content = new ModelNode();
- content.get("bytes").set(bytes);
- op.get("content").set(content);
-
- doAddStep(context, contentAddress, op);
- }
-
- private void doAddStep(OperationContext context, PathAddress address, ModelNode operation) {
- //System.out.println("**** Adding Add Step ****");
- //System.out.println(scrub(operation).toString());
- context.addStep(operation, AuthServerUtil.getHandler(context, address, ADD), OperationContext.Stage.MODEL);
- }
-
- private static boolean isAuthServerEnabled(OperationContext context) throws OperationFailedException {
- ModelNode authServerModel = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().clone();
- return AuthServerDefinition.ENABLED.resolveModelAttribute(context, authServerModel).asBoolean();
- }
-
- // used for debugging
- private ModelNode scrub(ModelNode op) {
- ModelNode scrubbed = op.clone();
- if (scrubbed.has("content")) {
- scrubbed.get("content").set("BYTES REMOVED FOR DISPLAY");
- }
- if (scrubbed.has("bytes-to-upload")) {
- scrubbed.get("bytes-to-upload").set("BYTES REMOVED FOR DISPLAY");
- }
- return scrubbed;
- }
-
- /**
- * Get the WAR path where the overlay will live.
- *
- * @param fileName The name of the file being uploaded.
- * @return The overlay path as a String.
- */
- abstract String getOverlayPath(String fileName);
-}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AddProviderHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AddProviderHandler.java
deleted file mode 100644
index 8d8694d199..0000000000
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AddProviderHandler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.keycloak.subsystem.server.extension.authserver;
-
-import org.jboss.as.controller.OperationDefinition;
-import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
-
-/**
- * Operation to add a provider jar to WEB-INF/lib.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- */
-public class AddProviderHandler extends AbstractAddOverlayHandler {
-
- public static final String OP = "add-provider";
-
- public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
- .addParameter(BYTES_TO_UPLOAD)
- .addParameter(UPLOADED_FILE_NAME)
- .addParameter(REDEPLOY_SERVER)
- .addParameter(OVERWRITE)
- .build();
-
- public static final AddProviderHandler INSTANCE = new AddProviderHandler();
-
- private AddProviderHandler() {}
-
- @Override
- String getOverlayPath(String fileName) {
- if (!fileName.toLowerCase().endsWith(".jar")) {
- throw new IllegalArgumentException("Uploaded file name must end with .jar");
- }
- return "/WEB-INF/lib/" + fileName;
- }
-
-}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerAddHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerAddHandler.java
deleted file mode 100755
index e65957347d..0000000000
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerAddHandler.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.keycloak.subsystem.server.extension.authserver;
-
-import org.jboss.as.controller.AbstractAddStepHandler;
-import org.jboss.as.controller.AttributeDefinition;
-import org.jboss.as.controller.OperationContext;
-import org.jboss.as.controller.OperationFailedException;
-import org.jboss.dmr.ModelNode;
-
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
-import org.jboss.as.controller.registry.Resource;
-import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
-
-/**
- * Add an auth server.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- */
-public final class AuthServerAddHandler extends AbstractAddStepHandler {
-
- public static AuthServerAddHandler INSTANCE = new AuthServerAddHandler();
-
- private AuthServerAddHandler() {
- }
-
- @Override
- protected void populateModel(OperationContext context, ModelNode operation, Resource resource) throws OperationFailedException {
- // TODO: localize exception. get id number
- if (!operation.get(OP).asString().equals(ADD)) {
- throw new OperationFailedException("Unexpected operation for add Auth Server. operation=" + operation.toString());
- }
-
- ModelNode model = resource.getModel();
- for (AttributeDefinition attr : AuthServerDefinition.ALL_ATTRIBUTES) {
- attr.validateAndSet(operation, model);
- }
- model = context.resolveExpressions(model);
-
- // returns early if on domain controller
- if (!requiresRuntime(context)) return;
-
- // don't want to try to start server on host controller
- if (!context.isNormalServer()) return;
-
-
- ModelNode webContextNode = model.get(AuthServerDefinition.WEB_CONTEXT.getName());
- if (!webContextNode.isDefined()) webContextNode = AuthServerDefinition.WEB_CONTEXT.getDefaultValue();
- String webContext = webContextNode.asString();
-
- ModelNode isEnabled = model.get("enabled");
- boolean enabled = isEnabled.isDefined() && isEnabled.asBoolean();
-
- AuthServerUtil authServerUtil = new AuthServerUtil(operation);
- authServerUtil.addStepToUploadAuthServer(context, enabled);
- KeycloakAdapterConfigService.getInstance().addServerDeployment(authServerUtil.getDeploymentName(), webContext);
- }
-}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerDefinition.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerDefinition.java
deleted file mode 100755
index 7cfe27bdbc..0000000000
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/AuthServerDefinition.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.keycloak.subsystem.server.extension.authserver;
-
-import org.jboss.as.controller.AttributeDefinition;
-import org.jboss.as.controller.PathElement;
-import org.jboss.as.controller.SimpleAttributeDefinition;
-import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
-import org.jboss.as.controller.SimpleResourceDefinition;
-import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
-import org.jboss.as.controller.registry.ManagementResourceRegistration;
-import org.jboss.dmr.ModelNode;
-import org.jboss.dmr.ModelType;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.jboss.as.controller.OperationFailedException;
-import org.jboss.as.controller.descriptions.ResourceDescriptionResolver;
-import org.jboss.as.controller.operations.validation.ParameterValidator;
-import org.jboss.as.controller.registry.OperationEntry;
-import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
-import org.keycloak.subsystem.server.extension.KeycloakExtension;
-
-/**
- * Defines attributes and operations for an Auth Server
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- */
-public class AuthServerDefinition extends SimpleResourceDefinition {
-
- public static final String TAG_NAME = "auth-server";
-
- protected static final SimpleAttributeDefinition ENABLED =
- new SimpleAttributeDefinitionBuilder("enabled", ModelType.BOOLEAN, true)
- .setAllowExpression(true)
- .setDefaultValue(new ModelNode(false))
- .setRestartAllServices()
- .build();
-
- protected static final SimpleAttributeDefinition WEB_CONTEXT =
- new SimpleAttributeDefinitionBuilder("web-context", ModelType.STRING, true)
- .setAllowExpression(true)
- .setDefaultValue(new ModelNode("auth"))
- .setValidator(new WebContextValidator())
- .setRestartAllServices()
- .build();
-
- protected static final ResourceDescriptionResolver rscDescriptionResolver = KeycloakExtension.getResourceDescriptionResolver(TAG_NAME);
-
- public static final List ALL_ATTRIBUTES = new ArrayList();
- static {
- ALL_ATTRIBUTES.add(ENABLED);
- ALL_ATTRIBUTES.add(WEB_CONTEXT);
- }
-
- private static final Map DEFINITION_LOOKUP = new HashMap();
- static {
- for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
- DEFINITION_LOOKUP.put(def.getXmlName(), def);
- }
- }
-
- private static AuthServerWriteAttributeHandler attrHandler = new AuthServerWriteAttributeHandler(ALL_ATTRIBUTES);
-
- public AuthServerDefinition() {
- super(PathElement.pathElement(TAG_NAME),
- rscDescriptionResolver,
- AuthServerAddHandler.INSTANCE,
- AuthServerRemoveHandler.INSTANCE,
- null,
- OperationEntry.Flag.RESTART_ALL_SERVICES);
- }
-
- @Override
- public void registerOperations(ManagementResourceRegistration resourceRegistration) {
- super.registerOperations(resourceRegistration);
- resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
- resourceRegistration.registerOperationHandler(AddProviderHandler.DEFINITION, AddProviderHandler.INSTANCE);
- resourceRegistration.registerOperationHandler(OverlayKeycloakServerJsonHandler.DEFINITION, OverlayKeycloakServerJsonHandler.INSTANCE);
- resourceRegistration.registerOperationHandler(ListOverlaysHandler.DEFINITION, ListOverlaysHandler.INSTANCE);
- resourceRegistration.registerOperationHandler(RemoveOverlayHandler.DEFINITION, RemoveOverlayHandler.INSTANCE);
- }
-
- @Override
- public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
- super.registerAttributes(resourceRegistration);
- for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
- resourceRegistration.registerReadWriteAttribute(attrDef, null, attrHandler);
- }
- }
-
- public static SimpleAttributeDefinition lookup(String name) {
- return DEFINITION_LOOKUP.get(name);
- }
-
- private static class WebContextValidator implements ParameterValidator {
-
- @Override
- public void validateParameter(String paramName, ModelNode value) throws OperationFailedException {
- String strValue = value.asString();
- if (KeycloakAdapterConfigService.getInstance().isWebContextUsed(strValue)) {
- throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments.");
- }
- }
-
- @Override
- public void validateResolvedParameter(String paramName, ModelNode value) throws OperationFailedException {
- String strValue = value.asString();
- if (KeycloakAdapterConfigService.getInstance().isWebContextUsed(strValue)) {
- throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments.");
- }
- }
-
- }
-}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/ListOverlaysHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/ListOverlaysHandler.java
deleted file mode 100644
index 4b5b17e7ea..0000000000
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/ListOverlaysHandler.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.keycloak.subsystem.server.extension.authserver;
-
-import java.util.Set;
-import java.util.TreeSet;
-import org.jboss.as.controller.OperationContext;
-import org.jboss.as.controller.OperationDefinition;
-import org.jboss.as.controller.OperationFailedException;
-import org.jboss.as.controller.OperationStepHandler;
-import org.jboss.as.controller.PathAddress;
-import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
-import org.jboss.as.controller.registry.Resource;
-import org.jboss.dmr.ModelNode;
-import org.jboss.dmr.ModelType;
-
-/**
- * Operation to list all of the provider jars, theme jars, and keycloak-server.json that
- * have been uploaded to the auth server.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- */
-public class ListOverlaysHandler implements OperationStepHandler {
- static final String LIST_OVERLAYS_OPERATION = "list-overlays";
-
- static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(LIST_OVERLAYS_OPERATION, AuthServerDefinition.rscDescriptionResolver)
- .setReadOnly()
- .setRuntimeOnly()
- .setReplyType(ModelType.LIST)
- .setReplyValueType(ModelType.STRING)
- .build();
-
- static final OperationStepHandler INSTANCE = new ListOverlaysHandler();
-
- private ListOverlaysHandler() {}
-
- @Override
- public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
- final ModelNode result = context.getResult();
- result.setEmptyList();
-
- String overlayName = AuthServerUtil.getOverlayName(operation);
- boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
- if (isOverlayExists) {
- Set overlays = new TreeSet(getOverlayNames(context, overlayName));
- for (final String key : overlays) {
- result.add(key);
- }
- }
- }
-
- private Set getOverlayNames(OperationContext context, String overlayName) {
- PathAddress overlayAddr = PathAddress.pathAddress(DEPLOYMENT_OVERLAY, overlayName);
- Resource resource = context.readResourceFromRoot(overlayAddr);
- return resource.getChildrenNames(CONTENT);
- }
-}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/OverlayKeycloakServerJsonHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/OverlayKeycloakServerJsonHandler.java
deleted file mode 100644
index 744e264bdd..0000000000
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/OverlayKeycloakServerJsonHandler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.keycloak.subsystem.server.extension.authserver;
-
-import org.jboss.as.controller.OperationDefinition;
-import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
-
-/**
- * Operation to overlay keycloak-server.json.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- */
-public class OverlayKeycloakServerJsonHandler extends AbstractAddOverlayHandler {
-
- public static final String OP = "update-server-config";
-
- public static final OverlayKeycloakServerJsonHandler INSTANCE = new OverlayKeycloakServerJsonHandler();
-
- public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
- .addParameter(BYTES_TO_UPLOAD)
- .addParameter(REDEPLOY_SERVER)
- .addParameter(OVERWRITE)
- .build();
-
- private OverlayKeycloakServerJsonHandler() {}
-
- @Override
- String getOverlayPath(String fileName) {
- return "/WEB-INF/classes/META-INF/keycloak-server.json";
- }
-
-}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/RemoveOverlayHandler.java b/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/RemoveOverlayHandler.java
deleted file mode 100644
index 022e96c321..0000000000
--- a/integration/wildfly/wildfly-server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/authserver/RemoveOverlayHandler.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.keycloak.subsystem.server.extension.authserver;
-
-import static org.keycloak.subsystem.server.extension.authserver.AbstractAddOverlayHandler.REDEPLOY_SERVER;
-
-import org.jboss.as.controller.OperationContext;
-import org.jboss.as.controller.OperationDefinition;
-import org.jboss.as.controller.OperationFailedException;
-import org.jboss.as.controller.OperationStepHandler;
-import org.jboss.as.controller.PathAddress;
-import org.jboss.as.controller.SimpleAttributeDefinition;
-import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
-import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
-import org.jboss.dmr.ModelNode;
-import org.jboss.dmr.ModelType;
-
-/**
- * Operation to remove a provider jars, theme jars, or keycloak-server.json that
- * has been uploaded to the auth server.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- */
-public class RemoveOverlayHandler implements OperationStepHandler {
- static final String REMOVE_OVERLAY_OPERATION = "remove-overlay";
-
- protected static final SimpleAttributeDefinition OVERLAY_FILE_PATH =
- new SimpleAttributeDefinitionBuilder("overlay-file-path", ModelType.STRING, false)
- .setAllowExpression(true)
- .setAllowNull(false)
- .build();
-
- static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(REMOVE_OVERLAY_OPERATION, AuthServerDefinition.rscDescriptionResolver)
- .addParameter(OVERLAY_FILE_PATH)
- .addParameter(REDEPLOY_SERVER)
- .build();
-
- static final OperationStepHandler INSTANCE = new RemoveOverlayHandler();
-
- private RemoveOverlayHandler() {}
-
- @Override
- public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
- final ModelNode model = new ModelNode();
- OVERLAY_FILE_PATH.validateAndSet(operation, model);
- REDEPLOY_SERVER.validateAndSet(operation, model);
- String overlayName = AuthServerUtil.getOverlayName(operation);
- boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
- String overlayPath = OVERLAY_FILE_PATH.resolveModelAttribute(context, model).asString();
- if (isOverlayExists) {
- PathAddress overlayAddress = AuthServerUtil.getOverlayAddress(overlayName);
- AbstractAddOverlayHandler.removeContent(context, overlayAddress, overlayPath);
- } else {
- context.setRollbackOnly();
- throw new OperationFailedException("Overlay path " + overlayPath + " not found.");
- }
-
- boolean isRedeploy = AbstractAddOverlayHandler.isRedeploy(context, operation);
- String deploymentName = AuthServerUtil.getDeploymentName(operation);
- if (isRedeploy) AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
- if (!isRedeploy) context.restartRequired();
- }
-}
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties b/integration/wildfly/wildfly-server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties
index f09e3bd189..909e6b3818 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties
@@ -1,26 +1,4 @@
keycloak-server.subsystem=Keycloak subsystem
keycloak-server.subsystem.add=Operation Adds Keycloak subsystem
keycloak-server.subsystem.remove=Operation removes Keycloak subsystem
-keycloak-server.subsystem.auth-server=Keycloak Auth Server
-keycloak-server.subsystem.realm=A Keycloak realm.
-keycloak-server.subsystem.secure-deployment=A deployment secured by Keycloak.
-
-
-keycloak-server.auth-server=A Keycloak Auth Server
-keycloak-server.auth-server.add=Add an Auth Server to the subsystem.
-keycloak-server.auth-server.remove=Remove an Auth Server from the subsystem.
-keycloak-server.auth-server.add-provider=Add a provider service jar to the Keycloak auth server.
-keycloak-server.auth-server.add-provider.uploaded-file-name=The file name of the provider service jar to be added or updated.
-keycloak-server.auth-server.add-provider.bytes-to-upload=The bytes of the provider service jar to be added or updated.
-keycloak-server.auth-server.add-provider.redeploy=Redeploy the auth server after adding the provider. Ignored if auth server is disabled.
-keycloak-server.auth-server.add-provider.overwrite=Overwrite even if the uploaded-file-name already exists as an overlay.
-keycloak-server.auth-server.list-overlays=List the overlays uploaded for this auth server.
-keycloak-server.auth-server.remove-overlay=Remove a provider jar, theme jar, or keycloak-server.json that has been uploaded to the auth server.
-keycloak-server.auth-server.remove-overlay.overlay-file-path=The uploaded path and file name of the overlay to be removed.
-keycloak-server.auth-server.remove-overlay.redeploy=Redeploy the auth server after removing the overlay.
-keycloak-server.auth-server.update-server-config=Upload a new keycloak-server.json configuration file for the Keycloak auth server.
-keycloak-server.auth-server.update-server-config.bytes-to-upload=The bytes of the keycloak-server.json file to be added or updated.
-keycloak-server.auth-server.update-server-config.redeploy=Redeploy the auth server after updating the server config.
-keycloak-server.auth-server.update-server-config.overwrite=Overwrite even if keycloak-server.json already exitss as an overlay.
-keycloak-server.auth-server.enabled=Enable or disable the Auth Server.
-keycloak-server.auth-server.web-context=Web context the auth-server will use. Also, the module name of the auth-server deployment.
+keycloak-server.subsystem.web-context=Web context where Keycloak server is bound. Default value is 'auth'.
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd b/integration/wildfly/wildfly-server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd
index a8dd28e5a4..b346d36162 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd
@@ -18,21 +18,8 @@
]]>
-
-
+
+
-
-
-
-
-
-
-
-
- The name of the war archive containing the Keycloak server web application.
-
-
-
-
diff --git a/integration/wildfly/wildfly-server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml b/integration/wildfly/wildfly-server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml
index 7f66f74965..4a83086787 100644
--- a/integration/wildfly/wildfly-server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml
+++ b/integration/wildfly/wildfly-server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml
@@ -3,9 +3,6 @@
org.keycloak.keycloak-server-subsystem
-
- true
- auth
-
+ auth
diff --git a/integration/wildfly/wildfly-server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java b/integration/wildfly/wildfly-server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java
index 9f29a6f15b..405b06b39d 100755
--- a/integration/wildfly/wildfly-server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java
+++ b/integration/wildfly/wildfly-server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java
@@ -41,7 +41,6 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
@Test
public void testJson() throws Exception {
ModelNode node = new ModelNode();
- node.get("enabled").set(true);
node.get("web-context").set("auth");
System.out.println("json=" + node.toJSONString(false));
diff --git a/integration/wildfly/wildfly-server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml b/integration/wildfly/wildfly-server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml
index f05f8d19c7..bc8f11a778 100644
--- a/integration/wildfly/wildfly-server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml
+++ b/integration/wildfly/wildfly-server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml
@@ -1,6 +1,3 @@
-
- true
- auth
-
+ auth
\ No newline at end of file
diff --git a/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperSpi.java b/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperSpi.java
index f668058d3e..9597f08887 100644
--- a/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperSpi.java
+++ b/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperSpi.java
@@ -25,7 +25,7 @@ public class UserFederationMapperSpi implements Spi {
}
@Override
- public boolean isPrivate() {
- return false;
+ public boolean isInternal() {
+ return true;
}
}
diff --git a/model/api/src/main/java/org/keycloak/migration/MigrationModel.java b/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
index 936fbcf1da..df24b3d009 100755
--- a/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
+++ b/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
@@ -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.2.0.CR1";
+ public static final String LATEST_VERSION = "1.3.0.Beta1";
String getStoredVersion();
void setStoredVersion(String version);
diff --git a/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java b/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
index 7f52ab38e5..5d58fe1b1a 100755
--- a/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -17,11 +17,13 @@ public class MigrationModelManager {
String storedVersion = model.getStoredVersion();
if (MigrationModel.LATEST_VERSION.equals(storedVersion)) return;
ModelVersion stored = null;
- if (storedVersion != null) new ModelVersion(storedVersion);
+ if (storedVersion != null) {
+ stored = new ModelVersion(storedVersion);
+ }
if (stored == null || stored.lessThan(MigrationTo1_2_0_CR1.VERSION)) {
if (stored != null) {
- logger.debug("Migrating older model to 1.2.0.RC1 updates");
+ logger.debug("Migrating older model to 1.2.0.CR1 updates");
}
new MigrationTo1_2_0_CR1().migrate(session);
}
diff --git a/model/api/src/main/java/org/keycloak/migration/MigrationSpi.java b/model/api/src/main/java/org/keycloak/migration/MigrationSpi.java
index e599146a89..cc9601a366 100644
--- a/model/api/src/main/java/org/keycloak/migration/MigrationSpi.java
+++ b/model/api/src/main/java/org/keycloak/migration/MigrationSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class MigrationSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/model/api/src/main/java/org/keycloak/migration/ModelVersion.java b/model/api/src/main/java/org/keycloak/migration/ModelVersion.java
index 1dfcd14c0d..095576a560 100755
--- a/model/api/src/main/java/org/keycloak/migration/ModelVersion.java
+++ b/model/api/src/main/java/org/keycloak/migration/ModelVersion.java
@@ -59,7 +59,7 @@ public class ModelVersion {
if (major < version.major) return true;
if (minor < version.minor) return true;
if (micro < version.micro) return true;
- if (qualifier == version.qualifier) return false;
+ if (qualifier != null && qualifier.equals(version.qualifier)) return false;
if (qualifier == null) return false;
if (version.qualifier == null) return true;
int comp = qualifier.compareTo(version.qualifier);
diff --git a/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0_Beta1.java b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0_Beta1.java
index ccf3c75373..195910b2f7 100755
--- a/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0_Beta1.java
+++ b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0_Beta1.java
@@ -2,10 +2,20 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserFederationEventAwareProviderFactory;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderFactory;
+import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.directory.SearchControls;
/**
* @author Bill Burke
@@ -21,7 +31,54 @@ public class MigrateTo1_3_0_Beta1 {
if (realm.getAuthenticationFlows().size() == 0) {
DefaultAuthenticationFlows.addFlows(realm);
}
+
+ migrateLDAPProviders(session, realm);
}
}
+
+ private void migrateLDAPProviders(KeycloakSession session, RealmModel realm) {
+ List federationProviders = realm.getUserFederationProviders();
+ for (UserFederationProviderModel fedProvider : federationProviders) {
+
+ if (fedProvider.getProviderName().equals(LDAPConstants.LDAP_PROVIDER)) {
+ Map config = fedProvider.getConfig();
+
+ // Update config properties for LDAP federation provider
+ if (config.get(LDAPConstants.SEARCH_SCOPE) == null) {
+ config.put(LDAPConstants.SEARCH_SCOPE, String.valueOf(SearchControls.SUBTREE_SCOPE));
+ }
+
+ String usersDn = config.remove("userDnSuffix");
+ if (usersDn != null && config.get(LDAPConstants.USERS_DN) == null) {
+ config.put(LDAPConstants.USERS_DN, usersDn);
+ }
+
+ String usernameLdapAttribute = config.get(LDAPConstants.USERNAME_LDAP_ATTRIBUTE);
+ if (usernameLdapAttribute != null && config.get(LDAPConstants.RDN_LDAP_ATTRIBUTE) == null) {
+ if (usernameLdapAttribute.equalsIgnoreCase(LDAPConstants.SAM_ACCOUNT_NAME)) {
+ config.put(LDAPConstants.RDN_LDAP_ATTRIBUTE, LDAPConstants.CN);
+ } else {
+ config.put(LDAPConstants.RDN_LDAP_ATTRIBUTE, usernameLdapAttribute);
+ }
+ }
+
+ if (config.get(LDAPConstants.UUID_LDAP_ATTRIBUTE) == null) {
+ String uuidAttrName = LDAPConstants.getUuidAttributeName(config.get(LDAPConstants.VENDOR));
+ config.put(LDAPConstants.UUID_LDAP_ATTRIBUTE, uuidAttrName);
+ }
+
+ realm.updateUserFederationProvider(fedProvider);
+
+ // Create default mappers for LDAP
+ Set mappers = realm.getUserFederationMappersByFederationProvider(fedProvider.getId());
+ if (mappers.isEmpty()) {
+ UserFederationProviderFactory ldapFactory = (UserFederationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, LDAPConstants.LDAP_PROVIDER);
+ if (ldapFactory != null) {
+ ((UserFederationEventAwareProviderFactory) ldapFactory).onProviderModelCreated(realm, fedProvider);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java b/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
index c7cb4a797a..0c34e4be2d 100755
--- a/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
+++ b/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
@@ -20,6 +20,8 @@ package org.keycloak.models;
import java.util.HashMap;
import java.util.Map;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+
/**
* A model type representing the configuration for identity providers. It provides some common properties and also a {@link org.keycloak.models.IdentityProviderModel#config}
* for configuration options and properties specifics to a identity provider.
@@ -43,7 +45,15 @@ public class IdentityProviderModel {
private boolean enabled;
- private boolean updateProfileFirstLogin = true;
+ /**
+ * For possible values see {@link IdentityProviderRepresentation#getUpdateProfileFirstLoginMode()}
+ * @see IdentityProviderRepresentation#UPFLM_ON
+ * @see IdentityProviderRepresentation#UPFLM_MISSING
+ * @see IdentityProviderRepresentation#UPFLM_OFF
+ */
+ protected String updateProfileFirstLoginMode = IdentityProviderRepresentation.UPFLM_ON;
+
+ private boolean trustEmail;
private boolean storeToken;
@@ -68,7 +78,8 @@ public class IdentityProviderModel {
this.alias = model.getAlias();
this.config = new HashMap(model.getConfig());
this.enabled = model.isEnabled();
- this.updateProfileFirstLogin = model.isUpdateProfileFirstLogin();
+ this.updateProfileFirstLoginMode = model.getUpdateProfileFirstLoginMode();
+ this.trustEmail = model.isTrustEmail();
this.storeToken = model.isStoreToken();
this.authenticateByDefault = model.isAuthenticateByDefault();
this.addReadTokenRoleOnCreate = model.addReadTokenRoleOnCreate;
@@ -106,12 +117,18 @@ public class IdentityProviderModel {
this.enabled = enabled;
}
- public boolean isUpdateProfileFirstLogin() {
- return this.updateProfileFirstLogin;
+ /**
+ * @see IdentityProviderRepresentation#getUpdateProfileFirstLoginMode()
+ */
+ public String getUpdateProfileFirstLoginMode() {
+ return updateProfileFirstLoginMode;
}
- public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
- this.updateProfileFirstLogin = updateProfileFirstLogin;
+ /**
+ * @see IdentityProviderRepresentation#setUpdateProfileFirstLoginMode(String)
+ */
+ public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
+ this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}
public boolean isStoreToken() {
@@ -145,4 +162,13 @@ public class IdentityProviderModel {
public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) {
this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate;
}
+
+ public boolean isTrustEmail() {
+ return trustEmail;
+ }
+
+ public void setTrustEmail(boolean trustEmail) {
+ this.trustEmail = trustEmail;
+ }
+
}
diff --git a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
index c0c24a8757..0d97664029 100644
--- a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
+++ b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
@@ -5,6 +5,8 @@ package org.keycloak.models;
*/
public class LDAPConstants {
+ public static final String LDAP_PROVIDER = "ldap";
+
public static final String VENDOR = "vendor";
public static final String VENDOR_RHDS = "rhds";
public static final String VENDOR_ACTIVE_DIRECTORY = "ad";
@@ -19,6 +21,7 @@ public class LDAPConstants {
public static final String CONNECTION_URL = "connectionUrl";
public static final String SECURITY_PROTOCOL = "securityProtocol";
+ public static final String BASE_DN = "baseDn"; // used for tests only
public static final String USERS_DN = "usersDn";
public static final String BIND_DN = "bindDn";
public static final String BIND_CREDENTIAL = "bindCredential";
@@ -51,7 +54,7 @@ public class LDAPConstants {
public static final String CONFIG_DIVIDER = ":::";
// Those are forked from Picketlink
- public static final String GIVENNAME = "givenname";
+ public static final String GIVENNAME = "givenName";
public static final String CN = "cn";
public static final String SN = "sn";
public static final String SAM_ACCOUNT_NAME = "sAMAccountName";
@@ -62,6 +65,7 @@ public class LDAPConstants {
public static final String OBJECT_CLASS = "objectclass";
public static final String UID = "uid";
public static final String USER_PASSWORD_ATTRIBUTE = "userpassword";
+ public static final String GROUP = "group";
public static final String GROUP_OF_NAMES = "groupOfNames";
public static final String GROUP_OF_ENTRIES = "groupOfEntries";
public static final String GROUP_OF_UNIQUE_NAMES = "groupOfUniqueNames";
@@ -69,6 +73,7 @@ public class LDAPConstants {
public static final String COMMA = ",";
public static final String EQUAL = "=";
public static final String EMPTY_ATTRIBUTE_VALUE = " ";
+ public static final String EMPTY_MEMBER_ATTRIBUTE_VALUE = "";
public static final String CUSTOM_ATTRIBUTE_ENABLED = "enabled";
public static final String CUSTOM_ATTRIBUTE_CREATE_DATE = "createDate";
@@ -77,4 +82,21 @@ public class LDAPConstants {
public static final String OBJECT_GUID = "objectGUID";
public static final String CREATE_TIMESTAMP = "createTimestamp";
public static final String MODIFY_TIMESTAMP = "modifyTimestamp";
+
+ public static String getUuidAttributeName(String vendor) {
+ if (vendor != null) {
+ switch (vendor) {
+ case VENDOR_RHDS:
+ return "nsuniqueid";
+ case VENDOR_TIVOLI:
+ return "uniqueidentifier";
+ case VENDOR_NOVELL_EDIRECTORY:
+ return "guid";
+ case VENDOR_ACTIVE_DIRECTORY:
+ return OBJECT_GUID;
+ }
+ }
+
+ return ENTRY_UUID;
+ }
}
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index 43eaa30eb9..61bdbee405 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -29,6 +29,12 @@ public interface RealmModel extends RoleContainerModel {
RealmModel getRealm();
}
+ interface UserFederationMapperEvent extends ProviderEvent {
+ UserFederationMapperModel getFederationMapper();
+ RealmModel getRealm();
+ KeycloakSession getSession();
+ }
+
String getId();
String getName();
@@ -47,18 +53,18 @@ public interface RealmModel extends RoleContainerModel {
void setRegistrationAllowed(boolean registrationAllowed);
- public boolean isRegistrationEmailAsUsername();
+ boolean isRegistrationEmailAsUsername();
- public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername);
-
- boolean isPasswordCredentialGrantAllowed();
-
- void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed);
+ void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername);
boolean isRememberMe();
void setRememberMe(boolean rememberMe);
+ boolean isEditUsernameAllowed();
+
+ void setEditUsernameAllowed(boolean editUsernameAllowed);
+
//--- brute force settings
boolean isBruteForceProtected();
void setBruteForceProtected(boolean value);
diff --git a/model/api/src/main/java/org/keycloak/models/RealmSpi.java b/model/api/src/main/java/org/keycloak/models/RealmSpi.java
index f531cd918f..ce49557510 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmSpi.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class RealmSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationEventAwareProviderFactory.java b/model/api/src/main/java/org/keycloak/models/UserFederationEventAwareProviderFactory.java
index 866bf79881..b409d8784d 100644
--- a/model/api/src/main/java/org/keycloak/models/UserFederationEventAwareProviderFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationEventAwareProviderFactory.java
@@ -29,5 +29,5 @@ public abstract class UserFederationEventAwareProviderFactory implements UserFed
});
}
- protected abstract void onProviderModelCreated(RealmModel realm, UserFederationProviderModel createdProviderModel);
+ public abstract void onProviderModelCreated(RealmModel realm, UserFederationProviderModel createdProviderModel);
}
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
index bd07b772bf..4682dddbfa 100755
--- a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
@@ -20,6 +20,9 @@ public class UserFederationManager implements UserProvider {
protected KeycloakSession session;
+ // Set of already validated/proxied federation users during this session. Key is user ID
+ private Map managedUsers = new HashMap<>();
+
public UserFederationManager(KeycloakSession session) {
this.session = session;
}
@@ -47,7 +50,9 @@ public class UserFederationManager implements UserProvider {
UserFederationProvider fed = getFederationProvider(federation);
if (fed.synchronizeRegistrations()) {
user.setFederationLink(federation.getId());
- return fed.register(realm, user);
+ UserModel registered = fed.register(realm, user);
+ managedUsers.put(registered.getId(), registered);
+ return registered;
}
}
return user;
@@ -70,6 +75,7 @@ public class UserFederationManager implements UserProvider {
boolean fedRemoved = link.removeUser(realm, user);
if (fedRemoved) {
boolean localRemoved = session.userStorage().removeUser(realm, user);
+ managedUsers.remove(user.getId());
if (!localRemoved) {
logger.warn("User removed from federation provider, but failed to remove him from keycloak model");
}
@@ -84,6 +90,10 @@ public class UserFederationManager implements UserProvider {
}
protected void validateUser(RealmModel realm, UserModel user) {
+ if (managedUsers.containsKey(user.getId())) {
+ return;
+ }
+
UserFederationProvider link = getFederationLink(realm, user);
if (link != null && !link.isValid(realm, user)) {
deleteInvalidUser(realm, user);
@@ -100,7 +110,7 @@ public class UserFederationManager implements UserProvider {
if (realmModel == null) return;
UserModel deletedUser = tx.userStorage().getUserById(user.getId(), realmModel);
tx.userStorage().removeUser(realmModel, deletedUser);
- logger.debugf("Removed invalid user '%s'", user.getUsername());
+ logger.infof("Removed invalid user '%s'", user.getUsername());
tx.getTransaction().commit();
} finally {
tx.close();
@@ -109,10 +119,16 @@ public class UserFederationManager implements UserProvider {
protected UserModel validateAndProxyUser(RealmModel realm, UserModel user) {
+ UserModel managed = managedUsers.get(user.getId());
+ if (managed != null) {
+ return managed;
+ }
+
UserFederationProvider link = getFederationLink(realm, user);
if (link != null) {
UserModel validatedProxyUser = link.validateAndProxy(realm, user);
if (validatedProxyUser != null) {
+ managedUsers.put(user.getId(), user);
return validatedProxyUser;
} else {
deleteInvalidUser(realm, user);
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationMapperEventImpl.java b/model/api/src/main/java/org/keycloak/models/UserFederationMapperEventImpl.java
new file mode 100644
index 0000000000..212ecc37de
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationMapperEventImpl.java
@@ -0,0 +1,33 @@
+package org.keycloak.models;
+
+/**
+ * Called during creation or update of UserFederationMapperModel
+ *
+ * @author Marek Posolda
+ */
+public class UserFederationMapperEventImpl implements RealmModel.UserFederationMapperEvent {
+
+ private final UserFederationMapperModel mapperModel;
+ private final RealmModel realm;
+ private final KeycloakSession session;
+
+ public UserFederationMapperEventImpl(UserFederationMapperModel mapperModel, RealmModel realm, KeycloakSession session) {
+ this.mapperModel = mapperModel;
+ this.realm = realm;
+ this.session = session;
+ }
+
+ @Override
+ public UserFederationMapperModel getFederationMapper() {
+ return mapperModel;
+ }
+
+ @Override
+ public RealmModel getRealm() {
+ return realm;
+ }
+
+ public KeycloakSession getSession() {
+ return session;
+ }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java b/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java
index 7c97d675ee..8fdd45ac16 100755
--- a/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java
@@ -44,11 +44,12 @@ public interface UserFederationProvider extends Provider {
/**
* Gives the provider an option to validate if user still exists in federation backend and then proxy UserModel loaded from local storage.
- * This method is called whenever a UserModel is pulled from local storage.
+ * This method is called whenever a UserModel is pulled from Keycloak local storage.
* For example, the LDAP provider proxies the UserModel and does on-demand synchronization with
* LDAP whenever UserModel update methods are invoked. It also overrides UserModel.updateCredential for the
* credential types it supports
*
+ * @param realm
* @param local
* @return null if user is no longer valid or proxy object otherwise
*/
@@ -122,6 +123,7 @@ public interface UserFederationProvider extends Provider {
* Is the Keycloak UserModel still valid and/or existing in federated storage? Keycloak may call this method
* in various user operations. The local storage may be deleted if this method returns false.
*
+ * @param realm
* @param local
* @return
*/
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationSpi.java b/model/api/src/main/java/org/keycloak/models/UserFederationSpi.java
index c17c02a393..6b977513ce 100755
--- a/model/api/src/main/java/org/keycloak/models/UserFederationSpi.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class UserFederationSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return false;
}
diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionSpi.java b/model/api/src/main/java/org/keycloak/models/UserSessionSpi.java
index 8755660fad..993eb9ecd0 100644
--- a/model/api/src/main/java/org/keycloak/models/UserSessionSpi.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSessionSpi.java
@@ -12,7 +12,7 @@ public class UserSessionSpi implements Spi {
public static final String NAME = "userSessions";
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/model/api/src/main/java/org/keycloak/models/UserSpi.java b/model/api/src/main/java/org/keycloak/models/UserSpi.java
index 1d6cd74545..af834e8e61 100755
--- a/model/api/src/main/java/org/keycloak/models/UserSpi.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class UserSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java
index c90a6575b0..e98b37188b 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java
@@ -13,7 +13,7 @@ public class AuthenticationExecutionEntity {
protected AuthenticationExecutionModel.Requirement requirement;
protected int priority;
private boolean userSetupAllowed;
- private boolean autheticatorFlow;
+ private boolean authenticatorFlow;
private String parentFlow;
public String getId() {
@@ -56,12 +56,12 @@ public class AuthenticationExecutionEntity {
this.userSetupAllowed = userSetupAllowed;
}
- public boolean isAutheticatorFlow() {
- return autheticatorFlow;
+ public boolean isAuthenticatorFlow() {
+ return authenticatorFlow;
}
- public void setAutheticatorFlow(boolean autheticatorFlow) {
- this.autheticatorFlow = autheticatorFlow;
+ public void setAuthenticatorFlow(boolean authenticatorFlow) {
+ this.authenticatorFlow = authenticatorFlow;
}
public String getParentFlow() {
diff --git a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
index 04dd0bceec..c4cdd62803 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
@@ -30,7 +30,8 @@ public class IdentityProviderEntity {
private String providerId;
private String name;
private boolean enabled;
- private boolean updateProfileFirstLogin;
+ private String updateProfileFirstLoginMode;
+ private boolean trustEmail;
private boolean storeToken;
protected boolean addReadTokenRoleOnCreate;
private boolean authenticateByDefault;
@@ -61,12 +62,12 @@ public class IdentityProviderEntity {
this.enabled = enabled;
}
- public boolean isUpdateProfileFirstLogin() {
- return updateProfileFirstLogin;
+ public String getUpdateProfileFirstLoginMode() {
+ return updateProfileFirstLoginMode;
}
- public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
- this.updateProfileFirstLogin = updateProfileFirstLogin;
+ public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
+ this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}
public boolean isAuthenticateByDefault() {
@@ -116,4 +117,12 @@ public class IdentityProviderEntity {
public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) {
this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate;
}
+
+ public boolean isTrustEmail() {
+ return trustEmail;
+ }
+
+ public void setTrustEmail(boolean trustEmail) {
+ this.trustEmail = trustEmail;
+ }
}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
index 7c393bbb33..827c80bc89 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -17,9 +17,9 @@ public class RealmEntity extends AbstractIdentifiableEntity {
protected boolean registrationEmailAsUsername;
private boolean rememberMe;
private boolean verifyEmail;
- private boolean passwordCredentialGrantAllowed;
private boolean resetPasswordAllowed;
private String passwordPolicy;
+ private boolean editUsernameAllowed;
//--- brute force settings
private boolean bruteForceProtected;
private int maxFailureWaitSeconds;
@@ -102,14 +102,6 @@ public class RealmEntity extends AbstractIdentifiableEntity {
this.sslRequired = sslRequired;
}
- public boolean isPasswordCredentialGrantAllowed() {
- return passwordCredentialGrantAllowed;
- }
-
- public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
- this.passwordCredentialGrantAllowed = passwordCredentialGrantAllowed;
- }
-
public boolean isRegistrationAllowed() {
return registrationAllowed;
}
@@ -150,6 +142,14 @@ public class RealmEntity extends AbstractIdentifiableEntity {
this.resetPasswordAllowed = resetPasswordAllowed;
}
+ public boolean isEditUsernameAllowed() {
+ return editUsernameAllowed;
+ }
+
+ public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+ this.editUsernameAllowed = editUsernameAllowed;
+ }
+
public String getPasswordPolicy() {
return passwordPolicy;
}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 67d5932a65..2adcb2537a 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -99,7 +99,6 @@ public class ModelToRepresentation {
rep.setCodeSecret(realm.getCodeSecret());
}
rep.setCertificate(realm.getCertificatePem());
- rep.setPasswordCredentialGrantAllowed(realm.isPasswordCredentialGrantAllowed());
rep.setRegistrationAllowed(realm.isRegistrationAllowed());
rep.setRegistrationEmailAsUsername(realm.isRegistrationEmailAsUsername());
rep.setRememberMe(realm.isRememberMe());
@@ -124,6 +123,7 @@ public class ModelToRepresentation {
rep.setVerifyEmail(realm.isVerifyEmail());
rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
+ rep.setEditUsernameAllowed(realm.isEditUsernameAllowed());
rep.setAccessTokenLifespan(realm.getAccessTokenLifespan());
rep.setSsoSessionIdleTimeout(realm.getSsoSessionIdleTimeout());
rep.setSsoSessionMaxLifespan(realm.getSsoSessionMaxLifespan());
@@ -324,7 +324,8 @@ public class ModelToRepresentation {
providerRep.setAlias(identityProviderModel.getAlias());
providerRep.setEnabled(identityProviderModel.isEnabled());
providerRep.setStoreToken(identityProviderModel.isStoreToken());
- providerRep.setUpdateProfileFirstLogin(identityProviderModel.isUpdateProfileFirstLogin());
+ providerRep.setUpdateProfileFirstLoginMode(identityProviderModel.getUpdateProfileFirstLoginMode());
+ providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
providerRep.setConfig(identityProviderModel.getConfig());
providerRep.setAddReadTokenRoleOnCreate(identityProviderModel.isAddReadTokenRoleOnCreate());
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 715b14a9c3..c9611af143 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -96,13 +96,13 @@ public class RepresentationToModel {
else newRealm.setAccessCodeLifespanLogin(1800);
if (rep.getSslRequired() != null) newRealm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase()));
- if (rep.isPasswordCredentialGrantAllowed() != null) newRealm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed());
if (rep.isRegistrationEmailAsUsername() != null)
newRealm.setRegistrationEmailAsUsername(rep.isRegistrationEmailAsUsername());
if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe());
if (rep.isVerifyEmail() != null) newRealm.setVerifyEmail(rep.isVerifyEmail());
if (rep.isResetPasswordAllowed() != null) newRealm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
+ if (rep.isEditUsernameAllowed() != null) newRealm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
if (rep.getPrivateKey() == null || rep.getPublicKey() == null) {
KeycloakModelUtils.generateRealmKeys(newRealm);
} else {
@@ -420,12 +420,12 @@ public class RepresentationToModel {
if (rep.getQuickLoginCheckMilliSeconds() != null) realm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
if (rep.getMaxDeltaTimeSeconds() != null) realm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
if (rep.getFailureFactor() != null) realm.setFailureFactor(rep.getFailureFactor());
- if (rep.isPasswordCredentialGrantAllowed() != null) realm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
if (rep.isRegistrationEmailAsUsername() != null) realm.setRegistrationEmailAsUsername(rep.isRegistrationEmailAsUsername());
if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
+ if (rep.isEditUsernameAllowed() != null) realm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
if (rep.getSslRequired() != null) realm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase()));
if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
if (rep.getAccessCodeLifespanUserAction() != null) realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
@@ -917,7 +917,8 @@ public class RepresentationToModel {
identityProviderModel.setAlias(representation.getAlias());
identityProviderModel.setProviderId(representation.getProviderId());
identityProviderModel.setEnabled(representation.isEnabled());
- identityProviderModel.setUpdateProfileFirstLogin(representation.isUpdateProfileFirstLogin());
+ identityProviderModel.setUpdateProfileFirstLoginMode(representation.getUpdateProfileFirstLoginMode());
+ identityProviderModel.setTrustEmail(representation.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault());
identityProviderModel.setStoreToken(representation.isStoreToken());
identityProviderModel.setAddReadTokenRoleOnCreate(representation.isAddReadTokenRoleOnCreate());
diff --git a/model/api/src/main/java/org/keycloak/provider/Spi.java b/model/api/src/main/java/org/keycloak/provider/Spi.java
index be68251697..e88b66b7ad 100644
--- a/model/api/src/main/java/org/keycloak/provider/Spi.java
+++ b/model/api/src/main/java/org/keycloak/provider/Spi.java
@@ -5,9 +5,9 @@ package org.keycloak.provider;
*/
public interface Spi {
- public boolean isPrivate();
- public String getName();
- public Class extends Provider> getProviderClass();
- public Class extends ProviderFactory> getProviderFactoryClass();
+ boolean isInternal();
+ String getName();
+ Class extends Provider> getProviderClass();
+ Class extends ProviderFactory> getProviderFactoryClass();
}
diff --git a/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java b/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java
index c706d8a07c..9bdd231867 100755
--- a/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java
+++ b/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java
@@ -16,30 +16,30 @@ public class MigrationVersionTest {
Assert.assertEquals(version_100Beta1.getMajor(), 1);
Assert.assertEquals(version_100Beta1.getMinor(), 0);
Assert.assertEquals(version_100Beta1.getMicro(), 0);
- ModelVersion version_100RC1 = new ModelVersion("1.0.0.RC1");
+ ModelVersion version_100CR1 = new ModelVersion("1.0.0.CR1");
ModelVersion version_100 = new ModelVersion("1.0.0");
ModelVersion version_110Beta1 = new ModelVersion("1.1.0.Beta1");
- ModelVersion version_110RC1 = new ModelVersion("1.1.0.RC1");
+ ModelVersion version_110CR1 = new ModelVersion("1.1.0.CR1");
ModelVersion version_110 = new ModelVersion("1.1.0");
ModelVersion version_111Beta1 = new ModelVersion("1.1.1.Beta1");
- ModelVersion version_111RC1 = new ModelVersion("1.1.1.RC1");
+ ModelVersion version_111CR1 = new ModelVersion("1.1.1.CR1");
ModelVersion version_111 = new ModelVersion("1.1.1");
ModelVersion version_211Beta1 = new ModelVersion("2.1.1.Beta1");
- ModelVersion version_211RC1 = new ModelVersion("2.1.1.RC1");
- Assert.assertEquals(version_211RC1.getMajor(), 2);
- Assert.assertEquals(version_211RC1.getMinor(), 1);
- Assert.assertEquals(version_211RC1.getMicro(), 1);
- Assert.assertEquals(version_211RC1.getQualifier(), "RC1");
+ ModelVersion version_211CR1 = new ModelVersion("2.1.1.CR1");
+ Assert.assertEquals(version_211CR1.getMajor(), 2);
+ Assert.assertEquals(version_211CR1.getMinor(), 1);
+ Assert.assertEquals(version_211CR1.getMicro(), 1);
+ Assert.assertEquals(version_211CR1.getQualifier(), "CR1");
ModelVersion version_211 = new ModelVersion("2.1.1");
Assert.assertFalse(version_100Beta1.lessThan(version_100Beta1));
- Assert.assertTrue(version_100Beta1.lessThan(version_100RC1));
+ Assert.assertTrue(version_100Beta1.lessThan(version_100CR1));
Assert.assertTrue(version_100Beta1.lessThan(version_100));
Assert.assertTrue(version_100Beta1.lessThan(version_110Beta1));
- Assert.assertTrue(version_100Beta1.lessThan(version_110RC1));
+ Assert.assertTrue(version_100Beta1.lessThan(version_110CR1));
Assert.assertTrue(version_100Beta1.lessThan(version_110));
- Assert.assertFalse(version_211.lessThan(version_110RC1));
+ Assert.assertFalse(version_211.lessThan(version_110CR1));
}
}
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
index 26e09bb53e..1a19bad3d6 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
@@ -30,6 +30,7 @@ import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperEventImpl;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderCreationEventImpl;
import org.keycloak.models.UserFederationProviderModel;
@@ -138,16 +139,6 @@ public class RealmAdapter implements RealmModel {
realm.setSslRequired(sslRequired.name());
}
- @Override
- public boolean isPasswordCredentialGrantAllowed() {
- return realm.isPasswordCredentialGrantAllowed();
- }
-
- @Override
- public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
- realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
- }
-
@Override
public boolean isRegistrationAllowed() {
return realm.isRegistrationAllowed();
@@ -270,6 +261,16 @@ public class RealmAdapter implements RealmModel {
realm.setResetPasswordAllowed(resetPassword);
}
+ @Override
+ public boolean isEditUsernameAllowed() {
+ return realm.isEditUsernameAllowed();
+ }
+
+ @Override
+ public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+ realm.setEditUsernameAllowed(editUsernameAllowed);
+ }
+
@Override
public PasswordPolicy getPasswordPolicy() {
if (passwordPolicy == null) {
@@ -837,7 +838,9 @@ public class RealmAdapter implements RealmModel {
realm.getUserFederationProviders().add(entity);
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
+
return providerModel;
}
@@ -935,6 +938,7 @@ public class RealmAdapter implements RealmModel {
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
entities.add(entity);
+
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
}
@@ -1283,7 +1287,7 @@ public class RealmAdapter implements RealmModel {
model.setPriority(entity.getPriority());
model.setAuthenticator(entity.getAuthenticator());
model.setParentFlow(entity.getParentFlow());
- model.setAutheticatorFlow(entity.isAutheticatorFlow());
+ model.setAutheticatorFlow(entity.isAuthenticatorFlow());
return model;
}
@@ -1313,7 +1317,7 @@ public class RealmAdapter implements RealmModel {
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
entity.setUserSetupAllowed(model.isUserSetupAllowed());
- entity.setAutheticatorFlow(model.isAutheticatorFlow());
+ entity.setAuthenticatorFlow(model.isAutheticatorFlow());
AuthenticationFlowEntity flow = getFlowEntity(model.getId());
flow.getExecutions().add(entity);
model.setId(entity.getId());
@@ -1331,7 +1335,7 @@ public class RealmAdapter implements RealmModel {
}
}
if (entity == null) return;
- entity.setAutheticatorFlow(model.isAutheticatorFlow());
+ entity.setAuthenticatorFlow(model.isAutheticatorFlow());
entity.setAuthenticator(model.getAuthenticator());
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
@@ -1459,7 +1463,11 @@ public class RealmAdapter implements RealmModel {
entity.setConfig(model.getConfig());
this.realm.getUserFederationMappers().add(entity);
- return entityToModel(entity);
+ UserFederationMapperModel mapperModel = entityToModel(entity);
+
+ session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapperModel, this, session));
+
+ return mapperModel;
}
protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
@@ -1511,6 +1519,8 @@ public class RealmAdapter implements RealmModel {
entity.getConfig().clear();
entity.getConfig().putAll(mapper.getConfig());
}
+
+ session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapper, this, session));
}
@Override
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java
index 300b8f0d1b..bff04a9af7 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java
@@ -11,7 +11,7 @@ import org.keycloak.provider.Spi;
public class CacheRealmProviderSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
index 9e0affa8e6..989f062362 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
@@ -11,7 +11,7 @@ import org.keycloak.provider.Spi;
public class CacheUserProviderSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index afb1c2c574..75b8b82923 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -8,14 +8,12 @@ import org.keycloak.models.AuthenticatorModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.LDAPConstants;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
import org.keycloak.models.cache.entities.CachedRealm;
import org.keycloak.models.utils.KeycloakModelUtils;
@@ -123,18 +121,6 @@ public class RealmAdapter implements RealmModel {
getDelegateForUpdate();
updated.setRegistrationEmailAsUsername(registrationEmailAsUsername);
}
-
- @Override
- public boolean isPasswordCredentialGrantAllowed() {
- if (updated != null) return updated.isPasswordCredentialGrantAllowed();
- return cached.isPasswordCredentialGrantAllowed();
- }
-
- @Override
- public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
- getDelegateForUpdate();
- updated.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
- }
@Override
public boolean isRememberMe() {
@@ -256,6 +242,18 @@ public class RealmAdapter implements RealmModel {
updated.setResetPasswordAllowed(resetPasswordAllowed);
}
+ @Override
+ public boolean isEditUsernameAllowed() {
+ if (updated != null) return updated.isEditUsernameAllowed();
+ return cached.isEditUsernameAllowed();
+ }
+
+ @Override
+ public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+ getDelegateForUpdate();
+ updated.setEditUsernameAllowed(editUsernameAllowed);
+ }
+
@Override
public int getSsoSessionIdleTimeout() {
if (updated != null) return updated.getSsoSessionIdleTimeout();
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
index d93acf6948..016870e37c 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
@@ -39,9 +39,9 @@ public class CachedRealm {
private boolean registrationEmailAsUsername;
private boolean rememberMe;
private boolean verifyEmail;
- private boolean passwordCredentialGrantAllowed;
private boolean resetPasswordAllowed;
private boolean identityFederationEnabled;
+ private boolean editUsernameAllowed;
//--- brute force settings
private boolean bruteForceProtected;
private int maxFailureWaitSeconds;
@@ -111,9 +111,9 @@ public class CachedRealm {
registrationEmailAsUsername = model.isRegistrationEmailAsUsername();
rememberMe = model.isRememberMe();
verifyEmail = model.isVerifyEmail();
- passwordCredentialGrantAllowed = model.isPasswordCredentialGrantAllowed();
resetPasswordAllowed = model.isResetPasswordAllowed();
identityFederationEnabled = model.isIdentityFederationEnabled();
+ editUsernameAllowed = model.isEditUsernameAllowed();
//--- brute force settings
bruteForceProtected = model.isBruteForceProtected();
maxFailureWaitSeconds = model.getMaxFailureWaitSeconds();
@@ -244,10 +244,6 @@ public class CachedRealm {
return registrationEmailAsUsername;
}
- public boolean isPasswordCredentialGrantAllowed() {
- return passwordCredentialGrantAllowed;
- }
-
public boolean isRememberMe() {
return this.rememberMe;
}
@@ -288,6 +284,10 @@ public class CachedRealm {
return resetPasswordAllowed;
}
+ public boolean isEditUsernameAllowed() {
+ return editUsernameAllowed;
+ }
+
public int getSsoSessionIdleTimeout() {
return ssoSessionIdleTimeout;
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 6689a24970..8cd0678960 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -13,6 +13,7 @@ import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperEventImpl;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderCreationEventImpl;
import org.keycloak.models.UserFederationProviderModel;
@@ -111,17 +112,6 @@ public class RealmAdapter implements RealmModel {
em.flush();
}
- @Override
- public boolean isPasswordCredentialGrantAllowed() {
- return realm.isPasswordCredentialGrantAllowed();
- }
-
- @Override
- public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
- realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
- em.flush();
- }
-
@Override
public boolean isRegistrationAllowed() {
return realm.isRegistrationAllowed();
@@ -320,6 +310,17 @@ public class RealmAdapter implements RealmModel {
em.flush();
}
+ @Override
+ public boolean isEditUsernameAllowed() {
+ return realm.isEditUsernameAllowed();
+ }
+
+ @Override
+ public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+ realm.setEditUsernameAllowed(editUsernameAllowed);
+ em.flush();
+ }
+
@Override
public int getNotBefore() {
return realm.getNotBefore();
@@ -789,7 +790,9 @@ public class RealmAdapter implements RealmModel {
realm.getUserFederationProviders().add(entity);
em.flush();
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
+
return providerModel;
}
@@ -801,18 +804,23 @@ public class RealmAdapter implements RealmModel {
if (entity.getId().equals(provider.getId())) {
session.users().preRemove(this, provider);
+ removeFederationMappersForProvider(provider.getId());
- Set mappers = getUserFederationMapperEntitiesByFederationProvider(provider.getId());
- for (UserFederationMapperEntity mapper : mappers) {
- realm.getUserFederationMappers().remove(mapper);
- em.remove(mapper);
- }
it.remove();
em.remove(entity);
return;
}
}
}
+
+ private void removeFederationMappersForProvider(String federationProviderId) {
+ Set mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
+ for (UserFederationMapperEntity mapper : mappers) {
+ realm.getUserFederationMappers().remove(mapper);
+ em.remove(mapper);
+ }
+ }
+
@Override
public void updateUserFederationProvider(UserFederationProviderModel model) {
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
@@ -852,10 +860,9 @@ public class RealmAdapter implements RealmModel {
entity.setConfig(model.getConfig());
entity.setPriority(model.getPriority());
entity.setProviderName(model.getProviderName());
- entity.setPriority(model.getPriority());
String displayName = model.getDisplayName();
if (displayName != null) {
- entity.setDisplayName(model.getDisplayName());
+ entity.setDisplayName(displayName);
}
entity.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
@@ -868,6 +875,8 @@ public class RealmAdapter implements RealmModel {
if (found) continue;
session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+ removeFederationMappersForProvider(entity.getId());
+
it.remove();
em.remove(entity);
}
@@ -907,6 +916,7 @@ public class RealmAdapter implements RealmModel {
entity.setLastSync(model.getLastSync());
em.persist(entity);
realm.getUserFederationProviders().add(entity);
+
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
}
}
@@ -1153,7 +1163,8 @@ public class RealmAdapter implements RealmModel {
identityProviderModel.setInternalId(entity.getInternalId());
identityProviderModel.setConfig(entity.getConfig());
identityProviderModel.setEnabled(entity.isEnabled());
- identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
+ identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
+ identityProviderModel.setTrustEmail(entity.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
identityProviderModel.setStoreToken(entity.isStoreToken());
identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
@@ -1185,7 +1196,8 @@ public class RealmAdapter implements RealmModel {
entity.setEnabled(identityProvider.isEnabled());
entity.setStoreToken(identityProvider.isStoreToken());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
- entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
+ entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+ entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setConfig(identityProvider.getConfig());
@@ -1211,7 +1223,8 @@ public class RealmAdapter implements RealmModel {
if (entity.getInternalId().equals(identityProvider.getInternalId())) {
entity.setAlias(identityProvider.getAlias());
entity.setEnabled(identityProvider.isEnabled());
- entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
+ entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+ entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setStoreToken(identityProvider.isStoreToken());
@@ -1410,7 +1423,11 @@ public class RealmAdapter implements RealmModel {
em.persist(entity);
this.realm.getUserFederationMappers().add(entity);
- return entityToModel(entity);
+ UserFederationMapperModel mapperModel = entityToModel(entity);
+
+ session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapperModel, this, session));
+
+ return mapperModel;
}
@Override
@@ -1464,6 +1481,8 @@ public class RealmAdapter implements RealmModel {
entity.getConfig().putAll(mapper.getConfig());
}
em.flush();
+
+ session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapper, this, session));
}
@Override
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
index ba6de02019..eeef707d8c 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
@@ -41,8 +41,11 @@ public class IdentityProviderEntity {
@Column(name="ENABLED")
private boolean enabled;
- @Column(name="UPDATE_PROFILE_FIRST_LOGIN")
- private boolean updateProfileFirstLogin;
+ @Column(name = "UPDATE_PROFILE_FIRST_LGN_MD")
+ private String updateProfileFirstLoginMode;
+
+ @Column(name = "TRUST_EMAIL")
+ private boolean trustEmail;
@Column(name="STORE_TOKEN")
private boolean storeToken;
@@ -99,12 +102,12 @@ public class IdentityProviderEntity {
this.enabled = enabled;
}
- public boolean isUpdateProfileFirstLogin() {
- return this.updateProfileFirstLogin;
+ public String getUpdateProfileFirstLoginMode() {
+ return updateProfileFirstLoginMode;
}
- public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
- this.updateProfileFirstLogin = updateProfileFirstLogin;
+ public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
+ this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}
public boolean isStoreToken() {
@@ -138,4 +141,12 @@ public class IdentityProviderEntity {
public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) {
this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate;
}
+
+ public boolean isTrustEmail() {
+ return trustEmail;
+ }
+
+ public void setTrustEmail(boolean trustEmail) {
+ this.trustEmail = trustEmail;
+ }
}
\ No newline at end of file
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 089cd67039..41be2b16cf 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -49,8 +49,6 @@ public class RealmEntity {
protected boolean registrationAllowed;
@Column(name = "REG_EMAIL_AS_USERNAME")
protected boolean registrationEmailAsUsername;
- @Column(name="PASSWORD_CRED_GRANT_ALLOWED")
- protected boolean passwordCredentialGrantAllowed;
@Column(name="VERIFY_EMAIL")
protected boolean verifyEmail;
@Column(name="RESET_PASSWORD_ALLOWED")
@@ -59,6 +57,8 @@ public class RealmEntity {
protected boolean rememberMe;
@Column(name="PASSWORD_POLICY")
protected String passwordPolicy;
+ @Column(name="EDIT_USERNAME_ALLOWED")
+ protected boolean editUsernameAllowed;
@Column(name="SSO_IDLE_TIMEOUT")
private int ssoSessionIdleTimeout;
@@ -206,14 +206,6 @@ public class RealmEntity {
this.sslRequired = sslRequired;
}
- public boolean isPasswordCredentialGrantAllowed() {
- return passwordCredentialGrantAllowed;
- }
-
- public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
- this.passwordCredentialGrantAllowed = passwordCredentialGrantAllowed;
- }
-
public boolean isRegistrationAllowed() {
return registrationAllowed;
}
@@ -254,6 +246,14 @@ public class RealmEntity {
this.resetPasswordAllowed = resetPasswordAllowed;
}
+ public boolean isEditUsernameAllowed() {
+ return editUsernameAllowed;
+ }
+
+ public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+ this.editUsernameAllowed = editUsernameAllowed;
+ }
+
public int getSsoSessionIdleTimeout() {
return ssoSessionIdleTimeout;
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 9b57238072..2b8c397f04 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -18,6 +18,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperEventImpl;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderCreationEventImpl;
import org.keycloak.models.UserFederationProviderModel;
@@ -111,17 +112,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
updateRealm();
}
- @Override
- public boolean isPasswordCredentialGrantAllowed() {
- return realm.isPasswordCredentialGrantAllowed();
- }
-
- @Override
- public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
- realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
- updateRealm();
- }
-
@Override
public boolean isRegistrationAllowed() {
return realm.isRegistrationAllowed();
@@ -254,6 +244,17 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
updateRealm();
}
+ @Override
+ public boolean isEditUsernameAllowed() {
+ return realm.isEditUsernameAllowed();
+ }
+
+ @Override
+ public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+ realm.setEditUsernameAllowed(editUsernameAllowed);
+ updateRealm();
+ }
+
@Override
public PasswordPolicy getPasswordPolicy() {
if (passwordPolicy == null) {
@@ -771,7 +772,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
identityProviderModel.setInternalId(entity.getInternalId());
identityProviderModel.setConfig(entity.getConfig());
identityProviderModel.setEnabled(entity.isEnabled());
- identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
+ identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
+ identityProviderModel.setTrustEmail(entity.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
identityProviderModel.setStoreToken(entity.isStoreToken());
identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
@@ -801,7 +803,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
entity.setAlias(identityProvider.getAlias());
entity.setProviderId(identityProvider.getProviderId());
entity.setEnabled(identityProvider.isEnabled());
- entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
+ entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+ entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setStoreToken(identityProvider.isStoreToken());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
@@ -813,7 +816,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
@Override
public void removeIdentityProviderByAlias(String alias) {
- IdentityProviderEntity toRemove;
for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
if (entity.getAlias().equals(alias)) {
realm.getIdentityProviders().remove(entity);
@@ -829,7 +831,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
if (entity.getInternalId().equals(identityProvider.getInternalId())) {
entity.setAlias(identityProvider.getAlias());
entity.setEnabled(identityProvider.isEnabled());
- entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
+ entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+ entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setStoreToken(identityProvider.isStoreToken());
@@ -860,7 +863,9 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
updateRealm();
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
+
return providerModel;
}
@@ -872,11 +877,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
if (entity.getId().equals(provider.getId())) {
session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-
- Set mappers = getUserFederationMapperEntitiesByFederationProvider(provider.getId());
- for (UserFederationMapperEntity mapper : mappers) {
- getMongoEntity().getUserFederationMappers().remove(mapper);
- }
+ removeFederationMappersForProvider(provider.getId());
it.remove();
}
@@ -884,6 +885,13 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
updateRealm();
}
+ private void removeFederationMappersForProvider(String federationProviderId) {
+ Set mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
+ for (UserFederationMapperEntity mapper : mappers) {
+ getMongoEntity().getUserFederationMappers().remove(mapper);
+ }
+ }
+
@Override
public void updateUserFederationProvider(UserFederationProviderModel model) {
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
@@ -938,8 +946,52 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
}
- List entities = new LinkedList();
+ List existingProviders = realm.getUserFederationProviders();
+ List toRemove = new LinkedList<>();
+ for (UserFederationProviderEntity entity : existingProviders) {
+ boolean found = false;
+ for (UserFederationProviderModel model : providers) {
+ if (entity.getId().equals(model.getId())) {
+ entity.setConfig(model.getConfig());
+ entity.setPriority(model.getPriority());
+ entity.setProviderName(model.getProviderName());
+ String displayName = model.getDisplayName();
+ if (displayName != null) {
+ entity.setDisplayName(displayName);
+ }
+ entity.setFullSyncPeriod(model.getFullSyncPeriod());
+ entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+ entity.setLastSync(model.getLastSync());
+ found = true;
+ break;
+ }
+
+ }
+ if (found) continue;
+ session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+ entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+ removeFederationMappersForProvider(entity.getId());
+
+ toRemove.add(entity);
+ }
+
+ for (UserFederationProviderEntity entity : toRemove) {
+ realm.getUserFederationProviders().remove(entity);
+ }
+
+ List add = new LinkedList();
for (UserFederationProviderModel model : providers) {
+ boolean found = false;
+ for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
+ if (entity.getId().equals(model.getId())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) add.add(model);
+ }
+
+ for (UserFederationProviderModel model : add) {
UserFederationProviderEntity entity = new UserFederationProviderEntity();
if (model.getId() != null) {
entity.setId(model.getId());
@@ -959,11 +1011,11 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
entity.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
- entities.add(entity);
+ realm.getUserFederationProviders().add(entity);
+
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
}
- realm.setUserFederationProviders(entities);
updateRealm();
}
@@ -1230,7 +1282,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
@Override
public List getAuthenticationFlows() {
List flows = getMongoEntity().getAuthenticationFlows();
- if (flows.size() == 0) return Collections.EMPTY_LIST;
List models = new LinkedList<>();
for (AuthenticationFlowEntity entity : flows) {
AuthenticationFlowModel model = entityToModel(entity);
@@ -1249,10 +1300,9 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
@Override
public AuthenticationFlowModel getAuthenticationFlowById(String id) {
- for (AuthenticationFlowModel model : getAuthenticationFlows()) {
- if (model.getId().equals(id)) return model;
- }
- return null;
+ AuthenticationFlowEntity entity = getFlowEntity(id);
+ if (entity == null) return null;
+ return entityToModel(entity);
}
protected AuthenticationFlowEntity getFlowEntity(String id) {
@@ -1274,7 +1324,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
@Override
public void updateAuthenticationFlow(AuthenticationFlowModel model) {
- List flows = getMongoEntity().getAuthenticationFlows();
AuthenticationFlowEntity toUpdate = getFlowEntity(model.getId());;
if (toUpdate == null) return;
toUpdate.setAlias(model.getAlias());
@@ -1316,7 +1365,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
model.setPriority(entity.getPriority());
model.setAuthenticator(entity.getAuthenticator());
model.setParentFlow(entity.getParentFlow());
- model.setAutheticatorFlow(entity.isAutheticatorFlow());
+ model.setAutheticatorFlow(entity.isAuthenticatorFlow());
return model;
}
@@ -1346,8 +1395,9 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
entity.setUserSetupAllowed(model.isUserSetupAllowed());
- entity.setAutheticatorFlow(model.isAutheticatorFlow());
- AuthenticationFlowEntity flow = getFlowEntity(model.getId());
+ entity.setAuthenticatorFlow(model.isAutheticatorFlow());
+ entity.setParentFlow(model.getParentFlow());
+ AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
flow.getExecutions().add(entity);
updateMongoEntity();
model.setId(entity.getId());
@@ -1365,7 +1415,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
}
}
if (entity == null) return;
- entity.setAutheticatorFlow(model.isAutheticatorFlow());
+ entity.setAuthenticatorFlow(model.isAutheticatorFlow());
entity.setAuthenticator(model.getAuthenticator());
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
@@ -1499,7 +1549,11 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
getMongoEntity().getUserFederationMappers().add(entity);
updateMongoEntity();
- return entityToModel(entity);
+ UserFederationMapperModel mapperModel = entityToModel(entity);
+
+ session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapperModel, this, session));
+
+ return mapperModel;
}
protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
@@ -1553,6 +1607,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme
entity.getConfig().putAll(mapper.getConfig());
}
updateMongoEntity();
+
+ session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapper, this, session));
}
@Override
diff --git a/pom.xml b/pom.xml
index 9fb531b095..a8dcdb715b 100755
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,7 @@
7.5.Final
1.0.1.Final
1.7.2
- 0.1.10
+ 0.1.12
1.9.0
1.0.4
@@ -1106,6 +1106,12 @@
${project.version}
zip
+
+ org.keycloak
+ keycloak-wf9-adapter-dist
+ ${project.version}
+ zip
+
org.keycloak
keycloak-server-overlay
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
index bfa184b3b0..09b033b9d7 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -504,6 +504,7 @@ public class SamlService {
@QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
logger.debug("SAML GET");
+ //String uri = uriInfo.getRequestUri().toString();
return new RedirectBindingProtocol().execute(samlRequest, samlResponse, relayState);
}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorSpi.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorSpi.java
index 684d07420c..81b0373e25 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticatorSpi.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticatorSpi.java
@@ -11,7 +11,7 @@ import org.keycloak.provider.Spi;
public class AuthenticatorSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return false;
}
diff --git a/services/src/main/java/org/keycloak/exportimport/ClientImportSpi.java b/services/src/main/java/org/keycloak/exportimport/ClientImportSpi.java
index e59a45af74..47a777e307 100755
--- a/services/src/main/java/org/keycloak/exportimport/ClientImportSpi.java
+++ b/services/src/main/java/org/keycloak/exportimport/ClientImportSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class ClientImportSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/services/src/main/java/org/keycloak/messages/MessagesSpi.java b/services/src/main/java/org/keycloak/messages/MessagesSpi.java
index 6e820068c8..dd8b2669a4 100644
--- a/services/src/main/java/org/keycloak/messages/MessagesSpi.java
+++ b/services/src/main/java/org/keycloak/messages/MessagesSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class MessagesSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/services/src/main/java/org/keycloak/offlineconfig/AdminRecovery.java b/services/src/main/java/org/keycloak/offlineconfig/AdminRecovery.java
new file mode 100644
index 0000000000..cb775b1b5f
--- /dev/null
+++ b/services/src/main/java/org/keycloak/offlineconfig/AdminRecovery.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.offlineconfig;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+import org.keycloak.services.managers.ApplianceBootstrap;
+
+/**
+ * Static utility class that performs recovery on the master admin account.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
+ */
+public class AdminRecovery {
+ private static final Logger log = Logger.getLogger(AdminRecovery.class);
+
+ public static final String RECOVER_ADMIN_ACCOUNT = "keycloak.recover-admin";
+ public static final String TEMP_ADMIN_PASSWORD = "keycloak.temp-admin-password";
+
+ // Don't allow instances
+ private AdminRecovery() {}
+
+ public static void recover(KeycloakSessionFactory sessionFactory) {
+ if (!needRecovery()) return;
+
+ KeycloakSession session = sessionFactory.create();
+
+ session.getTransaction().begin();
+ try {
+ doRecover(session, getTempAdminPassword());
+ session.getTransaction().commit();
+ log.info("*******************************");
+ log.info("Recovered Master Admin account.");
+ log.info("*******************************");
+ } finally {
+ session.close();
+ System.clearProperty(RECOVER_ADMIN_ACCOUNT);
+ System.clearProperty(TEMP_ADMIN_PASSWORD);
+ }
+ }
+
+ private static boolean needRecovery() {
+ String strNeedRecovery = System.getProperty(RECOVER_ADMIN_ACCOUNT, "false");
+ return Boolean.parseBoolean(strNeedRecovery);
+ }
+
+ private static String getTempAdminPassword() {
+ String tempAdminPassword = System.getProperty(TEMP_ADMIN_PASSWORD);
+ if ((tempAdminPassword == null) || tempAdminPassword.isEmpty()) {
+ throw new OfflineConfigException("Must provide temporary admin password to recover admin account.");
+ }
+ return tempAdminPassword;
+ }
+
+ private static void doRecover(KeycloakSession session, String tempAdminPassword) {
+ RealmProvider realmProvider = session.realms();
+ UserProvider userProvider = session.users();
+
+ String adminRealmName = Config.getAdminRealm();
+ RealmModel realm = realmProvider.getRealmByName(adminRealmName);
+ UserModel adminUser = userProvider.getUserByUsername("admin", realm);
+
+ if (adminUser == null) {
+ adminUser = userProvider.addUser(realm, "admin");
+ }
+
+ ApplianceBootstrap.setupAdminUser(session, realm, adminUser, tempAdminPassword);
+ }
+}
diff --git a/services/src/main/java/org/keycloak/offlineconfig/OfflineConfigException.java b/services/src/main/java/org/keycloak/offlineconfig/OfflineConfigException.java
new file mode 100644
index 0000000000..09a4a5ca6d
--- /dev/null
+++ b/services/src/main/java/org/keycloak/offlineconfig/OfflineConfigException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.offlineconfig;
+
+/**
+ * Runtime exception thrown when an offline configuration fails. Offline
+ * configuration is defined as any configuration done before the Keycloak Server
+ * starts accepting requests.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
+ */
+public class OfflineConfigException extends IllegalStateException {
+
+ public OfflineConfigException(String msg) {
+ super(msg);
+ }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java b/services/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java
index 6ac5496f60..2b594deafa 100755
--- a/services/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java
+++ b/services/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java
@@ -10,7 +10,7 @@ import org.keycloak.provider.Spi;
public class LoginProtocolSpi implements Spi {
@Override
- public boolean isPrivate() {
+ public boolean isInternal() {
return true;
}
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java
index 1b98e07dc8..f08e7dd665 100755
--- a/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java
@@ -10,8 +10,8 @@ import org.keycloak.provider.Spi;
public class ProtocolMapperSpi implements Spi {
@Override
- public boolean isPrivate() {
- return false;
+ public boolean isInternal() {
+ return true;
}
@Override
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
index 80aee4ab2a..afd2a8a1c8 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
@@ -20,7 +20,7 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
public static final List DEFAULT_ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED = list("RS256");
- public static final List DEFAULT_GRANT_TYPES_SUPPORTED = list(OAuth2Constants.AUTHORIZATION_CODE, OAuth2Constants.REFRESH_TOKEN);
+ public static final List DEFAULT_GRANT_TYPES_SUPPORTED = list(OAuth2Constants.AUTHORIZATION_CODE, OAuth2Constants.REFRESH_TOKEN, OAuth2Constants.PASSWORD);
public static final List DEFAULT_RESPONSE_TYPES_SUPPORTED = list(OAuth2Constants.CODE);
@@ -53,14 +53,7 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
config.setResponseTypesSupported(DEFAULT_RESPONSE_TYPES_SUPPORTED);
config.setSubjectTypesSupported(DEFAULT_SUBJECT_TYPES_SUPPORTED);
config.setResponseModesSupported(DEFAULT_RESPONSE_MODES_SUPPORTED);
-
- if (!realm.isPasswordCredentialGrantAllowed()) {
- config.setGrantTypesSupported(DEFAULT_GRANT_TYPES_SUPPORTED);
- } else {
- List grantTypes = new LinkedList<>(DEFAULT_GRANT_TYPES_SUPPORTED);
- grantTypes.add(OAuth2Constants.PASSWORD);
- config.setGrantTypesSupported(grantTypes);
- }
+ config.setGrantTypesSupported(DEFAULT_GRANT_TYPES_SUPPORTED);
return config;
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
index ffbc6a78e6..66d399592d 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
@@ -37,6 +37,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
+import java.util.List;
import java.util.Map;
/**
@@ -150,7 +151,7 @@ public class TokenEndpoint {
if (legacyGrantType != null) {
grantType = legacyGrantType;
} else {
- throw new ErrorResponseException("invalid_request", "Missing query parameter: " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Response.Status.BAD_REQUEST);
+ throw new ErrorResponseException("invalid_request", "Missing form parameter: " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Response.Status.BAD_REQUEST);
}
}
@@ -227,16 +228,7 @@ public class TokenEndpoint {
throw new ErrorResponseException("invalid_grant", "Session not active", Response.Status.BAD_REQUEST);
}
- String adapterSessionId = formParams.getFirst(AdapterConstants.CLIENT_SESSION_STATE);
- if (adapterSessionId != null) {
- String adapterSessionHost = formParams.getFirst(AdapterConstants.CLIENT_SESSION_HOST);
- logger.debugf("Adapter Session '%s' saved in ClientSession for client '%s'. Host is '%s'", adapterSessionId, client.getClientId(), adapterSessionHost);
-
- event.detail(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId);
- clientSession.setNote(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId);
- event.detail(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost);
- clientSession.setNote(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost);
- }
+ updateClientSession(clientSession);
AccessToken token = tokenManager.createClientAccessToken(session, accessCode.getRequestedRoles(), realm, client, user, userSession, clientSession);
@@ -259,6 +251,10 @@ public class TokenEndpoint {
AccessTokenResponse res;
try {
res = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, event, headers);
+
+ UserSessionModel userSession = session.sessions().getUserSession(realm, res.getSessionState());
+ updateClientSessions(userSession.getClientSessions());
+
} catch (OAuthErrorException e) {
event.error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
@@ -269,11 +265,46 @@ public class TokenEndpoint {
return Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
}
- public Response buildResourceOwnerPasswordCredentialsGrant() {
- if (!realm.isPasswordCredentialGrantAllowed()) {
- throw new ErrorResponseException("not_enabled", "Direct Grant REST API not enabled", Response.Status.FORBIDDEN);
+ private void updateClientSession(ClientSessionModel clientSession) {
+
+ if(clientSession == null) {
+ logger.error("client session is null");
+ return;
}
+ String adapterSessionId = formParams.getFirst(AdapterConstants.CLIENT_SESSION_STATE);
+ if (adapterSessionId != null) {
+ String adapterSessionHost = formParams.getFirst(AdapterConstants.CLIENT_SESSION_HOST);
+ logger.debugf("Adapter Session '%s' saved in ClientSession for client '%s'. Host is '%s'", adapterSessionId, client.getClientId(), adapterSessionHost);
+
+ event.detail(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId);
+ clientSession.setNote(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId);
+ event.detail(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost);
+ clientSession.setNote(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost);
+ }
+ }
+
+ private void updateClientSessions(List clientSessions) {
+ if(clientSessions == null) {
+ logger.error("client sessions is null");
+ return;
+ }
+ for (ClientSessionModel clientSession : clientSessions) {
+ if(clientSession == null) {
+ logger.error("client session is null");
+ continue;
+ }
+ if(clientSession.getClient() == null) {
+ logger.error("client model in client session is null");
+ continue;
+ }
+ if(client.getId().equals(clientSession.getClient().getId())) {
+ updateClientSession(clientSession);
+ }
+ }
+ }
+
+ public Response buildResourceOwnerPasswordCredentialsGrant() {
event.detail(Details.AUTH_METHOD, "oauth_credentials").detail(Details.RESPONSE_TYPE, "token");
String username = formParams.getFirst(AuthenticationManager.FORM_USERNAME);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java
index a8a9e2a495..0626f1c015 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java
@@ -39,7 +39,7 @@ public class AuthorizeClientUtil {
if (client_id == null) {
Map error = new HashMap();
error.put(OAuth2Constants.ERROR, "invalid_client");
- error.put(OAuth2Constants.ERROR_DESCRIPTION, "Could not find client");
+ error.put(OAuth2Constants.ERROR_DESCRIPTION, "Missing client_id parameter");
throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build());
}
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index 0bd9f31b86..b91858ab72 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -4,8 +4,6 @@ import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderEvent;
import org.keycloak.provider.ProviderEventListener;
@@ -66,7 +64,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
Config.Scope scope = Config.scope(spi.getName(), provider);
factory.init(scope);
- if (spi.isPrivate() && !isInternal(factory)) {
+ if (spi.isInternal() && !isInternal(factory)) {
log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
}
@@ -78,7 +76,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
Config.Scope scope = Config.scope(spi.getName(), factory.getId());
factory.init(scope);
- if (spi.isPrivate() && !isInternal(factory)) {
+ if (spi.isInternal() && !isInternal(factory)) {
log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
}
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
index 8760ff01b3..7510572c79 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -61,11 +61,15 @@ public class ApplianceBootstrap {
KeycloakModelUtils.generateRealmKeys(realm);
UserModel adminUser = session.users().addUser(realm, "admin");
+ setupAdminUser(session, realm, adminUser, "admin");
+ }
+
+ public static void setupAdminUser(KeycloakSession session, RealmModel realm, UserModel adminUser, String password) {
adminUser.setEnabled(true);
- UserCredentialModel password = new UserCredentialModel();
- password.setType(UserCredentialModel.PASSWORD);
- password.setValue("admin");
- session.users().updateCredential(realm, adminUser, password);
+ UserCredentialModel usrCredModel = new UserCredentialModel();
+ usrCredModel.setType(UserCredentialModel.PASSWORD);
+ usrCredModel.setValue(password);
+ session.users().updateCredential(realm, adminUser, usrCredModel);
adminUser.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 3ada8798e3..f200130794 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -443,7 +443,7 @@ public class AuthenticationManager {
Iterator i = user.getRequiredActions().iterator();
String action = i.next();
- if (action.equals(UserModel.RequiredAction.VERIFY_EMAIL.name()) && Validation.isEmpty(user.getEmail())) {
+ if (action.equals(UserModel.RequiredAction.VERIFY_EMAIL.name()) && Validation.isBlank(user.getEmail())) {
if (i.hasNext())
action = i.next();
else
@@ -465,7 +465,6 @@ public class AuthenticationManager {
}
if (client.isConsentRequired()) {
- accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT);
UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
@@ -496,11 +495,18 @@ public class AuthenticationManager {
// Skip grant screen if everything was already approved by this user
if (realmRoles.size() > 0 || resourceRoles.size() > 0 || protocolMappers.size() > 0) {
+ accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT);
+
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(accessCode.getCode())
.setAccessRequest(realmRoles, resourceRoles, protocolMappers)
.createOAuthGrant(clientSession);
+ } else {
+ String consentDetail = (grantedConsent != null) ? Details.CONSENT_VALUE_PERSISTED_CONSENT : Details.CONSENT_VALUE_NO_CONSENT_REQUIRED;
+ event.detail(Details.CONSENT, consentDetail);
}
+ } else {
+ event.detail(Details.CONSENT, Details.CONSENT_VALUE_NO_CONSENT_REQUIRED);
}
event.success();
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 026c877637..697a28fe59 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -35,23 +35,35 @@ import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventStoreProvider;
import org.keycloak.events.EventType;
import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.*;
+import org.keycloak.models.AccountRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.ModelReadOnlyException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.TimeBasedOTP;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.protocol.oidc.utils.RedirectUtils;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.ForbiddenException;
+import org.keycloak.services.Urls;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
-import org.keycloak.services.Urls;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.services.util.ResolveRelative;
import org.keycloak.services.validation.Validation;
@@ -73,7 +85,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Variant;
-
import java.lang.reflect.Method;
import java.net.URI;
import java.util.HashSet;
@@ -414,13 +425,16 @@ public class AccountService {
UserModel user = auth.getUser();
- List errors = Validation.validateUpdateProfileForm(formData);
+ List errors = Validation.validateUpdateProfileForm(realm, formData);
if (errors != null && !errors.isEmpty()) {
setReferrerOnPage();
return account.setErrors(errors).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
}
try {
+ if (realm.isEditUsernameAllowed()) {
+ user.setUsername(formData.getFirst("username"));
+ }
user.setFirstName(formData.getFirst("firstName"));
user.setLastName(formData.getFirst("lastName"));
@@ -566,7 +580,7 @@ public class AccountService {
String totp = formData.getFirst("totp");
String totpSecret = formData.getFirst("totpSecret");
- if (Validation.isEmpty(totp)) {
+ if (Validation.isBlank(totp)) {
setReferrerOnPage();
return account.setError(Messages.MISSING_TOTP).createResponse(AccountPages.TOTP);
} else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) {
@@ -626,7 +640,7 @@ public class AccountService {
String passwordConfirm = formData.getFirst("password-confirm");
if (requireCurrent) {
- if (Validation.isEmpty(password)) {
+ if (Validation.isBlank(password)) {
setReferrerOnPage();
return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index e6660ee059..e1d6bfa5b8 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -44,10 +44,10 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
@@ -71,6 +71,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -278,12 +279,16 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
try {
federatedUser = createUser(context);
- if (identityProviderConfig.isUpdateProfileFirstLogin()) {
+ if (IdentityProviderRepresentation.UPFLM_ON.equals(identityProviderConfig.getUpdateProfileFirstLoginMode())
+ || (IdentityProviderRepresentation.UPFLM_MISSING.equals(identityProviderConfig.getUpdateProfileFirstLoginMode()) && !Validation.validateUserMandatoryFields(realmModel, federatedUser))) {
if (isDebugEnabled()) {
LOGGER.debugf("Identity provider requires update profile action.", federatedUser);
}
federatedUser.addRequiredAction(UPDATE_PROFILE);
}
+ if(identityProviderConfig.isTrustEmail() && !Validation.isBlank(federatedUser.getEmail())){
+ federatedUser.setEmailVerified(true);
+ }
} catch (Exception e) {
return redirectToLoginPage(e, clientCode);
}
@@ -506,7 +511,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
String username = context.getModelUsername();
if (username == null) {
username = context.getUsername();
- if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isEmpty(context.getEmail())) {
+ if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isBlank(context.getEmail())) {
username = context.getEmail();
} else if (username == null) {
username = context.getIdpConfig().getAlias() + "." + context.getId();
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index e4c821cd30..0e32fe8982 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -42,6 +42,7 @@ import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
+import org.keycloak.offlineconfig.AdminRecovery;
/**
* @author Bill Burke
@@ -88,6 +89,7 @@ public class KeycloakApplication extends Application {
importRealms(context);
migrateModel();
+ AdminRecovery.recover(sessionFactory);
setupScheduledTasks(sessionFactory);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 3af66d3ccd..08a05c9d5e 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -316,7 +316,7 @@ public class LoginActionsService {
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
}
if (!client.isEnabled()) {
- event.error(Errors.CLIENT_NOT_FOUND);
+ event.error(Errors.CLIENT_DISABLED);
return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
}
@@ -443,7 +443,7 @@ public class LoginActionsService {
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
}
if (!client.isEnabled()) {
- event.error(Errors.CLIENT_NOT_FOUND);
+ event.error(Errors.CLIENT_DISABLED);
return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
}
@@ -741,6 +741,7 @@ public class LoginActionsService {
}
user.updateConsent(grantedConsent);
+ event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
event.success();
return authManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, clientConnection);
@@ -829,7 +830,7 @@ public class LoginActionsService {
String totpSecret = formData.getFirst("totpSecret");
LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class).setUser(user);
- if (Validation.isEmpty(totp)) {
+ if (Validation.isBlank(totp)) {
return loginForms.setError(Messages.MISSING_TOTP)
.setClientSessionCode(accessCode.getCode())
.createResponse(RequiredAction.CONFIGURE_TOTP);
@@ -875,7 +876,7 @@ public class LoginActionsService {
LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class)
.setUser(user);
- if (Validation.isEmpty(passwordNew)) {
+ if (Validation.isBlank(passwordNew)) {
return loginForms.setError(Messages.MISSING_PASSWORD)
.setClientSessionCode(accessCode.getCode())
.createResponse(RequiredAction.UPDATE_PASSWORD);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index b27ce49430..c94fa6ec7c 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -193,8 +193,9 @@ public class RealmAdminResource {
} catch (PatternSyntaxException e) {
return ErrorResponse.error("Specified regex pattern(s) is invalid.", Response.Status.BAD_REQUEST);
} catch (ModelDuplicateException e) {
- return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists.");
- } catch (Exception e) {
+ throw e;
+ } catch (Exception e) {
+ logger.error(e);
return ErrorResponse.error("Failed to update " + rep.getRealm() + " Realm.", Response.Status.INTERNAL_SERVER_ERROR);
}
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
index 4e0d8f9078..4f1c22575b 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
@@ -69,9 +69,13 @@ public class ServerInfoAdminResource {
}
private void setProviders(ServerInfoRepresentation info) {
- Map> providers = new HashMap>();
+ List providers = new LinkedList<>();
for (Spi spi : ServiceLoader.load(Spi.class)) {
- providers.put(spi.getName(), session.listProviderIds(spi.getProviderClass()));
+ SpiInfoRepresentation spiRep = new SpiInfoRepresentation();
+ spiRep.setName(spi.getName());
+ spiRep.setInternal(spi.isInternal());
+ spiRep.setImplementations(session.listProviderIds(spi.getProviderClass()));
+ providers.add(spiRep);
}
info.providers = providers;
}
@@ -197,7 +201,7 @@ public class ServerInfoAdminResource {
private List protocols;
private List