Compare commits

...

5 Commits

7 changed files with 47 additions and 21 deletions

View File

@ -43,6 +43,14 @@
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.googlecode.json-simple</groupId> <groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId> <artifactId>json-simple</artifactId>

View File

@ -33,6 +33,10 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency> <dependency>
<groupId>io.minio</groupId> <groupId>io.minio</groupId>
<artifactId>minio</artifactId> <artifactId>minio</artifactId>

View File

@ -1,10 +1,11 @@
package org.gcube.keycloak.avatar; package org.gcube.keycloak.avatar;
import java.io.InputStream; import java.nio.file.Files;
import org.gcube.keycloak.avatar.storage.AvatarStorageProvider; import org.gcube.keycloak.avatar.storage.AvatarStorageProvider;
import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import org.jboss.resteasy.reactive.RestForm;
import org.jboss.resteasy.reactive.multipart.FileUpload;
import org.keycloak.common.ClientConnection; import org.keycloak.common.ClientConnection;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -62,7 +63,7 @@ public class AvatarAdminResource extends AbstractAvatarResource {
@NoCache @NoCache
@Path("/{user_id}") @Path("/{user_id}")
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadUserAvatarImage(@PathParam("user_id") String userId, MultipartFormDataInput input) { public Response uploadUserAvatarImage(@PathParam("user_id") String userId, @RestForm(AVATAR_IMAGE_PARAMETER) FileUpload image) {
try { try {
if (auth == null) { if (auth == null) {
return Response.status(Response.Status.UNAUTHORIZED).build(); return Response.status(Response.Status.UNAUTHORIZED).build();
@ -71,8 +72,7 @@ public class AvatarAdminResource extends AbstractAvatarResource {
RealmModel realm = session.getContext().getRealm(); RealmModel realm = session.getContext().getRealm();
UserModel user = session.users().getUserById(session.getContext().getRealm(), userId); UserModel user = session.users().getUserById(session.getContext().getRealm(), userId);
InputStream imageInputStream = input.getFormDataPart(AVATAR_IMAGE_PARAMETER, InputStream.class, null); saveUserImage(realm, user, Files.newInputStream(image.uploadedFile()));
saveUserImage(realm, user, imageInputStream);
} catch (ForbiddenException e) { } catch (ForbiddenException e) {
return Response.status(Response.Status.FORBIDDEN).entity(e.getMessage()).build(); return Response.status(Response.Status.FORBIDDEN).entity(e.getMessage()).build();
} catch (Exception e) { } catch (Exception e) {

View File

@ -1,14 +1,15 @@
package org.gcube.keycloak.avatar; package org.gcube.keycloak.avatar;
import java.io.InputStream; import java.nio.file.Files;
import java.util.List; import java.util.List;
import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import org.jboss.resteasy.reactive.RestForm;
import org.jboss.resteasy.reactive.multipart.FileUpload;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.http.HttpRequest; import org.keycloak.http.HttpRequest;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.services.resources.Cors; import org.keycloak.services.cors.Cors;
import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.resources.RealmsResource;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
@ -74,7 +75,7 @@ public class AvatarResource extends AbstractAvatarResource {
@POST @POST
@NoCache @NoCache
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadCurrentUserAvatarImage(MultipartFormDataInput input, @Context UriInfo uriInfo) { public Response uploadCurrentUserAvatarImage(@RestForm(AVATAR_IMAGE_PARAMETER) FileUpload image, @Context UriInfo uriInfo) {
if (auth == null) { if (auth == null) {
throw new NotAuthorizedException("Bearer"); throw new NotAuthorizedException("Bearer");
} }
@ -86,9 +87,7 @@ public class AvatarResource extends AbstractAvatarResource {
logger.debugf("Uploading new avatar for user %s in realm %s", auth.getUser(), auth.getSession().getRealm()); logger.debugf("Uploading new avatar for user %s in realm %s", auth.getUser(), auth.getSession().getRealm());
Response response = null; Response response = null;
try { try {
InputStream imageInputStream = input.getFormDataPart(AVATAR_IMAGE_PARAMETER, InputStream.class, null); saveUserImage(auth.getSession().getRealm(), auth.getUser(), Files.newInputStream(image.uploadedFile()));
saveUserImage(auth.getSession().getRealm(), auth.getUser(), imageInputStream);
if (uriInfo.getQueryParameters().containsKey("account")) { if (uriInfo.getQueryParameters().containsKey("account")) {
UriBuilder uriBuilder = RealmsResource.accountUrl(session.getContext().getUri().getBaseUriBuilder()); UriBuilder uriBuilder = RealmsResource.accountUrl(session.getContext().getUri().getBaseUriBuilder());

View File

@ -51,6 +51,18 @@ public class NoOpEventPublisherProvider extends OrchestratorEventPublisherProvid
// Nothing to do // Nothing to do
return null; return null;
} }
@Override
public int getLastSendHTTPResponseCode() {
// Nothing to do
return 0;
}
@Override
public int getLastRetrieveHTTPResponseCode() {
// Nothing to do
return 0;
}
}; };
} }

View File

@ -46,7 +46,7 @@
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId> <artifactId>keycloak-parent</artifactId>
<version>23.0.5</version> <version>24.0.2</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
@ -107,13 +107,13 @@
<dependency> <dependency>
<groupId>com.squareup.okhttp3</groupId> <groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>
<!-- <version>${okhttp3.version}</version>--> <version>${okhttp3.version}</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.squareup.okio</groupId> <groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId> <artifactId>okio</artifactId>
<!-- <version>${okio.version}</version>--> <version>${okio.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -60,7 +60,8 @@ public class D4ScienceContextMapperTest {
.map(ProviderConfigProperty::getName) .map(ProviderConfigProperty::getName)
.collect(Collectors.toList()); .collect(Collectors.toList());
assertThat(configPropertyNames).containsExactly(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, assertThat(configPropertyNames).containsExactlyInAnyOrder(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME,
OIDCAttributeMapperHelper.INCLUDE_IN_LIGHTWEIGHT_ACCESS_TOKEN,
OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, D4ScienceContextMapper.HTTP_REQUEST_HEADER_NAME, OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, D4ScienceContextMapper.HTTP_REQUEST_HEADER_NAME,
D4ScienceContextMapper.NARROW_RESOURCE_ACCESS); D4ScienceContextMapper.NARROW_RESOURCE_ACCESS);
} }
@ -109,8 +110,11 @@ public class D4ScienceContextMapperTest {
} }
private KeycloakSession givenKeycloakSession(boolean withHeader) { private KeycloakSession givenKeycloakSession(boolean withHeader) {
KeycloakSession keycloakSession = Mockito.mock(KeycloakSession.class); ClientModel clientModel = Mockito.mock(ClientModel.class);
when(clientModel.getName()).thenReturn("test-client-id");
KeycloakContext context = Mockito.mock(KeycloakContext.class); KeycloakContext context = Mockito.mock(KeycloakContext.class);
when(context.getClient()).thenReturn(clientModel);
KeycloakSession keycloakSession = Mockito.mock(KeycloakSession.class);
when(keycloakSession.getContext()).thenReturn(context); when(keycloakSession.getContext()).thenReturn(context);
HttpHeaders headers = Mockito.mock(HttpHeaders.class); HttpHeaders headers = Mockito.mock(HttpHeaders.class);
when(context.getRequestHeaders()).thenReturn(headers); when(context.getRequestHeaders()).thenReturn(headers);
@ -135,13 +139,12 @@ public class D4ScienceContextMapperTest {
} }
return new D4ScienceContextMapper().transformAccessToken(at, mappingModel, keycloakSession, return new D4ScienceContextMapper().transformAccessToken(at, mappingModel, keycloakSession,
userSessionModel, givenClientSessionContext()); userSessionModel, givenClientSessionContext(keycloakSession));
} }
private ClientSessionContext givenClientSessionContext() { private ClientSessionContext givenClientSessionContext(KeycloakSession keycloakSession) {
ClientModel clientModel = Mockito.mock(ClientModel.class);
when(clientModel.getName()).thenReturn("test-client-id");
AuthenticatedClientSessionModel acsm = Mockito.mock(AuthenticatedClientSessionModel.class); AuthenticatedClientSessionModel acsm = Mockito.mock(AuthenticatedClientSessionModel.class);
ClientModel clientModel = keycloakSession.getContext().getClient();
when(acsm.getClient()).thenReturn(clientModel); when(acsm.getClient()).thenReturn(clientModel);
ClientSessionContext csc = Mockito.mock(ClientSessionContext.class); ClientSessionContext csc = Mockito.mock(ClientSessionContext.class);
when(csc.getClientSession()).thenReturn(acsm); when(csc.getClientSession()).thenReturn(acsm);