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 @@
<groupId>org.codeability.sharing.demo</groupId>
<artifactId>plugin-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.1.2-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Plugin Demo</name>
......@@ -111,7 +111,7 @@
<dependency>
<groupId>org.codeability.sharing</groupId>
<artifactId>SharingPluginPlatformAPI</artifactId>
<version>0.1.0-Snapshot</version>
<version>0.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-client -->
<dependency>
......
......@@ -60,7 +60,9 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.antMatchers("/content/**")
.antMatchers("/h2-console/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/api/sharingPluginConfig")
.antMatchers("/test/**");
}
@Override
......
package org.codeability.sharing.demo.config;
import io.github.jhipster.config.JHipsterConstants;
import io.github.jhipster.config.JHipsterProperties;
import io.github.jhipster.config.h2.H2ConfigurationHelper;
import static java.net.URLDecoder.decode;
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.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.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
......@@ -17,14 +26,9 @@ import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import javax.servlet.*;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.*;
import static java.net.URLDecoder.decode;
import io.github.jhipster.config.JHipsterConstants;
import io.github.jhipster.config.JHipsterProperties;
import io.github.jhipster.config.h2.H2ConfigurationHelper;
/**
* Configuration of web application with Servlet 3.0 APIs.
......
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.data.domain.Page;
import org.springframework.data.domain.Pageable;
......@@ -9,9 +10,6 @@ import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
/**
* Spring Data JPA repository for the {@link User} entity.
*/
......
......@@ -7,7 +7,12 @@ import java.util.UUID;
public class OAuthIdpTokenResponseDTO implements Serializable {
@JsonProperty("token_type")
/**
*
*/
private static final long serialVersionUID = 1L;
@JsonProperty("token_type")
private String tokenType;
private String scope;
......
......@@ -63,7 +63,9 @@ public class SharingDemoService {
restClientConfig.register(SearchResultsDTO.class);
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.
request().
......
......@@ -7,10 +7,62 @@ import org.springframework.beans.factory.annotation.Value;
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
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.
......@@ -19,23 +71,28 @@ public class SharingPluginService {
@Value("${application.pluginToken}")
private String pluginToken;
/**
* the base url for call backs
*/
private String apiBaseUrl = null;
private SharingPluginInfo sharingPluginInfo;
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 boolean validate(String accessToken, String apiBaseUrl) {
public boolean validate(String accessToken, String apiBaseUrl, String applicationName) {
boolean valid = pluginToken.equals(accessToken);
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;
}
......@@ -55,7 +112,8 @@ public class SharingPluginService {
}
public String getApiBaseUrl() {
return apiBaseUrl;
if(sharingPluginInfo==null) return null;
return sharingPluginInfo.getApiBaseUrl();
}
}
package org.codeability.sharing.demo.web.rest;
import java.security.Principal;
import org.codeability.sharing.demo.service.UserService;
import org.codeability.sharing.demo.service.dto.UserDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
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.
......@@ -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;
......@@ -45,7 +44,6 @@ public class AccountResource {
* @throws AccountResourceException {@code 500 (Internal Server Error)} if the user couldn't be returned.
*/
@GetMapping("/account")
@SuppressWarnings("unchecked")
public UserDTO getAccount(Principal principal) {
if (principal instanceof AbstractAuthenticationToken) {
return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal);
......
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.plugins.api.SharingPluginConfig;
import org.slf4j.Logger;
......@@ -8,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
......@@ -33,19 +37,28 @@ public class SharingSupportResource {
this.sharingPluginService = sharingPluginService;
}
/**
* Returns Sharing Plugin configuration
*
* @return Sharing Plugin configuration
*/
@GetMapping("/sharingPluginConfig")
public ResponseEntity<SharingPluginConfig> getConfig(@RequestParam String accessToken, @RequestParam String apiBaseUrl) {
if(!sharingPluginService.validate(accessToken, apiBaseUrl)) {
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"));
}
/**
* Returns Sharing Plugin configuration
*
* @return Sharing Plugin configuration
*/
@GetMapping("/sharingPluginConfig")
public ResponseEntity<SharingPluginConfig> getConfig(@RequestHeader("Authorization") String bearer,
@RequestParam String apiBaseUrl, @RequestParam String installationName) {
Pattern p = Pattern.compile("Bearer\\s*(.+)");
Matcher m = p.matcher(bearer);
if (m.matches()) {
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;
import java.util.List;
import org.codeability.sharing.demo.config.Constants;
import org.codeability.sharing.demo.security.AuthoritiesConstants;
import org.codeability.sharing.demo.service.UserService;
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.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
......@@ -18,10 +15,14 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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 java.util.*;
import io.github.jhipster.web.util.PaginationUtil;
import io.github.jhipster.web.util.ResponseUtil;
/**
* REST controller for managing users.
......
......@@ -6,8 +6,7 @@ import { HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { SharingSearchService } from '../..//sharing/search/sharingSearch.service'
import { SearchRequest } from '../../shared/model/search/search-input.model';
import { SearchResultsDTO } from '../../shared/model/search/search-results-dto.model'
import { SearchRequest, SearchResultsDTO } from '../../shared/model/connector-dtos.model';
@Component({
......
import { MetadataSearchInput } from './metadata-search-input.model';
import {IExerciseType } from './exercise.model';
export class SearchResultsDTO {
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() {
this.keyword = '';
this.programmingLanguage = '';
this.naturalLanguage = [];
this.license = '';
this.author = '';
this.types = [];
}
}
export class SearchInput {
public fulltextQuery: string;
......@@ -44,3 +148,6 @@ export class SearchRequest {
import { Person } from './person.model';
import { SearchResultDTO } from './search-result-dto.model';
export enum IExerciseType {
COLLECTION = 'collection',
PROGRAMMING_EXERCISE = 'programming exercise',
EXERCISE = 'exercise',
OTHER = 'other',
}
// just a cheap trick, to make enum available to HTML.
// see https://stackoverflow.com/questions/35835984/how-to-use-a-typescript-enum-value-in-an-angular2-ngswitch-statement
// export function IExerciseTypeAware(constructor: Function) {
// constructor.prototype.IExerciseType = IExerciseType;
// }
// export class IExerciseTypeClass {
// myEnum: typeof IExerciseType;
// myEnumField: IExerciseType;
// }
export interface Exercise {
// from metadata (required)
title: string;
license: string;
// from metadata (optional)
description: string;
programmingLanguages: string[];
languages: string[];
creators: Person[];
publisher: Person[];
contributor: Person[];
requires: string[];
imageURL: string;
timeRequired: string;
deprecated: boolean;
difficulty: string;
educationLevel: string;
format: Array<string>;
keyword: Array<string>;
// language: Array<string>;
// repositoryURL: string;
// source: Array<string>;
status: string;
// structure: string;
type: IExerciseType;
structure: string;
version: string;
metadataVersion: string;
gitlabURL: string;
// not in metadata
rating: number;
lastUpdate: Date;
originalResult: SearchResultDTO;
// thesis
views: number;
downloads: number;
}
export interface MetadataFileDTO {
filename: string;
path: string;
commit_id: string;
indexing_date: Date;
}
import {IExerciseType } from './exercise.model';
export class MetadataSearchInput {
public keyword: string;
public programmingLanguage: string;
public naturalLanguage: string;
public license: string;
public author: string;
public types: Array<IExerciseType>
public constructor() {
this.keyword = '';
this.programmingLanguage = '';
this.naturalLanguage = '';
this.license = '';
this.author = '';
this.types = [];
}
}
export interface Person {
name: string;
email: string;
affiliation: string;
}