Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rabbitmq - Fix event sending process #81

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions gateway/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@
<artifactId>json</artifactId>
<version>20230618</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>rabbitmq</artifactId>
<version>1.19.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.georchestra</groupId>
<artifactId>georchestra-testcontainers</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;

@RequiredArgsConstructor
public abstract class AbstractAccountsManager implements AccountManager {

private final @NonNull Consumer<AccountCreated> eventPublisher;
private final @NonNull ApplicationEventPublisher eventPublisher;

protected final ReadWriteLock lock = new ReentrantReadWriteLock();

Expand Down Expand Up @@ -64,7 +65,7 @@ GeorchestraUser createIfMissing(GeorchestraUser mapped) {
createInternal(mapped);
existing = findInternal(mapped).orElseThrow(() -> new IllegalStateException(
"User " + mapped.getUsername() + " not found right after creation"));
eventPublisher.accept(new AccountCreated(existing));
eventPublisher.publishEvent(new AccountCreated(existing));
}
return existing;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
Expand All @@ -37,12 +36,12 @@
import org.georchestra.ds.users.AccountFactory;
import org.georchestra.ds.users.DuplicatedEmailException;
import org.georchestra.ds.users.DuplicatedUidException;
import org.georchestra.gateway.accounts.admin.AbstractAccountsManager;
import org.georchestra.gateway.accounts.admin.AccountCreated;
import org.georchestra.gateway.accounts.admin.AbstractAccountsManager;;
import org.georchestra.gateway.accounts.admin.AccountManager;
import org.georchestra.security.api.UsersApi;
import org.georchestra.security.model.GeorchestraUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.ldap.NameNotFoundException;

import lombok.NonNull;
Expand All @@ -63,7 +62,7 @@ class LdapAccountsManager extends AbstractAccountsManager {
private final @NonNull OrgsDao orgsDao;
private final @NonNull UsersApi usersApi;

public LdapAccountsManager(Consumer<AccountCreated> eventPublisher, AccountDao accountDao, RoleDao roleDao,
public LdapAccountsManager(ApplicationEventPublisher eventPublisher, AccountDao accountDao, RoleDao roleDao,
OrgsDao orgsDao, UsersApi usersApi) {
super(eventPublisher);
this.accountDao = accountDao;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* distributed event through rabbitmq to the {@literal OAUTH2-ACCOUNT-CREATION}
* queue.
*/

public class RabbitmqAccountCreatedEventSender {

public static final String OAUTH2_ACCOUNT_CREATION = "OAUTH2-ACCOUNT-CREATION";
Expand All @@ -41,7 +42,7 @@ public RabbitmqAccountCreatedEventSender(AmqpTemplate eventTemplate) {
this.eventTemplate = eventTemplate;
}

@EventListener(AccountCreated.class)
@EventListener
public void on(AccountCreated event) {
GeorchestraUser user = event.getUser();
final String oAuth2Provider = user.getOAuth2Provider();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package org.georchestra.gateway.rabbitmq;

import org.geonetwork.testcontainers.postgres.GeorchestraDatabaseContainer;
import org.georchestra.ds.orgs.OrgsDao;
import org.georchestra.ds.users.AccountDao;
import org.georchestra.gateway.accounts.admin.AccountCreated;
import org.georchestra.gateway.accounts.events.rabbitmq.RabbitmqAccountCreatedEventSender;
import org.georchestra.gateway.app.GeorchestraGatewayApplication;
import org.georchestra.security.model.GeorchestraUser;
import org.georchestra.testcontainers.console.GeorchestraConsoleContainer;
import org.georchestra.testcontainers.ldap.GeorchestraLdapContainer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.testcontainers.Testcontainers;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.RabbitMQContainer;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.MountableFile;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;

/**
* Integration tests for {@link RabbitmqAccountCreatedEventSender}.
*/
@SpringBootTest(classes = GeorchestraGatewayApplication.class)
@ActiveProfiles("rabbitmq")
@ExtendWith(OutputCaptureExtension.class)
@TestPropertySource(properties = { "enableRabbitmqEvents=true", //
"georchestra.datadir=src/test/resources/test-datadir"//
})
public class SendMessageRabbitmqIT {

private @Autowired ApplicationEventPublisher eventPublisher;
private @Autowired ApplicationContext context;
private @Autowired RabbitmqAccountCreatedEventSender sender;
private @Autowired AccountDao accountDao;
private @Autowired OrgsDao orgsDao;
public static int rabbitmqPort = 5672;
public static int smtpPort = 25;

public static GeorchestraLdapContainer ldap = new GeorchestraLdapContainer();
public static GeorchestraDatabaseContainer db = new GeorchestraDatabaseContainer();
public static RabbitMQContainer rabbitmq = new RabbitMQContainer(DockerImageName.parse("rabbitmq:3.12"))
.withExposedPorts(rabbitmqPort);
public static GenericContainer<?> smtp = new GenericContainer<>("camptocamp/smtp-sink:latest")
.withExposedPorts(smtpPort);
public static GeorchestraConsoleContainer console;

public static @BeforeAll void startUpContainers() {
db.start();
ldap.start();
smtp.start();
rabbitmq.start();

Testcontainers.exposeHostPorts(ldap.getMappedLdapPort(), db.getMappedDatabasePort(),
rabbitmq.getMappedPort(rabbitmqPort), smtp.getMappedPort(smtpPort));
System.setProperty("georchestra.gateway.security.events.rabbitmq.host", "localhost");
System.setProperty("georchestra.gateway.security.events.rabbitmq.port",
String.valueOf(rabbitmq.getMappedPort(rabbitmqPort)));

console = new GeorchestraConsoleContainer()//
.withCopyFileToContainer(MountableFile.forClasspathResource("test-datadir"), "/etc/georchestra")//
.withEnv("enableRabbitmqEvents", "true").withEnv("pgsqlHost", "host.testcontainers.internal")//
.withEnv("pgsqlPort", String.valueOf(db.getMappedDatabasePort()))//
.withEnv("ldapHost", "host.testcontainers.internal")//
.withEnv("ldapPort", String.valueOf(ldap.getMappedLdapPort()))//
.withEnv("rabbitmqHost", "host.testcontainers.internal")//
.withEnv("rabbitmqPort", String.valueOf(rabbitmq.getMappedPort(rabbitmqPort)))//
.withEnv("rabbitmqUser", "guest")//
.withEnv("rabbitmqPassword", "guest")//
.withEnv("smtpHost", "host.testcontainers.internal")//
.withEnv("smtpPort", String.valueOf(smtp.getMappedPort(smtpPort)))//
.withLogToStdOut();

console.start();
System.setProperty("georchestra.console.url",
String.format("http://localhost:%d", console.getMappedConsolePort()));
}

public static @AfterAll void shutDownContainers() {
console.stop();
ldap.stop();
db.stop();
smtp.stop();
}

public @Test void testReceivingMessageFromConsole(CapturedOutput output) throws Exception {
assertNotNull(sender);
GeorchestraUser user = new GeorchestraUser();
user.setId(UUID.randomUUID().toString());
user.setLastUpdated("anystringwoulddo");
user.setUsername("testadmin");
user.setEmail("testadmin@georchestra.org");
user.setFirstName("John");
user.setLastName("Doe");
user.setRoles(Arrays.asList("ADMINISTRATOR", "GN_ADMIN"));
user.setTelephoneNumber("341444111");
user.setTitle("developer");
user.setNotes("user notes");
user.setPostalAddress("123 java street");
user.setOrganization("PSC");
user.setOAuth2Provider("testProvider");
user.setOAuth2Uid("123");
eventPublisher.publishEvent(new AccountCreated(user));
await().atMost(30, TimeUnit.SECONDS).until(() -> {
return output.getOut().contains(
"new OAuth2 account creation notification for testadmin@georchestra.org has been received by console");
});
}
}
65 changes: 65 additions & 0 deletions gateway/src/test/resources/application-rabbitmq.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
georchestra:
gateway:
default-headers:
# Default security headers to append to proxied requests
proxy: true
username: true
roles: true
org: true
orgname: true
global-access-rules:
- intercept-url:
- "/**"
- "/proxy/?url=*"
anonymous: true
security:
createNonExistingUsersInLDAP: true
oauth2.enabled: false
header-authentication:
enabled: true
ldap:
default:
enabled: true
extended: true
url: ldap://${ldapHost}:${ldapPort}/
baseDn: dc=georchestra,dc=org
adminDn: cn=admin,dc=georchestra,dc=org
adminPassword: secret
users:
rdn: ou=users
searchFilter: (uid={0})
pendingUsersSearchBaseDN: ou=pendingusers
protectedUsers: geoserver_privileged_user
roles:
rdn: ou=roles
searchFilter: (member={0})
protectedRoles: ADMINISTRATOR, EXTRACTORAPP, GN_.*, ORGADMIN, REFERENT, USER, SUPERUSER
orgs:
rdn: ou=orgs
orgTypes: Association,Company,NGO,Individual,Other
pendingOrgSearchBaseDN: ou=pendingorgs
events:
rabbitmq:
# Note usually enableRabbitmqEvents, rabbitmqHost, etc. come from georchestra's default.properties
enabled: true
host: ${rabbitmqHost}
port: ${rabbitmqPort}
user: guest
password: guest
spring:
main:
web-application-type: reactive
banner-mode: off
application.name: gateway-service
cloud:
gateway:
enabled: true
default-filters:
- SecureHeaders
- TokenRelay
- RemoveSecurityHeaders
# AddSecHeaders appends sec-* headers to proxied requests based on the
# georchestra.gateway.default-headers and georchestra.gateway.servies.<service>.headers config properties
- AddSecHeaders
httpclient.wiretap: true
httpserver.wiretap: false
Loading
Loading