diff --git a/Backend/alfresco/module/src/main/amp/config/alfresco/extension/custom-cache-context.xml b/Backend/alfresco/module/src/main/amp/config/alfresco/extension/custom-cache-context.xml
index b4e235ab9..3d77059c7 100644
--- a/Backend/alfresco/module/src/main/amp/config/alfresco/extension/custom-cache-context.xml
+++ b/Backend/alfresco/module/src/main/amp/config/alfresco/extension/custom-cache-context.xml
@@ -54,9 +54,13 @@
-
-
-
+
+
+
+
+
+
+
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/restservices/ApiAuthenticationFilter.java b/Backend/services/core/src/main/java/org/edu_sharing/restservices/ApiAuthenticationFilter.java
index e63257d06..e63c27655 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/restservices/ApiAuthenticationFilter.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/restservices/ApiAuthenticationFilter.java
@@ -1,29 +1,17 @@
package org.edu_sharing.restservices;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.*;
-
import com.typesafe.config.Config;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.FilterConfig;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletResponse;
+import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
-
-import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.apache.log4j.Logger;
import org.edu_sharing.alfresco.authentication.subsystems.SubsystemChainingAuthenticationService;
import org.edu_sharing.alfresco.lightbend.LightbendConfigLoader;
-import org.edu_sharing.alfrescocontext.gate.AlfAppContextGate;
import org.edu_sharing.repository.client.tools.CCConstants;
import org.edu_sharing.repository.server.AuthenticationToolAPI;
import org.edu_sharing.repository.server.authentication.AuthenticationFilter;
import org.edu_sharing.repository.server.authentication.ContextManagementFilter;
-import org.edu_sharing.service.authentication.EduAuthentication;
import org.edu_sharing.service.authentication.oauth2.TokenService;
import org.edu_sharing.service.authentication.oauth2.TokenService.Token;
import org.edu_sharing.service.authority.AuthorityServiceFactory;
@@ -33,16 +21,19 @@
import org.edu_sharing.spring.security.basic.CSRFConfig;
import org.springframework.context.ApplicationContext;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
public class ApiAuthenticationFilter implements jakarta.servlet.Filter {
Logger logger = Logger.getLogger(ApiAuthenticationFilter.class);
private TokenService tokenService;
- @Override
- public void destroy() {
- }
-
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
@@ -106,20 +97,18 @@ public void doFilter(ServletRequest req, ServletResponse resp,
}
} else if (authHdr.length() > 10 && authHdr.substring(0, 10).equalsIgnoreCase(CCConstants.AUTH_HEADER_EDU_TICKET)) {
String ticket = authHdr.substring(10).trim();
- if (ticket != null) {
- if (authTool.validateTicket(ticket)) {
- // Force a renew of all toolpermissions since they might have now changed!
- ToolPermissionServiceFactory.getInstance().getAllAvailableToolPermissions(true);
- //if its APIClient username is ignored and is figured out with authentication service
- authTool.storeAuthInfoInSession(authTool.getCurrentUser(), ticket, CCConstants.AUTH_TYPE_TICKET, httpReq.getSession());
- validatedAuth = authTool.validateAuthentication(session);
- }
+ if (authTool.validateTicket(ticket)) {
+ // Force a renew of all toolpermissions since they might have now changed!
+ ToolPermissionServiceFactory.getInstance().getAllAvailableToolPermissions(true);
+ //if its APIClient username is ignored and is figured out with authentication service
+ authTool.storeAuthInfoInSession(authTool.getCurrentUser(), ticket, CCConstants.AUTH_TYPE_TICKET, httpReq.getSession());
+ validatedAuth = authTool.validateAuthentication(session);
}
}
}
Config accessConfig = LightbendConfigLoader.get().getConfig("security.access");
- List AUTHLESS_ENDPOINTS = Arrays.asList(new String[]{"/authentication", "/_about", "/config", "/register", "/sharing",
+ List AUTHLESS_ENDPOINTS = Arrays.asList("/authentication", "/_about", "/config", "/register", "/sharing",
"/lti/v13/oidc/login_initiations",
"/lti/v13/lti13",
"/lti/v13/registration/dynamic",
@@ -127,13 +116,13 @@ public void doFilter(ServletRequest req, ServletResponse resp,
"/lti/v13/details",
"/ltiplatform/v13/openid-configuration",
"/ltiplatform/v13/openid-registration",
- "/ltiplatform/v13/content"});
- List ADMIN_ENDPOINTS = Arrays.asList(new String[]{"/admin", "/bulk", "/lti/v13/registration/static", "/lti/v13/registration/url"});
+ "/ltiplatform/v13/content");
+ List ADMIN_ENDPOINTS = Arrays.asList("/admin", "/bulk", "/lti/v13/registration/static", "/lti/v13/registration/url");
List DISABLED_ENDPOINTS = new ArrayList<>();
try {
- if (!ConfigServiceFactory.getCurrentConfig(req).getValue("register.local", true)) {
- if (ConfigServiceFactory.getCurrentConfig(req).getValue("register.recoverPassword", false)) {
+ if (!ConfigServiceFactory.getCurrentConfig(httpReq).getValue("register.local", true)) {
+ if (ConfigServiceFactory.getCurrentConfig(httpReq).getValue("register.recoverPassword", false)) {
DISABLED_ENDPOINTS.add("/register/v1/register");
DISABLED_ENDPOINTS.add("/register/v1/activate");
} else {
@@ -141,7 +130,7 @@ public void doFilter(ServletRequest req, ServletResponse resp,
DISABLED_ENDPOINTS.add("/register");
}
}
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
boolean noAuthenticationNeeded = false;
@@ -203,13 +192,8 @@ public void doFilter(ServletRequest req, ServletResponse resp,
return;
}
- /**
- * allow authless calls with AUTH_SINGLE_USE_NODEID by appauth
- */
- boolean trustedAuth = false;
- if (ContextManagementFilter.accessTool != null && ContextManagementFilter.accessTool.get() != null) {
- trustedAuth = true;
- }
+ // allow authless calls with AUTH_SINGLE_USE_NODEID by appauth
+ boolean trustedAuth = ContextManagementFilter.accessTool != null && ContextManagementFilter.accessTool.get() != null;
// ignore the auth for the login
if (validatedAuth == null && (!noAuthenticationNeeded && !trustedAuth)) {
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/restservices/admin/v1/AdminApi.java b/Backend/services/core/src/main/java/org/edu_sharing/restservices/admin/v1/AdminApi.java
index 0420b0f15..01a5961fb 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/restservices/admin/v1/AdminApi.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/restservices/admin/v1/AdminApi.java
@@ -11,6 +11,10 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.Action;
@@ -44,6 +48,7 @@
import org.edu_sharing.service.admin.model.RepositoryConfig;
import org.edu_sharing.service.admin.model.ServerUpdateInfo;
import org.edu_sharing.service.admin.model.ToolPermission;
+import org.edu_sharing.service.config.ConfigServiceFactory;
import org.edu_sharing.service.lifecycle.PersonDeleteOptions;
import org.edu_sharing.service.lifecycle.PersonLifecycleService;
import org.edu_sharing.service.lifecycle.PersonReport;
@@ -57,10 +62,6 @@
import org.edu_sharing.service.version.RepositoryVersionInfo;
import org.glassfish.jersey.media.multipart.FormDataParam;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.Context;
-import jakarta.ws.rs.core.Response;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.Serializable;
@@ -1523,6 +1524,47 @@ public Response setConfig(@Context HttpServletRequest req,RepositoryConfig confi
return ErrorResponse.createResponse(t);
}
}
+
+ @PUT
+ @Path("/repositoryConfig/enforceContext/{contextId}")
+ @Operation(summary = "set/update the repository config object")
+ @ApiResponses(value = {
+ @ApiResponse(responseCode="200", description=RestConstants.HTTP_200, content = @Content(schema = @Schema(implementation = Void.class))),
+ @ApiResponse(responseCode="400", description=RestConstants.HTTP_400, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="401", description=RestConstants.HTTP_401, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="403", description=RestConstants.HTTP_403, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="404", description=RestConstants.HTTP_404, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="500", description=RestConstants.HTTP_500, content = @Content(schema = @Schema(implementation = ErrorResponse.class))) })
+ public Response enforceContext(@Context HttpServletRequest req, @PathParam("contextId") String contextId) {
+ try {
+ ConfigServiceFactory.enforceContext(contextId);
+ return Response.ok().build();
+ } catch (Throwable t) {
+ return ErrorResponse.createResponse(t);
+ }
+ }
+
+ @DELETE
+ @Path("/repositoryConfig/enforceContext")
+ @Operation(summary = "set/update the repository config object")
+ @ApiResponses(value = {
+ @ApiResponse(responseCode="200", description=RestConstants.HTTP_200, content = @Content(schema = @Schema(implementation = Void.class))),
+ @ApiResponse(responseCode="400", description=RestConstants.HTTP_400, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="401", description=RestConstants.HTTP_401, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="403", description=RestConstants.HTTP_403, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="404", description=RestConstants.HTTP_404, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
+ @ApiResponse(responseCode="500", description=RestConstants.HTTP_500, content = @Content(schema = @Schema(implementation = ErrorResponse.class))) })
+ public Response clearEnforcedContext(@Context HttpServletRequest req) {
+ try {
+ ConfigServiceFactory.clearEnforcedContext();
+ return Response.ok().build();
+ } catch (Throwable t) {
+ return ErrorResponse.createResponse(t);
+ }
+ }
+
+
+
@GET
@Path("/configFile")
@Operation(summary = "get a base system config file (e.g. edu-sharing.conf)")
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/restservices/config/v1/ConfigApi.java b/Backend/services/core/src/main/java/org/edu_sharing/restservices/config/v1/ConfigApi.java
index 49704fbb5..7498aea31 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/restservices/config/v1/ConfigApi.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/restservices/config/v1/ConfigApi.java
@@ -54,7 +54,7 @@ public Response getConfig() {
ConfigService configService = ConfigServiceFactory.getConfigService();
config.setGlobal(configService.getConfig().values);
try {
- Context context = configService.getContext(ConfigServiceFactory.getCurrentDomain());
+ Context context = configService.getContextByDomain(ConfigServiceFactory.getCurrentDomain());
if (context != null) {
config.setContextId(context.id);
config.setCurrent(configService.getConfigByContext(context).values);
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/admin/AdminService.java b/Backend/services/core/src/main/java/org/edu_sharing/service/admin/AdminService.java
index 18d6f95df..340a44b48 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/service/admin/AdminService.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/service/admin/AdminService.java
@@ -1,28 +1,28 @@
package org.edu_sharing.service.admin;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
import org.alfresco.service.cmr.repository.NodeRef;
import org.edu_sharing.repository.client.rpc.cache.CacheCluster;
import org.edu_sharing.repository.client.rpc.cache.CacheInfo;
import org.edu_sharing.repository.server.jobs.quartz.ImmediateJobListener;
import org.edu_sharing.repository.server.jobs.quartz.JobDescription;
+import org.edu_sharing.repository.server.jobs.quartz.JobInfo;
import org.edu_sharing.repository.server.tools.ApplicationInfo;
import org.edu_sharing.repository.server.tools.PropertiesHelper;
import org.edu_sharing.restservices.admin.v1.model.PluginStatus;
import org.edu_sharing.service.admin.model.GlobalGroup;
-import org.edu_sharing.repository.server.jobs.quartz.JobInfo;
import org.edu_sharing.service.admin.model.RepositoryConfig;
import org.edu_sharing.service.admin.model.ServerUpdateInfo;
import org.edu_sharing.service.admin.model.ToolPermission;
import org.edu_sharing.service.version.RepositoryVersionInfo;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
public interface AdminService {
List getJobs() throws Throwable;
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigService.java b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigService.java
index 1b9e4d116..4a0264d96 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigService.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigService.java
@@ -17,9 +17,11 @@ public interface ConfigService {
* @return
* @throws Exception
*/
- Context getContext(String domain) throws Exception;
+ Context getContextByDomain(String domain) throws Exception;
List getAvailableContext() throws Exception;
+ Context getContextById(String id) throws Exception;
+
Context createOrUpdateContext(Context context);
Config getConfigByDomain(String domain) throws Exception;
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceFactory.java b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceFactory.java
index 618d7fc7f..2cf0924f7 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceFactory.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceFactory.java
@@ -1,21 +1,23 @@
package org.edu_sharing.service.config;
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
-import org.edu_sharing.repository.server.AuthenticationToolAPI;
import org.edu_sharing.alfresco.repository.server.authentication.Context;
import org.edu_sharing.alfresco.service.config.model.Config;
import org.edu_sharing.alfresco.service.config.model.KeyValuePair;
import org.edu_sharing.alfresco.service.config.model.Language;
+import org.edu_sharing.repository.server.AuthenticationToolAPI;
import org.edu_sharing.repository.server.RequestHelper;
-
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.http.HttpServletRequest;
import org.edu_sharing.spring.ApplicationContextFactory;
+import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
public class ConfigServiceFactory {
- private static final String[] DEFAULT_LANGUAGES = new String[]{"de", "en"};
+ private static final String[] DEFAULT_LANGUAGES = new String[]{"de", "en"};
+ public static final String ENFORCED_CONTEXT = "ENFORCED_CONTEXT";
static Logger logger = Logger.getLogger(ConfigServiceFactory.class);
public static ConfigService getConfigService(){
@@ -33,7 +35,7 @@ public static String getCurrentContextId(){
}
public static String getCurrentContextId(HttpServletRequest req){
try {
- org.edu_sharing.alfresco.service.config.model.Context context = getConfigService().getContext(getCurrentDomain(req));
+ org.edu_sharing.alfresco.service.config.model.Context context = getConfigService().getContextByDomain(getCurrentDomain(req));
if(context == null) {
return null;
}
@@ -43,7 +45,7 @@ public static String getCurrentContextId(HttpServletRequest req){
return null;
}
}
- public static Config getCurrentConfig(ServletRequest req) throws Exception {
+ public static Config getCurrentConfig(HttpServletRequest req) throws Exception {
try {
return getConfigService().getConfigByDomain(req==null ? getCurrentDomain() : getCurrentDomain(req));
}catch(Throwable t) {
@@ -54,12 +56,42 @@ public static Config getCurrentConfig(ServletRequest req) throws Exception {
public static String getCurrentDomain() {
return getCurrentDomain(Context.getCurrentInstance().getRequest());
}
- public static String getCurrentDomain(ServletRequest req) {
+
+ public static String getCurrentDomain(HttpServletRequest req) {
+ Object enforcedContext = req.getSession().getAttribute(ENFORCED_CONTEXT);
+ if(StringUtils.isNotBlank((String)enforcedContext)){
+ return enforcedContext.toString();
+ }
+
String domain = new RequestHelper(req).getServerName();
logger.debug("current domain:" + domain);
return domain;
}
+ public static void enforceContext(String contextId){
+ try {
+ org.edu_sharing.alfresco.service.config.model.Context context = getConfigService().getContextById(contextId);
+ if(context == null){
+ throw new IllegalArgumentException(String.format("Context with contextId %s does not exists",contextId));
+ }
+
+ if(context.domain == null || context.domain.length == 0){
+ throw new IllegalArgumentException(String.format("Context %s doesn't has domains",contextId));
+ }
+
+ Optional domain = Arrays.stream(context.domain).findFirst();
+ Context.getCurrentInstance().getRequest().getSession().setAttribute(ENFORCED_CONTEXT, domain.get());
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void clearEnforcedContext(){
+ Context.getCurrentInstance().getRequest().getSession().removeAttribute(ENFORCED_CONTEXT);
+ }
+
public static List getLanguageData(List languages,String language) {
if(languages!=null && languages.size()>0) {
for(org.edu_sharing.alfresco.service.config.model.Language entry : languages) {
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java
index 4fdec3579..86e5087d1 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java
@@ -45,7 +45,8 @@ public class ConfigServiceImpl implements ConfigService, ApplicationListener[ configCache = AlfAppContextGate.getApplicationContext().getBean("eduSharingConfigCache", SimpleCache.class);
- private static SimpleCache contextCache = AlfAppContextGate.getApplicationContext().getBean("eduSharingContextCache", SimpleCache.class);
+ private static SimpleCache contextCacheByDomain = AlfAppContextGate.getApplicationContext().getBean("eduSharingContextCacheByDomain", SimpleCache.class);
+ private static SimpleCache contextCacheById = AlfAppContextGate.getApplicationContext().getBean("eduSharingContextCacheById", SimpleCache.class);
private static final Unmarshaller jaxbUnmarshaller;
private final ObjectMapper objectMapper = new ObjectMapper();
@@ -106,16 +107,26 @@ public void deleteContext(String id) throws Exception {
}
@Override
- public Context getContext(String domain) throws Exception {
- if(StringUtils.isBlank(domain)) {
+ public Context getContextByDomain(String domain) throws Exception {
+ if (StringUtils.isBlank(domain)) {
return null;
}
buildContextCache();
- return contextCache.get(domain);
+ return contextCacheByDomain.get(domain);
}
@Override
- public List getAvailableContext() throws Exception {
+ public Context getContextById(String id) throws Exception {
+ if (StringUtils.isBlank(id)) {
+ return null;
+ }
+
+ buildContextCache();
+ return contextCacheById.get(id);
+ }
+
+ @Override
+ public List getAvailableContext() {
return AuthenticationUtil.runAsSystem(() -> {
String eduSharingSystemFolderContext = userEnvironmentTool.getEdu_SharingContextFolder();
Map> dynamicContextObjects = nodeService.getChildrenPropsByType(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, eduSharingSystemFolderContext, CCConstants.CCM_TYPE_CONTEXT);
@@ -130,9 +141,7 @@ public List getAvailableContext() throws Exception {
}
private void buildContextCache() throws Exception {
- if (contextCache.getKeys().isEmpty()) {
- // put an element so that next time, the cache is never empty!
- contextCache.put("", null);
+ if (contextCacheByDomain.getKeys().isEmpty()) {
Config config = getConfig();
if (config.contexts != null && config.contexts.context != null) {
for (Context context : config.contexts.context) {
@@ -141,7 +150,7 @@ private void buildContextCache() throws Exception {
}
for (String dom : context.domain) {
- contextCache.put(dom, context);
+ contextCacheByDomain.put(dom, context);
}
}
}
@@ -155,13 +164,53 @@ private void buildContextCache() throws Exception {
.map(x -> x.get(CCConstants.CCM_PROP_CONTEXT_CONFIG).toString())
.map(CheckedFunction.wrap(x -> objectMapper.readValue(x, Context.class), null))
.filter(Objects::nonNull)
- .forEach(x -> Arrays.stream(x.domain).forEach(y -> contextCache.put(y, x)));
+ .forEach(x -> Arrays.stream(x.domain).filter(Objects::nonNull).forEach(y -> contextCacheByDomain.put(y, x)));
+
+ return null;
+ });
+
+
+
+ if(contextCacheByDomain.getKeys().isEmpty()){
+ // put an element so that next time, the cache is never empty!
+ contextCacheByDomain.put("", null);
+ }
+ }
+
+ if(contextCacheById.getKeys().isEmpty()){
+ Config config = getConfig();
+ if (config.contexts != null && config.contexts.context != null) {
+ for (Context context : config.contexts.context) {
+ if (StringUtils.isNotBlank(context.id)) {
+ contextCacheById.put(context.id, context);
+ }
+ }
+ }
+ AuthenticationUtil.runAsSystem(() -> {
+ String eduSharingSystemFolderContext = userEnvironmentTool.getEdu_SharingContextFolder();
+ Map> dynamicContextObjects = nodeService.getChildrenPropsByType(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, eduSharingSystemFolderContext, CCConstants.CCM_TYPE_CONTEXT);
+ dynamicContextObjects
+ .values()
+ .stream()
+ .map(x -> x.get(CCConstants.CCM_PROP_CONTEXT_CONFIG).toString())
+ .map(CheckedFunction.wrap(x -> objectMapper.readValue(x, Context.class), null))
+ .filter(Objects::nonNull)
+ .filter(x -> StringUtils.isNotBlank(x.id))
+ .forEach(x -> contextCacheById.put(x.id, x));
return null;
});
+
+ if(contextCacheById.getKeys().isEmpty()){
+ // put an element so that next time, the cache is never empty!
+ contextCacheById.put("", null);
+ }
}
}
+
+
+
@Override
public Context createOrUpdateContext(Context context) {
return AuthenticationUtil.runAsSystem(() -> {
@@ -183,7 +232,7 @@ public Context createOrUpdateContext(Context context) {
@Override
public Config getConfigByDomain(String domain) throws Exception {
- Context context = getContext(domain);
+ Context context = getContextByDomain(domain);
if (context == null) {
throw new IllegalArgumentException("Context with domain " + domain + " does not exists");
}
@@ -308,7 +357,7 @@ private void overrideValues(Values values, Values override) throws
private void refresh() {
configCache.clear();
- contextCache.clear();
+ contextCacheByDomain.clear();
try {
getConfig();
} catch (Exception e) {
diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/license/LicenseService.java b/Backend/services/core/src/main/java/org/edu_sharing/service/license/LicenseService.java
index 59bfc681a..2812f5465 100644
--- a/Backend/services/core/src/main/java/org/edu_sharing/service/license/LicenseService.java
+++ b/Backend/services/core/src/main/java/org/edu_sharing/service/license/LicenseService.java
@@ -4,7 +4,7 @@
import org.edu_sharing.repository.tools.URLHelper;
public class LicenseService {
-
+ private static String DEFAULT_LICENSE_VERSION = "4.0";
public String getIconUrl(String license,boolean dynamic){
if(license==null || license.isEmpty())
license="none";
@@ -58,7 +58,7 @@ public String getLicenseUrl(String license, String locale, String version){
}
if(result != null){
- version = (version == null) ? "3.0" : version;
+ version = (version == null) ? DEFAULT_LICENSE_VERSION : version;
if(result.contains("${version}")){
result = result.replace("${version}", version);
}
@@ -71,5 +71,5 @@ public String getLicenseUrl(String license, String locale, String version){
return result;
}
-
+
}
diff --git a/Backend/services/rest/api/src/main/resources/openapi.json b/Backend/services/rest/api/src/main/resources/openapi.json
index 724e4ebc5..079285d0a 100644
--- a/Backend/services/rest/api/src/main/resources/openapi.json
+++ b/Backend/services/rest/api/src/main/resources/openapi.json
@@ -11165,6 +11165,150 @@
]
}
},
+ "/admin/v1/repositoryConfig/enforceContext": {
+ "delete": {
+ "operationId": "clearEnforcedContext",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {}
+ },
+ "description": "OK."
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Preconditions are not present."
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Authorization failed."
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Session user has insufficient rights to perform this operation."
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Ressources are not found."
+ },
+ "500": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Fatal error occured."
+ }
+ },
+ "summary": "set/update the repository config object",
+ "tags": [
+ "ADMIN v1"
+ ]
+ }
+ },
+ "/admin/v1/repositoryConfig/enforceContext/{contextId}": {
+ "put": {
+ "operationId": "enforceContext",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "contextId",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {}
+ },
+ "description": "OK."
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Preconditions are not present."
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Authorization failed."
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Session user has insufficient rights to perform this operation."
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Ressources are not found."
+ },
+ "500": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Fatal error occured."
+ }
+ },
+ "summary": "set/update the repository config object",
+ "tags": [
+ "ADMIN v1"
+ ]
+ }
+ },
"/admin/v1/serverUpdate/list": {
"get": {
"description": "list available update tasks",
diff --git a/Frontend/src/app/features/mds/mds-editor/widgets/mds-editor-widget-license/license-details/license-details.component.ts b/Frontend/src/app/features/mds/mds-editor/widgets/mds-editor-widget-license/license-details/license-details.component.ts
index 9db094a36..ec679c049 100644
--- a/Frontend/src/app/features/mds/mds-editor/widgets/mds-editor-widget-license/license-details/license-details.component.ts
+++ b/Frontend/src/app/features/mds/mds-editor/widgets/mds-editor-widget-license/license-details/license-details.component.ts
@@ -57,11 +57,11 @@ export class LicenseDetailsComponent implements OnChanges {
if (license.indexOf('ND') !== -1) this.ccShare = 'ND';
if (license.indexOf('NC') !== -1) this.ccCommercial = 'NC';
- this.ccVersion = this.getValueForAll(
- RestConstants.CCM_PROP_LICENSE_CC_VERSION,
- this.ccVersion,
- );
- this.ccCountry = this.getValueForAll(RestConstants.CCM_PROP_LICENSE_CC_LOCALE);
+ // also see @LicenseService
+ this.ccVersion =
+ this.getValueForAll(RestConstants.CCM_PROP_LICENSE_CC_VERSION, this.ccVersion) ||
+ '4.0';
+ this.ccCountry = this.getValueForAll(RestConstants.CCM_PROP_LICENSE_CC_LOCALE) || 'DE';
}
if (license === 'CC_0') {
this.type = 'CC_0';
diff --git a/deploy/docker/pom.xml b/deploy/docker/pom.xml
index 52980929b..25735f76a 100644
--- a/deploy/docker/pom.xml
+++ b/deploy/docker/pom.xml
@@ -87,7 +87,7 @@
- 6.2.14
+ 7.4.1
]