mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-28 04:13:22 -04:00
Add email extension to test framework (#35096)
Closes #35094 Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
parent
0d32d03c58
commit
89556c7b79
15 changed files with 295 additions and 0 deletions
|
|
@ -81,6 +81,12 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.test</groupId>
|
||||
<artifactId>keycloak-test-framework-email-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ public class ClientConfigBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ClientConfigBuilder directAccessGrants() {
|
||||
rep.setDirectAccessGrantsEnabled(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClientRepresentation build() {
|
||||
return rep;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.representations.idm.RolesRepresentation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EventListener;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class RealmConfigBuilder {
|
||||
|
||||
|
|
@ -43,6 +46,14 @@ public class RealmConfigBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public RealmConfigBuilder eventsListeners(String... eventListeners) {
|
||||
if (rep.getEventsListeners() == null) {
|
||||
rep.setEventsListeners(new LinkedList<>());
|
||||
}
|
||||
rep.getEventsListeners().addAll(List.of(eventListeners));
|
||||
return this;
|
||||
}
|
||||
|
||||
public RealmConfigBuilder roles(String... roleNames) {
|
||||
if (rep.getRoles() == null) {
|
||||
rep.setRoles(new RolesRepresentation());
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ public class UserConfigBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public UserConfigBuilder emailVerified() {
|
||||
rep.setEmailVerified(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserConfigBuilder password(String password) {
|
||||
rep.setCredentials(Collections.combine(rep.getCredentials(), Representations.toCredential(CredentialRepresentation.PASSWORD, password)));
|
||||
return this;
|
||||
|
|
|
|||
51
test-framework/email-server/pom.xml
Executable file
51
test-framework/email-server/pom.xml
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
~ and other contributors as indicated by the @author tags.
|
||||
~
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-test-framework-parent</artifactId>
|
||||
<groupId>org.keycloak.test</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-test-framework-email-server</artifactId>
|
||||
<name>Keycloak Test Framework - Email Server extension</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Email server extension for Keycloak Test Framework</description>
|
||||
|
||||
<properties>
|
||||
<greenmail.version>2.1.1</greenmail.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.test</groupId>
|
||||
<artifactId>keycloak-test-framework-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.icegreen</groupId>
|
||||
<artifactId>greenmail</artifactId>
|
||||
<version>${greenmail.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.keycloak.test.framework.mail;
|
||||
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.test.framework.mail.annotations.InjectMailServer;
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.realm.ManagedRealm;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GreenMailSupplier implements Supplier<MailServer, InjectMailServer> {
|
||||
|
||||
@Override
|
||||
public Class<InjectMailServer> getAnnotationClass() {
|
||||
return InjectMailServer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<MailServer> getValueType() {
|
||||
return MailServer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MailServer getValue(InstanceContext<MailServer, InjectMailServer> instanceContext) {
|
||||
ManagedRealm realm = instanceContext.getDependency(ManagedRealm.class);
|
||||
RealmRepresentation representation = realm.admin().toRepresentation();
|
||||
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put("from", "auto@keycloak.org");
|
||||
config.put("host", "localhost");
|
||||
config.put("port", "3025");
|
||||
|
||||
representation.setSmtpServer(config);
|
||||
realm.admin().update(representation);
|
||||
|
||||
MailServer mailServer = new MailServer();
|
||||
mailServer.start();
|
||||
return mailServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(InstanceContext<MailServer, InjectMailServer> instanceContext) {
|
||||
instanceContext.getValue().stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean compatible(InstanceContext<MailServer, InjectMailServer> a, RequestedInstance<MailServer, InjectMailServer> b) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package org.keycloak.test.framework.mail;
|
||||
|
||||
import org.keycloak.test.framework.TestFrameworkExtension;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GreenMailTestFrameworkExtension implements TestFrameworkExtension {
|
||||
|
||||
@Override
|
||||
public List<Supplier<?, ?>> suppliers() {
|
||||
return List.of(new GreenMailSupplier());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.keycloak.test.framework.mail;
|
||||
|
||||
import com.icegreen.greenmail.store.FolderException;
|
||||
import com.icegreen.greenmail.util.GreenMail;
|
||||
import com.icegreen.greenmail.util.ServerSetup;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import org.keycloak.test.framework.injection.ManagedTestResource;
|
||||
|
||||
public class MailServer extends ManagedTestResource {
|
||||
|
||||
private static final int PORT = 3025;
|
||||
private static final String HOST = "localhost";
|
||||
|
||||
private GreenMail greenMail;
|
||||
|
||||
public void start() {
|
||||
ServerSetup setup = new ServerSetup(PORT, HOST, "smtp");
|
||||
|
||||
greenMail = new GreenMail(setup);
|
||||
greenMail.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
greenMail.stop();
|
||||
}
|
||||
|
||||
public MimeMessage[] getReceivedMessages() {
|
||||
return greenMail.getReceivedMessages();
|
||||
}
|
||||
|
||||
public MimeMessage getLastReceivedMessage() {
|
||||
MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
|
||||
return receivedMessages != null && receivedMessages.length > 0 ? receivedMessages[receivedMessages.length - 1] : null;
|
||||
}
|
||||
|
||||
public boolean waitForIncomingEmail(long timeout, int emailCount) {
|
||||
return greenMail.waitForIncomingEmail(timeout, emailCount);
|
||||
}
|
||||
|
||||
public boolean waitForIncomingEmail(int emailCount) {
|
||||
return greenMail.waitForIncomingEmail(emailCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCleanup() {
|
||||
try {
|
||||
greenMail.purgeEmailFromAllMailboxes();
|
||||
} catch (FolderException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package org.keycloak.test.framework.mail.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface InjectMailServer { }
|
||||
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.test.framework.mail.GreenMailTestFrameworkExtension
|
||||
|
|
@ -72,6 +72,10 @@
|
|||
<groupId>org.keycloak.test</groupId>
|
||||
<artifactId>keycloak-test-framework-oauth-nimbus-poc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.test</groupId>
|
||||
<artifactId>keycloak-test-framework-email-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.test</groupId>
|
||||
<artifactId>keycloak-test-framework-ui</artifactId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
package org.keycloak.test.examples;
|
||||
|
||||
import com.nimbusds.oauth2.sdk.GeneralException;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.events.email.EmailEventListenerProviderFactory;
|
||||
import org.keycloak.test.framework.annotations.InjectRealm;
|
||||
import org.keycloak.test.framework.annotations.InjectUser;
|
||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.test.framework.mail.MailServer;
|
||||
import org.keycloak.test.framework.mail.annotations.InjectMailServer;
|
||||
import org.keycloak.test.framework.oauth.nimbus.OAuthClient;
|
||||
import org.keycloak.test.framework.oauth.nimbus.annotations.InjectOAuthClient;
|
||||
import org.keycloak.test.framework.realm.ManagedRealm;
|
||||
import org.keycloak.test.framework.realm.ManagedUser;
|
||||
import org.keycloak.test.framework.realm.RealmConfig;
|
||||
import org.keycloak.test.framework.realm.RealmConfigBuilder;
|
||||
import org.keycloak.test.framework.realm.UserConfig;
|
||||
import org.keycloak.test.framework.realm.UserConfigBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
@KeycloakIntegrationTest
|
||||
public class EmailTest {
|
||||
|
||||
@InjectRealm(config = EmailSenderRealmConfig.class)
|
||||
ManagedRealm realm;
|
||||
|
||||
@InjectUser(config = UserWithEmail.class)
|
||||
ManagedUser user;
|
||||
|
||||
@InjectMailServer
|
||||
MailServer mail;
|
||||
|
||||
@InjectOAuthClient
|
||||
OAuthClient oAuthClient;
|
||||
|
||||
@Test
|
||||
public void testEmail() throws GeneralException, IOException, MessagingException {
|
||||
oAuthClient.resourceOwnerCredentialGrant(user.getUsername(), "invalid");
|
||||
|
||||
Map<String, String> smtpServer = realm.admin().toRepresentation().getSmtpServer();
|
||||
Assertions.assertEquals("auto@keycloak.org", smtpServer.get("from"));
|
||||
Assertions.assertEquals("localhost", smtpServer.get("host"));
|
||||
Assertions.assertEquals("3025", smtpServer.get("port"));
|
||||
|
||||
mail.waitForIncomingEmail(1);
|
||||
MimeMessage lastReceivedMessage = mail.getLastReceivedMessage();
|
||||
Assertions.assertEquals("Login error", lastReceivedMessage.getSubject());
|
||||
}
|
||||
|
||||
public static class EmailSenderRealmConfig implements RealmConfig {
|
||||
|
||||
@Override
|
||||
public RealmConfigBuilder configure(RealmConfigBuilder realm) {
|
||||
return realm.eventsListeners(EmailEventListenerProviderFactory.ID);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UserWithEmail implements UserConfig {
|
||||
|
||||
@Override
|
||||
public UserConfigBuilder configure(UserConfigBuilder user) {
|
||||
return user.username("test").email("test@local").password("password").emailVerified();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ public class DefaultOAuthClientConfiguration implements ClientConfig {
|
|||
public ClientConfigBuilder configure(ClientConfigBuilder client) {
|
||||
return client.clientId("test-oauth-client")
|
||||
.serviceAccount()
|
||||
.directAccessGrants()
|
||||
.redirectUris("http://127.0.0.1/callback/oauth")
|
||||
.secret("test-secret");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.nimbusds.oauth2.sdk.AuthorizationGrant;
|
|||
import com.nimbusds.oauth2.sdk.AuthorizationRequest;
|
||||
import com.nimbusds.oauth2.sdk.ClientCredentialsGrant;
|
||||
import com.nimbusds.oauth2.sdk.GeneralException;
|
||||
import com.nimbusds.oauth2.sdk.ResourceOwnerPasswordCredentialsGrant;
|
||||
import com.nimbusds.oauth2.sdk.ResponseType;
|
||||
import com.nimbusds.oauth2.sdk.TokenIntrospectionRequest;
|
||||
import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
|
||||
|
|
@ -65,6 +66,15 @@ public class OAuthClient {
|
|||
return TokenResponse.parse(tokenRequest.toHTTPRequest().send());
|
||||
}
|
||||
|
||||
public TokenResponse resourceOwnerCredentialGrant(String username, String password) throws GeneralException, IOException {
|
||||
ResourceOwnerPasswordCredentialsGrant credentialsGrant = new ResourceOwnerPasswordCredentialsGrant(username, new Secret(password));
|
||||
ClientAuthentication clientAuthentication = getClientAuthentication();
|
||||
URI tokenEndpoint = getOIDCProviderMetadata().getTokenEndpointURI();
|
||||
|
||||
TokenRequest tokenRequest = new TokenRequest(tokenEndpoint, clientAuthentication, credentialsGrant);
|
||||
return TokenResponse.parse(tokenRequest.toHTTPRequest().send());
|
||||
}
|
||||
|
||||
public TokenResponse tokenRequest(AuthorizationCode authorizationCode) throws IOException, GeneralException {
|
||||
AuthorizationGrant grant = new AuthorizationCodeGrant(authorizationCode, callbackServer.getRedirectionUri());
|
||||
ClientAuthentication clientAuthentication = getClientAuthentication();
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
<module>db-mysql</module>
|
||||
<module>db-oracle</module>
|
||||
<module>db-postgres</module>
|
||||
<module>email-server</module>
|
||||
<module>oauth-nimbus-poc</module>
|
||||
<module>ui</module>
|
||||
<module>examples</module>
|
||||
|
|
|
|||
Loading…
Reference in a new issue