Skip to content

Commit

Permalink
feat: added redirectUrl config and functionality (#126)
Browse files Browse the repository at this point in the history
* feat: added redirectUrl config and functionality

Signed-off-by: jaivalis <[email protected]>

* chore: fixed changelog

Signed-off-by: jaivalis <[email protected]>

* chore: renamed config

Signed-off-by: jaivalis <[email protected]>

---------

Signed-off-by: jaivalis <[email protected]>
  • Loading branch information
jaivalis authored Aug 21, 2024
1 parent 12e7ba9 commit 3b0a8eb
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 17 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased](https://github.com/jaivalis/release-raccoon/compare/0.3.0...jdevelop)

## [0.3.1](https://github.com/jaivalis/release-raccoon/compare/0.3.0...0.3.1) - 21/08/2024

- Redirect on /me for UI

## [0.3.0](https://github.com/jaivalis/release-raccoon/compare/0.2.7...0.3.0) - 01/08/2024

- default postgres db
Expand Down
6 changes: 3 additions & 3 deletions http/rr.http
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
### Artists
GET {{ baseUrl }}/artists?page=0&size=10
GET {{baseUrl}}/artists?page=0&size=10

### Scrape releases
PUT {{ baseUrl }}/release-scrape
PUT {{baseUrl}}/release-scrape

### Notify
GET {{ baseUrl }}/notify-users
GET {{baseUrl}}/notify-users
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.raccoon.user;

import java.util.List;
import java.util.Optional;

import io.smallrye.config.ConfigMapping;

@ConfigMapping(prefix = "redirect")
public interface RedirectConfig {

Optional<List<String>> getWhitelistedUrls();

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.jboss.resteasy.annotations.jaxrs.QueryParam;

import java.net.URI;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;

import io.quarkus.oidc.IdToken;
Expand Down Expand Up @@ -35,12 +37,14 @@
public class UserProfileResource {

UserProfileService userProfileService;
RedirectConfig redirectConfig;
@IdToken
JsonWebToken idToken;

@Inject
public UserProfileResource(final UserProfileService userProfileService) {
public UserProfileResource(final UserProfileService userProfileService, final RedirectConfig redirectConfig) {
this.userProfileService = userProfileService;
this.redirectConfig = redirectConfig;
}

/**
Expand All @@ -51,9 +55,13 @@ public UserProfileResource(final UserProfileService userProfileService) {
@NoCache
@Produces(MediaType.TEXT_HTML)
@Transactional
public Response registrationCallback() {
public Response registrationCallback(@QueryParam("redirectUrl") String redirectUrl) {
final String email = idToken.getClaim(EMAIL_CLAIM);
userProfileService.completeRegistration(email);
if (shouldRedirect(redirectUrl)) {
log.info("Redirecting to ");
return Response.temporaryRedirect(URI.create(redirectUrl)).build();
}

return Response.ok(userProfileService.renderTemplateInstance(email)).build();
}
Expand Down Expand Up @@ -109,4 +117,10 @@ public FollowedArtistsResponse getFollowedArtists() {
return userProfileService.getFollowedArtists(email);
}

private boolean shouldRedirect(String redirectUrl) {
return Objects.nonNull(redirectUrl)
&& Objects.nonNull(redirectConfig.getWhitelistedUrls())
&& redirectConfig.getWhitelistedUrls().orElse(Collections.emptyList()).contains(redirectUrl);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
import com.raccoon.entity.repository.UserArtistRepository;
import com.raccoon.entity.repository.UserRepository;
import com.raccoon.search.dto.SearchResultArtistDto;
import com.raccoon.user.RedirectConfig;
import com.raccoon.user.UserProfileResource;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Optional;

import io.quarkus.mailer.MockMailbox;
import io.quarkus.test.InjectMock;
import io.quarkus.test.Mock;
import io.quarkus.test.TestTransaction;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.common.http.TestHTTPEndpoint;
Expand All @@ -25,15 +29,21 @@
import io.quarkus.test.security.oidc.Claim;
import io.quarkus.test.security.oidc.OidcSecurity;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.smallrye.config.SmallRyeConfig;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;

import static com.raccoon.Constants.EMAIL_CLAIM;
import static io.restassured.RestAssured.given;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.SC_TEMPORARY_REDIRECT;
import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

@QuarkusTest
@TestHTTPEndpoint(UserProfileResource.class)
Expand All @@ -54,6 +64,18 @@ class RaccoonUserProfileResourceIT {
@Inject
ArtistReleaseRepository artistReleaseRepository;

@Inject
SmallRyeConfig smallRyeConfig;

@InjectMock
RedirectConfig redirectConfig;

@ApplicationScoped
@Mock
RedirectConfig featuresConfig() {
return smallRyeConfig.getConfigMapping(RedirectConfig.class);
}

@BeforeEach
@Transactional
public void setup() {
Expand All @@ -69,11 +91,86 @@ public void setup() {
void getProfileOnce() {
given()
.contentType(ContentType.JSON)
.when().get()
.when()
.get()
.then()
.statusCode(SC_OK);

assertEquals(1, mockMailbox.getMailsSentTo("[email protected]").size());
assertThat(mockMailbox.getMailsSentTo("[email protected]"))
.hasSize(1);
}

@Test
@TestSecurity(user = EXISTING_USERNAME, roles = "user")
@OidcSecurity(claims = {
@Claim(key = EMAIL_CLAIM, value = "[email protected]")
})
@DisplayName("get should redirect when url in whitelist")
void getWithRedirect_should_redirect_when_urlInWhitelist() {
String redirectUrl = "https://mock.url.from.whitelist";
when(redirectConfig.getWhitelistedUrls()).thenReturn(Optional.of(List.of(redirectUrl)));

Response response = given()
.queryParam("redirectUrl", redirectUrl)
.redirects().follow(false)
.contentType(ContentType.JSON)
.when()
.get()
.then()
.statusCode(SC_TEMPORARY_REDIRECT)
.extract()
.response();

assertThat(response.getHeader("Location"))
.isEqualTo(redirectUrl);
}

@Test
@TestSecurity(user = EXISTING_USERNAME, roles = "user")
@OidcSecurity(claims = {
@Claim(key = EMAIL_CLAIM, value = "[email protected]")
})
@DisplayName("get should not redirect when url not in whitelist")
void getWithRedirect_should_not_redirect_when_urlNotInWhitelist() {
String redirectUrl = "https://mock.url.from.whitelist";
when(redirectConfig.getWhitelistedUrls()).thenReturn(Optional.of(List.of("not" + redirectUrl)));

Response response = given()
.queryParam("redirectUrl", redirectUrl)
.contentType(ContentType.JSON)
.when()
.get()
.then()
.statusCode(SC_OK)
.extract()
.response();

assertThat(response.getHeader("Location"))
.isNull();
}

@Test
@TestSecurity(user = EXISTING_USERNAME, roles = "user")
@OidcSecurity(claims = {
@Claim(key = EMAIL_CLAIM, value = "[email protected]")
})
@DisplayName("get should not redirect when url not in whitelist")
void getWithRedirect_should_not_redirect_when_whitelistEmpty() {
String redirectUrl = "https://mock.url.from.whitelist";
when(redirectConfig.getWhitelistedUrls()).thenReturn(Optional.empty());

Response response = given()
.queryParam("redirectUrl", redirectUrl)
.contentType(ContentType.JSON)
.when()
.get()
.then()
.statusCode(SC_OK)
.extract()
.response();

assertThat(response.getHeader("Location"))
.isNull();
}

@Test
Expand Down Expand Up @@ -215,7 +312,7 @@ void getUserArtists() {
.statusCode(SC_OK)
.extract().body().jsonPath().getList("rows", ArtistDto.class);

assertEquals(1, list.size());
assertThat(list).hasSize(1);
assertEquals(artistDto.getName(), list.get(0).getName());
assertEquals(artistDto.getSpotifyUri(), list.get(0).getSpotifyUri());
assertEquals(artistDto.getLastfmUri(), list.get(0).getLastfmUri());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ void setUp() {
scraper = new LastfmScraper(artistFactoryMock, artistRepositoryMock, lastfmApiMock);
}

private de.umass.lastfm.Artist stubArtist(int id) {
var uri = "uri" + id;
var name = "name" + id;
var lastfmArtist = mock(de.umass.lastfm.Artist.class);
when(lastfmArtist.getName()).thenReturn(name);
when(lastfmArtist.getUrl()).thenReturn(uri);
return lastfmArtist;
}

@Test
@DisplayName("no play history")
void scrapeTasteNoHistory() {
Expand Down

0 comments on commit 3b0a8eb

Please sign in to comment.