merged development
This commit is contained in:
		
						commit
						a1660de341
					
				
					 10 changed files with 69 additions and 37 deletions
				
			
		
							
								
								
									
										12
									
								
								.github/workflows/buildReporting.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/buildReporting.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -53,6 +53,8 @@ jobs: | |||
|     - | ||||
|       name: Reporting | ||||
|       uses: codecov/codecov-action@v4 | ||||
|       env: | ||||
|         CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | ||||
|       with: | ||||
|         flags: unittests  | ||||
|         name: SEB Server Build  | ||||
|  | @ -92,7 +94,7 @@ jobs: | |||
|       uses: docker/setup-qemu-action@v3 | ||||
|     - | ||||
|       name: Set up Docker Buildx | ||||
|       uses: docker/setup-buildx-action@v2 | ||||
|       uses: docker/setup-buildx-action@v4 | ||||
|     - | ||||
|       name: Login to DockerHub | ||||
|       uses: docker/login-action@v2 | ||||
|  | @ -147,13 +149,13 @@ jobs: | |||
|         TAGS: ${{ steps.meta.outputs.tags }} | ||||
|          | ||||
|   cleanup: | ||||
|     needs: docker-build | ||||
|      # Run only on tagging | ||||
|     if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') | ||||
|     needs: [maven-build-reporting, docker-build] | ||||
|     if: | | ||||
|       always() | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - | ||||
|       name: Delete Artifacts | ||||
|       uses: geekyeggo/delete-artifact@v4 | ||||
|       uses: geekyeggo/delete-artifact@v5 | ||||
|       with: | ||||
|           name: Package | ||||
|  |  | |||
|  | @ -40,9 +40,6 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; | |||
| @Order(7) | ||||
| public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ErrorController { | ||||
| 
 | ||||
|     private static final String ERROR_PATH = "/sebserver/error"; | ||||
|     private static final String CHECK_PATH = "/sebserver/check"; | ||||
| 
 | ||||
|     @Value("${sebserver.webservice.http.redirect.gui}") | ||||
|     private String guiRedirect; | ||||
|     @Value("${sebserver.webservice.api.exam.endpoint.discovery}") | ||||
|  | @ -77,25 +74,11 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements E | |||
|         return new BCryptPasswordEncoder(4); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void configure(final WebSecurity web) { | ||||
|         web | ||||
|                 .ignoring() | ||||
|                 .antMatchers(ERROR_PATH) | ||||
|                 .antMatchers(CHECK_PATH) | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint) | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT) | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT + API.PASSWORD_PATH_SEGMENT) | ||||
|                 .antMatchers(this.adminAPIEndpoint + API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT + "/**") | ||||
|                 .antMatchers(this.adminAPIEndpoint + API.INFO_ENDPOINT + API.INFO_INST_PATH_SEGMENT + "/**") | ||||
|                 .antMatchers(this.adminAPIEndpoint + API.REGISTER_ENDPOINT); | ||||
|     } | ||||
| 
 | ||||
|     @RequestMapping(CHECK_PATH) | ||||
|     @RequestMapping(API.CHECK_PATH) | ||||
|     public void check() throws IOException { | ||||
|     } | ||||
| 
 | ||||
|     @RequestMapping(ERROR_PATH) | ||||
|     @RequestMapping(API.ERROR_PATH) | ||||
|     public void handleError(final HttpServletResponse response) throws IOException { | ||||
|         response.getOutputStream().print(response.getStatus()); | ||||
|         response.setHeader(HttpHeaders.LOCATION, this.guiRedirect); | ||||
|  |  | |||
|  | @ -12,6 +12,9 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; | |||
| 
 | ||||
| public final class API { | ||||
| 
 | ||||
|     public static final String ERROR_PATH = "/sebserver/error"; | ||||
|     public static final String CHECK_PATH = "/sebserver/check"; | ||||
| 
 | ||||
|     public enum BulkActionType { | ||||
|         HARD_DELETE, | ||||
|         DEACTIVATE, | ||||
|  |  | |||
|  | @ -281,7 +281,7 @@ public final class Exam implements GrantEntity { | |||
|             } | ||||
|             return result; | ||||
|         } else { | ||||
|             return null; | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,6 +42,10 @@ public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter { | |||
|     private String remoteProctoringViewServletEndpoint; | ||||
|     @Value("${springdoc.api-docs.enabled:false}") | ||||
|     private boolean springDocsAPIEnabled; | ||||
|     @Value("${sebserver.webservice.api.exam.endpoint.discovery}") | ||||
|     private String examAPIDiscoveryEndpoint; | ||||
|     @Value("${sebserver.webservice.api.admin.endpoint}") | ||||
|     private String adminAPIEndpoint; | ||||
| 
 | ||||
|     /** Gui-service related public URLS from spring web security perspective */ | ||||
|     public static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher( | ||||
|  | @ -52,28 +56,42 @@ public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter { | |||
|             // project specific static resources | ||||
|             new AntPathRequestMatcher("/images/**"), | ||||
| 
 | ||||
|             new AntPathRequestMatcher("/favicon.ico")); | ||||
|             new AntPathRequestMatcher("/favicon.ico") | ||||
|     ); | ||||
| 
 | ||||
|     @Override | ||||
|     public void configure(final WebSecurity web) { | ||||
|         web | ||||
|             .ignoring() | ||||
|                 .requestMatchers(PUBLIC_URLS) | ||||
|             .antMatchers(this.guiEntryPoint) | ||||
|                 .antMatchers(this.remoteProctoringEndpoint) | ||||
|                 .antMatchers(this.remoteProctoringEndpoint + this.remoteProctoringViewServletEndpoint + "/*"); | ||||
|         ; | ||||
| 
 | ||||
|         if (this.springDocsAPIEnabled) { | ||||
|             web.ignoring().antMatchers("/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|     public void configure(final HttpSecurity http) throws Exception { | ||||
|         http | ||||
|                 .sessionManagement() | ||||
|                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||||
|                 .and() | ||||
|                 .authorizeRequests() | ||||
|                 .antMatchers(this.remoteProctoringEndpoint).permitAll() | ||||
|                 .antMatchers(this.remoteProctoringEndpoint + this.remoteProctoringViewServletEndpoint + "/*").permitAll() | ||||
|                 .requestMatchers(PUBLIC_URLS).permitAll() | ||||
|                 .antMatchers(API.ERROR_PATH).permitAll() | ||||
|                 .antMatchers(API.CHECK_PATH).permitAll() | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint).permitAll() | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT).permitAll() | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT + API.PASSWORD_PATH_SEGMENT).permitAll() | ||||
|                 .antMatchers(adminAPIEndpoint + API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT + "/**").permitAll() | ||||
|                 .antMatchers(adminAPIEndpoint + API.INFO_ENDPOINT + API.INFO_INST_PATH_SEGMENT + "/**").permitAll() | ||||
|                 .antMatchers(adminAPIEndpoint + API.REGISTER_ENDPOINT).permitAll() | ||||
|                 .and() | ||||
|                 .antMatcher("/**") | ||||
|                 .authorizeRequests() | ||||
|                 .anyRequest() | ||||
|  |  | |||
|  | @ -57,6 +57,8 @@ public class ExamIndicatorsList implements TemplateComposer { | |||
|             new LocTextKey("sebserver.exam.indicator.list.pleaseSelect"); | ||||
|     private static final LocTextKey INDICATOR_EMPTY_LIST_MESSAGE = | ||||
|             new LocTextKey("sebserver.exam.indicator.list.empty"); | ||||
|     private static final LocTextKey CONFIRM_MESSAGE_REMOVE_INDICATOR = | ||||
|             new LocTextKey("sebserver.exam.indicator.list.delete.confirm"); | ||||
| 
 | ||||
|     private final PageService pageService; | ||||
|     private final ResourceService resourceService; | ||||
|  | @ -144,6 +146,7 @@ public class ExamIndicatorsList implements TemplateComposer { | |||
|                         indicatorTable::getMultiSelection, | ||||
|                         this::deleteSelectedIndicator, | ||||
|                         INDICATOR_EMPTY_SELECTION_TEXT_KEY) | ||||
|                 .withConfirm(() -> CONFIRM_MESSAGE_REMOVE_INDICATOR) | ||||
|                 .publishIf(() -> indicatorEnabled && !isLight && editable && indicatorTable.hasAnyContent(), false) | ||||
| 
 | ||||
|                 .newAction(ActionDefinition.EXAM_INDICATOR_NEW) | ||||
|  |  | |||
|  | @ -32,11 +32,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueCon | |||
| @WebServiceProfile | ||||
| public class RealNumberConverter implements AttributeValueConverter { | ||||
| 
 | ||||
|     private static final Logger log = LoggerFactory.getLogger(IntegerConverter.class); | ||||
|     private static final Logger log = LoggerFactory.getLogger(RealNumberConverter.class); | ||||
| 
 | ||||
|     public static final Set<String> SUPPORTED_ATTR_NAMES = Utils.immutableSetOf( | ||||
|             "defaultPageZoomLevel", | ||||
|             "defaultTextZoomLevel"); | ||||
|             "defaultTextZoomLevel", | ||||
|             "screenProctoringImageDownscale"); | ||||
| 
 | ||||
|     private static final String XML_TEMPLATE = "<key>%s</key><real>%s</real>"; | ||||
|     private static final String JSON_TEMPLATE = "\"%s\":%s"; | ||||
|  | @ -89,6 +90,12 @@ public class RealNumberConverter implements AttributeValueConverter { | |||
|             realVal = 0; | ||||
|         } | ||||
| 
 | ||||
|         // NOTE: this is a special case for screenProctoringImageDownscale selector to get the selected real value | ||||
|         //       from the selection-index instead using the index. See SEBSERV-527 | ||||
|         if ("screenProctoringImageDownscale".equals(attribute.name)) { | ||||
|             realVal = realVal / 10.0 + 1.0; | ||||
|         } | ||||
| 
 | ||||
|         out.write(Utils.toByteArray(String.format( | ||||
|                 template, | ||||
|                 AttributeValueConverter.extractName(attribute), | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ import java.io.IOException; | |||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| 
 | ||||
| import ch.ethz.seb.sebserver.gbl.api.API; | ||||
| import org.apache.catalina.filters.RemoteIpFilter; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | @ -50,18 +51,18 @@ import ch.ethz.seb.sebserver.webservice.weblayer.oauth.WebClientDetailsService; | |||
| import ch.ethz.seb.sebserver.webservice.weblayer.oauth.WebserviceResourceConfiguration; | ||||
| 
 | ||||
| /** This is the main web-security Spring configuration for SEB-Server webservice API | ||||
|  * | ||||
|  * <p> | ||||
|  * Currently two separated Rest API's are implemented, one for administration and maintenance | ||||
|  * of the SEB-Server (AdminAPI) and one for SEB-Client connection on running exams and eventually | ||||
|  * also for LMS communication), if needed (ExamAPI). The AdministrationAPI uses OAuth 2 password | ||||
|  * grant with refresh-token, same as in the prototype and the ExamAPI uses the client_credential grant. | ||||
|  * | ||||
|  * <p> | ||||
|  * There is a Spring Authorization-Server defining this two clients (AdminAPIClient and ExamAPIClient) as well as | ||||
|  * two Spring Resource-Server for the separation of the different API's | ||||
|  * | ||||
|  * <p> | ||||
|  * The endpoint of the AdministrationAPI can be configured within the key; sebserver.webservice.api.admin.endpoint | ||||
|  * and is by default set to "/admin-api/**" | ||||
|  * | ||||
|  * <p> | ||||
|  * The endpoint of the ExamAPI can be configured within the key; sebserver.webservice.api.exam.endpoint | ||||
|  * and is by default set to "/exam-api/**" */ | ||||
| @WebServiceProfile | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ package ch.ethz.seb.sebserver.webservice.weblayer.oauth; | |||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import ch.ethz.seb.sebserver.gbl.api.API; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.security.authentication.AuthenticationManager; | ||||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||||
| import org.springframework.security.config.http.SessionCreationPolicy; | ||||
|  | @ -30,6 +32,8 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf | |||
|     public static final String ADMIN_API_RESOURCE_ID = "seb-server-administration-api"; | ||||
|     /** The resource identifier of the Exam API resources */ | ||||
|     public static final String EXAM_API_RESOURCE_ID = "seb-server-exam-api"; | ||||
|     @Value("${sebserver.webservice.api.exam.endpoint.discovery}") | ||||
|     private String examAPIDiscoveryEndpoint; | ||||
| 
 | ||||
|     public WebserviceResourceConfiguration( | ||||
|             final TokenStore tokenStore, | ||||
|  | @ -74,6 +78,16 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf | |||
|                 .sessionManagement() | ||||
|                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||||
|                 .and() | ||||
|                 .authorizeRequests() | ||||
|                 .antMatchers(API.ERROR_PATH).permitAll() | ||||
|                 .antMatchers(API.CHECK_PATH).permitAll() | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint).permitAll() | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT).permitAll() | ||||
|                 .antMatchers(this.examAPIDiscoveryEndpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT + API.PASSWORD_PATH_SEGMENT).permitAll() | ||||
|                 .antMatchers(configurerAdapter.apiEndpoint + API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT + "/**").permitAll() | ||||
|                 .antMatchers(configurerAdapter.apiEndpoint + API.INFO_ENDPOINT + API.INFO_INST_PATH_SEGMENT + "/**").permitAll() | ||||
|                 .antMatchers(configurerAdapter.apiEndpoint + API.REGISTER_ENDPOINT).permitAll() | ||||
|                 .and() | ||||
|                 .antMatcher(configurerAdapter.apiEndpoint + "/**") | ||||
|                 .authorizeRequests() | ||||
|                 .anyRequest() | ||||
|  |  | |||
|  | @ -709,6 +709,7 @@ sebserver.exam.indicator.list.column.thresholds=Thresholds | |||
| sebserver.exam.indicator.list.column.thresholds.tooltip=The thresholds of the indicator | ||||
| sebserver.exam.indicator.list.empty=There is currently no indicator defined for this exam. Please create a new one | ||||
| sebserver.exam.indicator.list.pleaseSelect=At first please select an indicator from the list | ||||
| sebserver.exam.indicator.list.delete.confirm=Are you sure to delete the selected Indicator from the Exam? | ||||
| 
 | ||||
| sebserver.exam.clientgroup.list.actions=  | ||||
| sebserver.exam.clientgroup.list.title=Client Groups | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti