Notifying events by (Authorized)Thread

This commit is contained in:
Francesco Mangiacrapa 2024-07-02 14:40:30 +02:00
parent 6a709a3c38
commit 2d6fac18dc
2 changed files with 234 additions and 95 deletions

View File

@ -38,6 +38,7 @@ import org.gcube.application.geoportal.service.engine.mongo.ProfiledMongoManager
import org.gcube.application.geoportal.service.engine.providers.ConfigurationCache;
import org.gcube.application.geoportal.service.engine.providers.ProjectAccessImpl;
import org.gcube.application.geoportal.service.http.PATCH;
import org.gcube.application.geoportal.service.util.AuthorizedThread;
import com.webcohesion.enunciate.metadata.Ignore;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
@ -95,7 +96,7 @@ public class ProfiledDocuments {
String path = CalledMethodHandler.buildCalledResource(HttpMethod.GET,
"/" + InterfaceConstants.Methods.PROJECTS + "/" + profileID);
CalledMethodHandler.setCalledMethod(path + "/"+InterfaceConstants.Methods.CONFIGURATION_PATH);
CalledMethodHandler.setCalledMethod(path + "/" + InterfaceConstants.Methods.CONFIGURATION_PATH);
return new GuardedMethod<Configuration>() {
@ -136,6 +137,10 @@ public class ProfiledDocuments {
// If latest operation status is not ERROR, notify PROJECT_CREATED event
if (status != null && !status.equals(LifecycleInformation.Status.ERROR)) {
// notifying the Event.PROJECT_CREATED;
AuthorizedThread autThr = null;
try {
autThr = new AuthorizedThread(UserUtils.getCurrent()) {
public void run() {
ItemObserved<Project> item = new ItemObserved<Project>();
EventManager.Event event = Event.PROJECT_CREATED;
AccountingInfo user = UserUtils.getCurrent().asInfo();
@ -145,9 +150,20 @@ public class ProfiledDocuments {
item.setEvent(event);
item.setProject(theNewProject);
item.setUseCaseDescriptor(manager.getUseCaseDescriptor());
log.info("By notifying event ({}, ID {})", event, item.getProjectId());
log.info("By notifying event ({}, on Project ID {}) by thread id {}", event, item.getProjectId(),
this.getId());
eventManager.notify(event, item);
}
};
autThr.start();
} catch (Exception e) {
log.warn("Error occurred when notifying event " + Event.PROJECT_CREATED, e);
} finally {
if (autThr != null)
autThr.resetContext();
}
}
return theNewProject;
}
@ -181,6 +197,10 @@ public class ProfiledDocuments {
// If latest operation status is not ERROR, notify PROJECT_UPDATED event
if (status != null && !status.equals(LifecycleInformation.Status.ERROR)) {
AuthorizedThread autThr = null;
try {
autThr = new AuthorizedThread(UserUtils.getCurrent()) {
public void run() {
ItemObserved<Project> item = new ItemObserved<Project>();
EventManager.Event event = Event.PROJECT_UPDATED;
AccountingInfo user = UserUtils.getCurrent().asInfo();
@ -190,9 +210,20 @@ public class ProfiledDocuments {
item.setEvent(event);
item.setProject(theUpdatedProject);
item.setUseCaseDescriptor(manager.getUseCaseDescriptor());
log.info("By notifying event ({}, ID {})", event, item.getProjectId());
log.info("By notifying event ({}, on Project ID {}) by thread id {}", event, item.getProjectId(),
this.getId());
eventManager.notify(event, item);
}
};
autThr.start();
} catch (Exception e) {
log.warn("Error occurred when notifying event " + Event.PROJECT_UPDATED, e);
} finally {
if (autThr != null)
autThr.resetContext();
}
}
return theUpdatedProject;
}
@ -248,15 +279,15 @@ public class ProfiledDocuments {
* @param force the force
* @return the boolean
*
* @Ignore means excluded by API doc
* Updated by Francesco M.
* @Ignore means excluded by API doc Updated by Francesco M.
*/
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Path("{" + InterfaceConstants.Parameters.PROJECT_ID + "}"+"/"+HIDDEN_PATH)
@Path("{" + InterfaceConstants.Parameters.PROJECT_ID + "}" + "/" + HIDDEN_PATH)
@Ignore
public Boolean delete(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id,
@DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force, @QueryParam(InterfaceConstants.Parameters.IGNORE_ERRORS) Boolean ignoreErrors) {
@DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force,
@QueryParam(InterfaceConstants.Parameters.IGNORE_ERRORS) Boolean ignoreErrors) {
String path = CalledMethodHandler.buildCalledResource(HttpMethod.DELETE,
"/" + InterfaceConstants.Methods.PROJECTS + "/" + manager.getUseCaseDescriptor().getId());
@ -265,8 +296,8 @@ public class ProfiledDocuments {
Boolean deleted = new GuardedMethod<Boolean>() {
@Override
protected Boolean run() throws Exception, WebApplicationException {
log.info("Deleting Project ({}, ID {}). Force is {}, Ignore_Errors is {}", manager.getUseCaseDescriptor().getId(), id,
force, ignoreErrors);
log.info("Deleting Project ({}, ID {}). Force is {}, Ignore_Errors is {}",
manager.getUseCaseDescriptor().getId(), id, force, ignoreErrors);
manager.delete(id, force, ignoreErrors);
return true;
}
@ -274,6 +305,10 @@ public class ProfiledDocuments {
// If deleted, notify PROJECT_DELETED event
if (deleted) {
AuthorizedThread autThr = null;
try {
autThr = new AuthorizedThread(UserUtils.getCurrent()) {
public void run() {
ItemObserved<Project> item = new ItemObserved<Project>();
EventManager.Event event = Event.PROJECT_DELETED;
AccountingInfo user = UserUtils.getCurrent().asInfo();
@ -286,9 +321,20 @@ public class ProfiledDocuments {
deletedProject.setId(id);
deletedProject.setProfileID(manager.getUseCaseDescriptor().getId());
item.setProject(deletedProject);
log.info("By notifying event ({}, ID {})", event, item.getProjectId());
log.info("By notifying event ({}, on Project ID {}) by thread id {}", event, item.getProjectId(),
this.getId());
eventManager.notify(event, item);
}
};
autThr.start();
} catch (Exception e) {
log.warn("Error occurred when notifying event " + Event.PROJECT_DELETED, e);
} finally {
if (autThr != null)
autThr.resetContext();
}
}
return deleted;
}
@ -323,7 +369,6 @@ public class ProfiledDocuments {
}.execute().getResult();
}
/**
* Delete file set. the Authorization must be a VRE token
*
@ -342,12 +387,10 @@ public class ProfiledDocuments {
@Produces(MediaType.APPLICATION_JSON)
@Path("/" + InterfaceConstants.Methods.DELETE_FILES_PATH + "/{" + InterfaceConstants.Parameters.PROJECT_ID + "}")
public Project deleteFileSet(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id,
@DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force,
String path) {
@DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force, String path) {
return deleteFileSet(id, force, false, path);
}
/**
* Delete file set. the Authorization must be a VRE token
*
@ -356,8 +399,7 @@ public class ProfiledDocuments {
* @param path the path must be passed as text in the body
* @return the project
*
* @Ignore means that is excluded by API doc
* Updated by Francesco M.
* @Ignore means that is excluded by API doc Updated by Francesco M.
*/
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "VRE Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@ -365,7 +407,8 @@ public class ProfiledDocuments {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/" + InterfaceConstants.Methods.DELETE_FILES_PATH +"/"+HIDDEN_PATH+"/{" + InterfaceConstants.Parameters.PROJECT_ID + "}")
@Path("/" + InterfaceConstants.Methods.DELETE_FILES_PATH + "/" + HIDDEN_PATH + "/{"
+ InterfaceConstants.Parameters.PROJECT_ID + "}")
@Ignore
public Project deleteFileSet(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id,
@DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force,
@ -419,6 +462,11 @@ public class ProfiledDocuments {
// If latest operation status is not ERROR, notify LIFECYCLE_STEP_PERFORMED
// event
if (status != null && !status.equals(LifecycleInformation.Status.ERROR)) {
AuthorizedThread autThr = null;
try {
autThr = new AuthorizedThread(UserUtils.getCurrent()) {
public void run() {
ItemObserved<Project> item = new ItemObserved<Project>();
EventManager.Event event = Event.LIFECYCLE_STEP_PERFORMED;
AccountingInfo user = UserUtils.getCurrent().asInfo();
@ -428,9 +476,20 @@ public class ProfiledDocuments {
item.setOptional(OPTIONAL_FIELD.message, performStepRequest.getMessage());
item.setUseCaseDescriptor(manager.getUseCaseDescriptor());
item.setProject(theProject);
log.info("By notifying event ({}, ID {})", event, item.getProjectId());
log.info("By notifying event ({}, on Project ID {}) by thread id {}", event, item.getProjectId(),
this.getId());
eventManager.notify(event, item);
}
};
autThr.start();
} catch (Exception e) {
log.warn("Error occurred when notifying event " + Event.LIFECYCLE_STEP_PERFORMED, e);
} finally {
if (autThr != null)
autThr.resetContext();
}
}
return theProject;
}
@ -528,8 +587,7 @@ public class ProfiledDocuments {
String pathCalledResource = CalledMethodHandler.buildCalledResource(HttpMethod.GET,
"/" + InterfaceConstants.Methods.PROJECTS + "/" + manager.getUseCaseDescriptor().getId());
CalledMethodHandler
.setCalledMethod(pathCalledResource + "/{" + InterfaceConstants.Parameters.PROJECT_ID + "}");
CalledMethodHandler.setCalledMethod(pathCalledResource + "/{" + InterfaceConstants.Parameters.PROJECT_ID + "}");
return new GuardedMethod<Project>() {
@Override
@ -609,9 +667,9 @@ public class ProfiledDocuments {
String pathCalledResource = CalledMethodHandler.buildCalledResource(HttpMethod.GET,
"/" + InterfaceConstants.Methods.PROJECTS + "/" + manager.getUseCaseDescriptor().getId());
CalledMethodHandler.setCalledMethod(pathCalledResource + "/{"
+ InterfaceConstants.Methods.RELATIONSHIP + "}/{" + InterfaceConstants.Parameters.PROJECT_ID + "}"
+ "/{" + InterfaceConstants.Parameters.RELATIONSHIP_ID + "}");
CalledMethodHandler.setCalledMethod(pathCalledResource + "/{" + InterfaceConstants.Methods.RELATIONSHIP + "}/{"
+ InterfaceConstants.Parameters.PROJECT_ID + "}" + "/{" + InterfaceConstants.Parameters.RELATIONSHIP_ID
+ "}");
return new GuardedMethod<String>() {
@Override
@ -642,9 +700,9 @@ public class ProfiledDocuments {
String pathCalledResource = CalledMethodHandler.buildCalledResource(HttpMethod.PUT,
"/" + InterfaceConstants.Methods.PROJECTS + "/" + manager.getUseCaseDescriptor().getId());
CalledMethodHandler.setCalledMethod(pathCalledResource + "/{"
+ InterfaceConstants.Methods.RELATIONSHIP + "}/{" + InterfaceConstants.Parameters.PROJECT_ID + "}"
+ "/{" + InterfaceConstants.Parameters.RELATIONSHIP_ID + "}");
CalledMethodHandler.setCalledMethod(pathCalledResource + "/{" + InterfaceConstants.Methods.RELATIONSHIP + "}/{"
+ InterfaceConstants.Parameters.PROJECT_ID + "}" + "/{" + InterfaceConstants.Parameters.RELATIONSHIP_ID
+ "}");
return new GuardedMethod<Project>() {
@Override
@ -682,9 +740,9 @@ public class ProfiledDocuments {
String pathCalledResource = CalledMethodHandler.buildCalledResource(HttpMethod.DELETE,
"/" + InterfaceConstants.Methods.PROJECTS + "/" + manager.getUseCaseDescriptor().getId());
CalledMethodHandler.setCalledMethod(pathCalledResource + "/{"
+ InterfaceConstants.Methods.RELATIONSHIP + "}/{" + InterfaceConstants.Parameters.PROJECT_ID + "}"
+ "/{" + InterfaceConstants.Parameters.RELATIONSHIP_ID + "}");
CalledMethodHandler.setCalledMethod(pathCalledResource + "/{" + InterfaceConstants.Methods.RELATIONSHIP + "}/{"
+ InterfaceConstants.Parameters.PROJECT_ID + "}" + "/{" + InterfaceConstants.Parameters.RELATIONSHIP_ID
+ "}");
return new GuardedMethod<Project>() {
@Override

View File

@ -0,0 +1,81 @@
package org.gcube.application.geoportal.service.util;
import org.gcube.application.cms.implementations.utils.UserUtils.AuthenticatedUser;
import org.gcube.common.authorization.library.provider.AccessTokenProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import lombok.extern.slf4j.Slf4j;
/**
* The Class AuthorizedThread.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Jul 2, 2024
*/
@Slf4j
public class AuthorizedThread extends Thread {
private AuthenticatedUser authenticatedUser;
private String umaToken;
private String gcubeToken;
/**
* Instantiates a new authorized thread.
*
* @param authenticatedUser the authenticated user
*/
public AuthorizedThread(AuthenticatedUser authenticatedUser) {
this.authenticatedUser = authenticatedUser;
setContext();
}
/**
* Sets the context.
*/
private void setContext() {
if (authenticatedUser == null)
return;
log.debug("{} id {} setting context {}", AuthorizedThread.class.getSimpleName(), this.getId(),
authenticatedUser.getContext());
// Setting scope
ScopeProvider.instance.set(authenticatedUser.getContext());
// Setting umaToken
umaToken = authenticatedUser.getUma_token();
if (umaToken != null) {
log.debug("{} id {} setting UMA token {}", AuthorizedThread.class.getSimpleName(), this.getId(),
umaToken.substring(0, 20) + "_MASKED_TOKEN");
AccessTokenProvider.instance.set(umaToken);
}
// Setting gcubeToken
gcubeToken = authenticatedUser.getGcube_token();
if (gcubeToken != null) {
log.debug("{} id {} legacy token {}", AuthorizedThread.class.getSimpleName(), this.getId(),
gcubeToken.substring(0, 20) + "_MASKED_TOKEN");
SecurityTokenProvider.instance.set(gcubeToken);
}
}
/**
* Reset context.
*/
public void resetContext() {
log.debug("{} id {} resetting context called", AuthorizedThread.class.getSimpleName(), this.getId());
ScopeProvider.instance.reset();
if (umaToken != null)
AccessTokenProvider.instance.reset();
if (gcubeToken != null)
SecurityTokenProvider.instance.reset();
}
}