This is the codeAbility Sharing Platform! Learn more about the codeAbility Sharing Platform.

Commit fc751be5 authored by Michael Breu's avatar Michael Breu 💬
Browse files

Diverse Korrekturen und Anpassungen für Connector V0.1.2

parent a4ca8d49
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<groupId>org.codeability.sharing.demo</groupId> <groupId>org.codeability.sharing.demo</groupId>
<artifactId>plugin-demo</artifactId> <artifactId>plugin-demo</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.1.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Plugin Demo</name> <name>Plugin Demo</name>
...@@ -111,7 +111,7 @@ ...@@ -111,7 +111,7 @@
<dependency> <dependency>
<groupId>org.codeability.sharing</groupId> <groupId>org.codeability.sharing</groupId>
<artifactId>SharingPluginPlatformAPI</artifactId> <artifactId>SharingPluginPlatformAPI</artifactId>
<version>0.1.0-Snapshot</version> <version>0.1.2</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-client --> <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-client -->
<dependency> <dependency>
......
...@@ -60,7 +60,9 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { ...@@ -60,7 +60,9 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.antMatchers("/content/**") .antMatchers("/content/**")
.antMatchers("/h2-console/**") .antMatchers("/h2-console/**")
.antMatchers("/swagger-ui/index.html") .antMatchers("/swagger-ui/index.html")
.antMatchers("/api/sharingPluginConfig")
.antMatchers("/test/**"); .antMatchers("/test/**");
} }
@Override @Override
......
package org.codeability.sharing.demo.config; package org.codeability.sharing.demo.config;
import io.github.jhipster.config.JHipsterConstants; import static java.net.URLDecoder.decode;
import io.github.jhipster.config.JHipsterProperties;
import io.github.jhipster.config.h2.H2ConfigurationHelper; import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.web.server.*; import org.springframework.boot.web.server.MimeMappings;
import org.springframework.boot.web.server.WebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -17,14 +26,9 @@ import org.springframework.web.cors.CorsConfiguration; ...@@ -17,14 +26,9 @@ import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; import org.springframework.web.filter.CorsFilter;
import javax.servlet.*; import io.github.jhipster.config.JHipsterConstants;
import java.io.File; import io.github.jhipster.config.JHipsterProperties;
import java.io.UnsupportedEncodingException; import io.github.jhipster.config.h2.H2ConfigurationHelper;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.*;
import static java.net.URLDecoder.decode;
/** /**
* Configuration of web application with Servlet 3.0 APIs. * Configuration of web application with Servlet 3.0 APIs.
......
package org.codeability.sharing.demo.repository; package org.codeability.sharing.demo.repository;
import org.codeability.sharing.demo.domain.User; import java.util.Optional;
import org.codeability.sharing.demo.domain.User;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
...@@ -9,9 +10,6 @@ import org.springframework.data.jpa.repository.EntityGraph; ...@@ -9,9 +10,6 @@ import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
/** /**
* Spring Data JPA repository for the {@link User} entity. * Spring Data JPA repository for the {@link User} entity.
*/ */
......
...@@ -7,7 +7,12 @@ import java.util.UUID; ...@@ -7,7 +7,12 @@ import java.util.UUID;
public class OAuthIdpTokenResponseDTO implements Serializable { public class OAuthIdpTokenResponseDTO implements Serializable {
@JsonProperty("token_type") /**
*
*/
private static final long serialVersionUID = 1L;
@JsonProperty("token_type")
private String tokenType; private String tokenType;
private String scope; private String scope;
......
...@@ -63,7 +63,9 @@ public class SharingDemoService { ...@@ -63,7 +63,9 @@ public class SharingDemoService {
restClientConfig.register(SearchResultsDTO.class); restClientConfig.register(SearchResultsDTO.class);
Client client = ClientBuilder.newClient(restClientConfig); Client client = ClientBuilder.newClient(restClientConfig);
WebTarget target = client.target(sharingPluginService.getApiBaseUrl()+"/pluginIF/v0.1/page-details"); final String apiBaseUrl = sharingPluginService.getApiBaseUrl();
if(apiBaseUrl==null) throw new IOException("No api URL for Sharing Platform defined!");
WebTarget target = client.target(apiBaseUrl+"/pluginIF/v0.1/page-details");
SearchResultsDTO results = target. SearchResultsDTO results = target.
request(). request().
......
...@@ -7,10 +7,62 @@ import org.springframework.beans.factory.annotation.Value; ...@@ -7,10 +7,62 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
* Service to support Sharing Plattform functionality as a plugin. * Service to support Sharing Connector functionality for the sharing connector interface.
*/ */
@Service @Service
public class SharingPluginService { public class SharingPluginService {
public static class SharingPluginInfo {
/**
* the base url for call backs
*/
private String apiBaseUrl = null;
/**
* the sharing platform installation name
*/
private String installationName = null;
/**
*
* @param apiBaseUrl
* @param installationName
*/
public SharingPluginInfo(String apiBaseUrl, String installationName) {
super();
this.apiBaseUrl = apiBaseUrl;
this.installationName = installationName;
}
public SharingPluginInfo() {
// JSON
}
/**
* @return the apiBaseUrl
*/
public String getApiBaseUrl() {
return apiBaseUrl;
}
/**
* @param apiBaseUrl the apiBaseUrl to set
*/
public void setApiBaseUrl(String apiBaseUrl) {
this.apiBaseUrl = apiBaseUrl;
}
/**
* @return the installationName
*/
public String getInstallationName() {
return installationName;
}
/**
* @param installationName the installationName to set
*/
public void setInstallationName(String installationName) {
this.installationName = installationName;
}
}
/** /**
* the authorization token. * the authorization token.
...@@ -19,23 +71,28 @@ public class SharingPluginService { ...@@ -19,23 +71,28 @@ public class SharingPluginService {
@Value("${application.pluginToken}") @Value("${application.pluginToken}")
private String pluginToken; private String pluginToken;
/** private SharingPluginInfo sharingPluginInfo;
* the base url for call backs
*/
private String apiBaseUrl = null;
private final Logger log = LoggerFactory.getLogger(SharingPluginService.class); /**
* @return the sharingPluginInfo
*/
public SharingPluginInfo getSharingPluginInfo() {
return sharingPluginInfo;
}
private final Logger log = LoggerFactory.getLogger(SharingPluginService.class);
public SharingPluginService() { public SharingPluginService() {
} }
public boolean validate(String accessToken, String apiBaseUrl) { public boolean validate(String accessToken, String apiBaseUrl, String applicationName) {
boolean valid = pluginToken.equals(accessToken); boolean valid = pluginToken.equals(accessToken);
if(valid) { if(valid) {
this.apiBaseUrl = apiBaseUrl; this.sharingPluginInfo = new SharingPluginInfo(apiBaseUrl, applicationName);
} }
log.info("Sharing Platform \"{}\" requested config with apiBaseURL {}: valid={}", applicationName, apiBaseUrl, valid);
return valid; return valid;
} }
...@@ -55,7 +112,8 @@ public class SharingPluginService { ...@@ -55,7 +112,8 @@ public class SharingPluginService {
} }
public String getApiBaseUrl() { public String getApiBaseUrl() {
return apiBaseUrl; if(sharingPluginInfo==null) return null;
return sharingPluginInfo.getApiBaseUrl();
} }
} }
package org.codeability.sharing.demo.web.rest; package org.codeability.sharing.demo.web.rest;
import java.security.Principal;
import org.codeability.sharing.demo.service.UserService; import org.codeability.sharing.demo.service.UserService;
import org.codeability.sharing.demo.service.dto.UserDTO; import org.codeability.sharing.demo.service.dto.UserDTO;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
/** /**
* REST controller for managing the current user's account. * REST controller for managing the current user's account.
...@@ -29,7 +27,8 @@ public class AccountResource { ...@@ -29,7 +27,8 @@ public class AccountResource {
} }
} }
private final Logger log = LoggerFactory.getLogger(AccountResource.class); @SuppressWarnings("unused")
private final Logger log = LoggerFactory.getLogger(AccountResource.class);
private final UserService userService; private final UserService userService;
...@@ -45,7 +44,6 @@ public class AccountResource { ...@@ -45,7 +44,6 @@ public class AccountResource {
* @throws AccountResourceException {@code 500 (Internal Server Error)} if the user couldn't be returned. * @throws AccountResourceException {@code 500 (Internal Server Error)} if the user couldn't be returned.
*/ */
@GetMapping("/account") @GetMapping("/account")
@SuppressWarnings("unchecked")
public UserDTO getAccount(Principal principal) { public UserDTO getAccount(Principal principal) {
if (principal instanceof AbstractAuthenticationToken) { if (principal instanceof AbstractAuthenticationToken) {
return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal); return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal);
......
package org.codeability.sharing.demo.web.rest; package org.codeability.sharing.demo.web.rest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.codeability.sharing.demo.service.SharingPluginService; import org.codeability.sharing.demo.service.SharingPluginService;
import org.codeability.sharing.plugins.api.SharingPluginConfig; import org.codeability.sharing.plugins.api.SharingPluginConfig;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -8,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value; ...@@ -8,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
...@@ -33,19 +37,28 @@ public class SharingSupportResource { ...@@ -33,19 +37,28 @@ public class SharingSupportResource {
this.sharingPluginService = sharingPluginService; this.sharingPluginService = sharingPluginService;
} }
/** /**
* Returns Sharing Plugin configuration * Returns Sharing Plugin configuration
* *
* @return Sharing Plugin configuration * @return Sharing Plugin configuration
*/ */
@GetMapping("/sharingPluginConfig") @GetMapping("/sharingPluginConfig")
public ResponseEntity<SharingPluginConfig> getConfig(@RequestParam String accessToken, @RequestParam String apiBaseUrl) { public ResponseEntity<SharingPluginConfig> getConfig(@RequestHeader("Authorization") String bearer,
if(!sharingPluginService.validate(accessToken, apiBaseUrl)) { @RequestParam String apiBaseUrl, @RequestParam String installationName) {
return ResponseEntity.badRequest().headers(io.github.jhipster.web.util.HeaderUtil.createFailureAlert(applicationName, true, "PluginConfig", "Token invalid", Pattern p = Pattern.compile("Bearer\\s*(.+)");
"Token not valid. Request ignored.")).build();
Matcher m = p.matcher(bearer);
} if (m.matches()) {
return ResponseEntity.ok(sharingPluginService.getPluginConfig("/api")); String accessToken = m.group(1);
} if (!sharingPluginService.validate(accessToken, apiBaseUrl, installationName)) {
return ResponseEntity.badRequest()
.headers(io.github.jhipster.web.util.HeaderUtil.createFailureAlert(applicationName, true,
"PluginConfig", "Token invalid", "Token not valid. Request ignored."))
.build();
}
}
return ResponseEntity.ok(sharingPluginService.getPluginConfig("/api"));
}
} }
package org.codeability.sharing.demo.web.rest; package org.codeability.sharing.demo.web.rest;
import java.util.List;
import org.codeability.sharing.demo.config.Constants; import org.codeability.sharing.demo.config.Constants;
import org.codeability.sharing.demo.security.AuthoritiesConstants; import org.codeability.sharing.demo.security.AuthoritiesConstants;
import org.codeability.sharing.demo.service.UserService; import org.codeability.sharing.demo.service.UserService;
import org.codeability.sharing.demo.service.dto.UserDTO; import org.codeability.sharing.demo.service.dto.UserDTO;
import io.github.jhipster.web.util.HeaderUtil;
import io.github.jhipster.web.util.PaginationUtil;
import io.github.jhipster.web.util.ResponseUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
...@@ -18,10 +15,14 @@ import org.springframework.http.HttpHeaders; ...@@ -18,10 +15,14 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.util.*; import io.github.jhipster.web.util.PaginationUtil;
import io.github.jhipster.web.util.ResponseUtil;
/** /**
* REST controller for managing users. * REST controller for managing users.
......
...@@ -6,8 +6,7 @@ import { HttpResponse } from '@angular/common/http'; ...@@ -6,8 +6,7 @@ import { HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { SharingSearchService } from '../..//sharing/search/sharingSearch.service' import { SharingSearchService } from '../..//sharing/search/sharingSearch.service'
import { SearchRequest } from '../../shared/model/search/search-input.model'; import { SearchRequest, SearchResultsDTO } from '../../shared/model/connector-dtos.model';
import { SearchResultsDTO } from '../../shared/model/search/search-results-dto.model'
@Component({ @Component({
......
import { MetadataSearchInput } from './metadata-search-input.model'; export class SearchResultsDTO {
import {IExerciseType } from './exercise.model'; hitCount = 0;
pageStartIndex = 0;
searchResult: SearchResultDTO[] = [];
}
export interface SearchResultDTO {
project: ProjectDTO;
file: MetadataFileDTO;
metadata: UserProvidedMetadataDTO;
ranking5: number;
supportedActions: PluginActionInfo[];
views: number;
downloads: number;
}
export interface PluginActionInfo {
plugin: string;
action: string;
commandName: string;
}
export interface UserProvidedMetadataDTO {
contributor: Array<Person>;
creator: Array<Person>;
deprecated: boolean;
description: string;
difficulty: string;
educationLevel: string;
format: Array<string>;
identifier: string;
image: string;
keyword: Array<string>;
language: Array<string>;
license: string;
metadataVersion: string;
programmingLanguage: Array<string>;
collectionContent: Array<string>;
publisher: Array<Person>;
requires: Array<string>;
source: Array<string>;
status: string;
structure: string;
timeRequired: string;
title: string;
type: IExerciseType;
version: string;
}
export interface Person {
name: string;
email: string;
affiliation: string;
}
export enum IExerciseType {
COLLECTION = 'collection',
PROGRAMMING_EXERCISE = 'programming exercise',
EXERCISE = 'exercise',
OTHER = 'other',
}
export interface ProjectDTO {
project_id: string;
project_name: string;
namespace: string;
main_group: string;
sub_group: string;
url: string;
last_activity_at: Date;
}
export interface MetadataFileDTO {
filename: string;
path: string;
commit_id: string;
indexing_date: Date;
}
export type ShoppingBasket = {
exerciseInfo: Array<SearchResultDTO>;
userInfo: UserInfo;
tokenValidUntil: number;
};
export type UserInfo = {
email: string;
};
export class MetadataSearchInput {
public keyword: string;
public programmingLanguage: string;
public naturalLanguage: Array<string>;
public license: string;
public author: string;
public types: Array<IExerciseType>
public constructor() {