diff options
Diffstat (limited to 'ecomp-portal-widget-ms/widget-ms')
49 files changed, 3548 insertions, 0 deletions
diff --git a/ecomp-portal-widget-ms/widget-ms/.gitignore b/ecomp-portal-widget-ms/widget-ms/.gitignore new file mode 100644 index 00000000..172a425c --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/.gitignore @@ -0,0 +1,39 @@ +.classpath +.project +/bin/ +target/ +logs/ +DEV_HOME_IS_UNDEFINED/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.factorypath +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +/target/ +/catalina.base_IS_UNDEFINED/ +.mvn +.settings/ +.springBeans +bin/ +debug-logs/ +logs/ +/application.properties +mvnw +mvnw.cmd diff --git a/ecomp-portal-widget-ms/widget-ms/README.md b/ecomp-portal-widget-ms/widget-ms/README.md new file mode 100644 index 00000000..ceb9dd2b --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/README.md @@ -0,0 +1,189 @@ +# Portal Widget Microservice + +For security, the server listens only on localhost (127.0.0.1) and requires HTTP Basic +Authentication. No outside network traffic is accepted or processed (packets never leave +the host). Currently, the server uses a self signed certificate - details below. + +## Build Prerequisites + +1. Java version 1.8 +2. Maven version 3 +3. Connectivity to AT&T Maven Central + +## Run Prerequisites + +1. Java version 1.8 +2. A Mysql database using the same database as the Portal + +## Build and Package + +Use maven to build and package the microservice into a jar using this command: + + mvn clean package + +## Configuring + +All configuration parameters are entered in a file called application.properties. A version with default values can be found in the top level of this project. + +Details about the database are configured in this file. The default entries for the database configuration are shown here: + + spring.datasource.url=jdbc:mariadb:failover://{db_host:db_port/{portal_db} + spring.datasource.username={username} + spring.datasource.password=ENC({encrypted_password}) + +The HTTP server's username and password are configured in this file. Only one username/password is used to secure the REST endpoint. The default entries for the server are shown here: + + security.user.name={basic_auth_username} + security.user.password=ENC({encrypted_basic_auth_password}) + +When you package the application into a jar file and launch the microservice using that jar, the configuration file must be in the current working directory where you launch the service. + +## Generating Encrypted Passwords + +Use the following command to generate an encrypted password for the database and the +micro service. The entire command must be entered on one line; the command shown +below uses backslashes to break lines for readability: + + java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar \ + org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \ + algorithm=PBEWithMD5AndDES \ + input='YourPasswordHere' \ + password='EncryptionKey' + +Note, 'YourPasswordHere' is the actual database password, as supplied in the 'password' +parameter. The value 'EncryptionKey' is used to encrypt the input, and must be supplied +at run time in one of two ways: + +* On the command line with a JVM argument "-Djasypt.encryptor.password". Here's an example +of using maven with the Spring-Boot goal: + + mvn -Djasypt.encryptor.password=EncryptionKey spring-boot:run + +Here's an example of using java and the jar file: + + java -jar dbc-microservice.jar -Djasypt.encryptor.password=EncryptionKey + +* In the application.properties file using the key jasypt.encryptor.password. For example: + + jasypt.encryptor.password=EncryptionKey + +## Development Launch + +Check the configuration properties in file src/main/resources/application.properties. Then launch the microservice for development and testing like this: + + mvn clean spring-boot:run + +## Production Launch + +Ensure a valid configuration is present in file application.properties in the current working directory. Then launch the microservice for production like this: + + widget-service.sh start + +## Release Notes + +### Release 1702, February 2017 + +#### Consul Release Notes + +Build 1702.3.48, 5 Feb 2017 +- DE264319 - Corrected spelling for output file from 'consule.out' to 'consul.out' - Please do not miss re-deploying consul build. Widget-ms build is not enough (or required) for this bug fix to be validated. + +#### Widget-ms Release Notes + +Build 1.2.175 +- Def 120258 Fixed the widget displaying issues in Internet Explorer 11 + +Build 1.2.145 +- Def 143148 - fixed the defect, common widgets work on Firefox version 45 +- Def 142432 - Widget-ms: InputStream is not getting closed in file StorageServiceImpl.java + +Build 1.2.140 +- St 164888 allow partner applications to trigger a new app tab through portal +- St 164847 CCD Widgets +- Def 141951 Fixed the issue for inappropriate location of framework-template.js file +- Def 141352 Widget Onboarding Page, download icon is not clickable in FF 45 version, Revise widget upload service temporary storage to /tmp +- St 164902 One copy of framework.js hidden in the Portal instead of being part of the widgets +- St 164905 Download the widget +- St 164711 Widget Personalization: Allow user to define his/her own parameters on widgets +- St 164863 Widgets to use service onboarding feature + +Build 1702.3.86 +- MariaDB connector / failover fix + +Build 1702.3.79, 10 Feb 2017 +- Updated application.properties to correct database schema name from dbca to portal +- US799260 appended complete hostname to widget certificate for irvine +- US799260 appended complete hostname to consul config.json file in prod1 and prod2 +- US799260 fixed the bar chart issue on devn1, the bar chart shows up on devn1 Home Page + +Build 1702.3.78, 9 Feb 2017 +- US799260 fixed the firefox compatibility issue; and y-scales issue in bar chart +- US799260 Added the three new widgets in dashboard-widgets folder; removed all testing logs in all widgets; fixed a bug in widget-test + +Build 1702.3.75, 07 Feb 2017 +DE267061 - Removed a hardcoded intance of loginId used in the query. + +Build 1702.3.73, 06 Feb 2017 +DE267061 - Fixed - user should only see widgets that were uploaded against app/roles that they have OR if they were uploaded by checking All Users checkbox. +Build 1702.3.71, 5 Feb 2017 +- Important Note: Copied all these build notes from Portal WebApp to here (widget-ms) - in order not to confuse folks, we have removed Portal's build numbers for these notes. Going forward, will add widget-ms's own build number. Also note that we've changed the version series in POM.xml from 1702.0 to 1702.3 in pom.xml - Although Jenkins/SWM overrides and doesn't care about maven's versioning, but did this to synch with what Portal Web App POM. +- DE261560 Portal App: Widgets MS logs are not getting rolled over +- DE261655 Unable to delete standard widgets +- DE262487 EP-Portal App: News widget not adapting when tile size is changed by user +- DE257516 Common widgets reload in a single tab +- DE262505 Upload Duplicate Widget Issue +- DE262610 Widget Microservice logging is not following EELF guidelines +- DE262800 Issues with widget name this requires database modifications +- DE263090 Issues with widget roles +- US799260 BE now 'discovers' widget-service using Consul. If consul is not running, it fallbacks to the current implemenation which is https://localhost and the port of your choosing in system.properties - Ex: localhost:8082 +- US799260 Fix delete feature for the three special widgets news, events, resources widget can have spaces in its name +- US799260 Widget feature: + + Add the editing feature in widgetOnboarding page + + Move widget catalog and onboarding to new directories +- US811188 Log / Audit widgets logging in DB +- US818934 Allow basic authentication +- US814730 Make news / Events and Resources as widgets +- US827836 Portal Widget Framework + +## Contact + +Ikram Ikramullah + +## Certificate + +### Create self signed certificate + +1. Create a self signed certificate for the microservice +keytool -genkey -alias widget-microservice -storetype PKCS12 -keyalg RSA -keystore widget-keystore.p12 + +### Import into client's trust store + +1. Export certificate from microservice's keystore - default password is 'microservice' +keytool -exportcert -keystore widget-keystore.p12 -alias widget-microservice -file widget-cert.cer + +2. Import the exported certificate of microservice from step 1 and import it into Portal JRE's cacerts file. The location of this file is %JRE%/lib/secuirty/cacerts. + +keytool -import -trustcacerts -keystore "C:\Program Files\Java\jre1.8.0_91\lib\security\cacerts" -noprompt -alias widget-microservice -file widget-cert.cer + +OR +; +keytool -import -trustcacerts -keystore /usr/local/add-on/jdk1.8.0_60/jre/lib/security/ -noprompt -alias widget-microservice -file widget-cert.cer + +### Runing on http (not https) + +If the intent is to run this microservice without https i.e run on plain http, comment out (put a leading #) infront of all properties in 'Certificate Properties' section of application.properties - these properties are + +server.ssl.key-store=classpath:widget-keystore.p12 +server.ssl.key-store-password=ENC(DiIYnAMab4u7rEW2yKhF9zBL00uU55q8) +server.ssl.keyStoreType=PKCS12 +server.ssl.keyAlias=widget-microservice + +## Running service in docker + +a). Build docker image: mvn docker:build +b). Run the service in docker: docker run -p <port>:<port-in> -t <image-name> +c). Check running docker containers: docker ps + +## Migration Instruction +1. Due to changes in the existing tables, the user will have to remove all the existing widgets in 1702 release +2. Re-upload the latest version of widgets under dashboard-widgets folder diff --git a/ecomp-portal-widget-ms/widget-ms/docs/Deployment Guide Portal Microservices and Consul.docx b/ecomp-portal-widget-ms/widget-ms/docs/Deployment Guide Portal Microservices and Consul.docx Binary files differnew file mode 100644 index 00000000..683b1e92 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/docs/Deployment Guide Portal Microservices and Consul.docx diff --git a/ecomp-portal-widget-ms/widget-ms/pom.xml b/ecomp-portal-widget-ms/widget-ms/pom.xml new file mode 100644 index 00000000..14820b65 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/pom.xml @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.openecomp.portal</groupId> + <artifactId>widget-ms</artifactId> + <version>1.3.0-SNAPSHOT</version> + <packaging>jar</packaging> + <name>widget-microservice</name> + + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>1.4.2.RELEASE</version> + <relativePath /> <!-- lookup parent from repository --> + </parent> + + <properties> + <docker.imagename>widget-ms</docker.imagename> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <java.version>1.8</java.version> + <hibernate.version>4.3.11.Final</hibernate.version> + <skipTests>true</skipTests> + </properties> + + <dependencies> + <dependency> + <!-- Setup Spring Data JPA Repository support --> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-thymeleaf</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-devtools</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-core</artifactId> + <!-- <version>${hibernate.version}</version> --> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <!-- <version>1.10</version> --> + </dependency> + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <!-- <version>1.5.8</version> --> + </dependency> + <dependency> + <groupId>com.github.ulisesbocchio</groupId> + <artifactId>jasypt-spring-boot-starter</artifactId> + <version>1.9</version> + </dependency> + <!-- hibernate-core depends on dom4j, which has optional dependencies. + On jenkins, contrary to doc, mvn 3.0.5 packages the optional dependencies + in the war. Workaround: exclude them explicitly. --> + <dependency> + <groupId>dom4j</groupId> + <artifactId>dom4j</artifactId> + <!-- <version>1.6.1</version> --> + <exclusions> + <exclusion> + <groupId>jaxme</groupId> + <artifactId>jaxme-api</artifactId> + </exclusion> + <exclusion> + <groupId>jaxen</groupId> + <artifactId>jaxen</artifactId> + </exclusion> + <exclusion> + <groupId>msv</groupId> + <artifactId>xsdlib</artifactId> + </exclusion> + <exclusion> + <groupId>msv</groupId> + <artifactId>relaxngDatatype</artifactId> + </exclusion> + <exclusion> + <groupId>pull-parser</groupId> + <artifactId>pull-parser</artifactId> + </exclusion> + <exclusion> + <groupId>xpp3</groupId> + <artifactId>xpp3</artifactId> + </exclusion> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + <build> + + <finalName>${project.artifactId}</finalName> + + <!-- To add resources, must name all including usual src/main/resources --> + <resources> + <resource> + <directory>src/main/resources</directory> + <filtering>true</filtering> + </resource> + <resource> + <directory>../common-widgets/target</directory> + <includes> + <include>**/*.zip</include> + </includes> + </resource> + </resources> + + <plugins> + + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + </plugin> + + <plugin> + <groupId>com.spotify</groupId> + <artifactId>docker-maven-plugin</artifactId> + <version>0.4.11</version> + <configuration> + <imageName>${project.artifactId}</imageName> + <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory> + <resources> + <resource> + <targetPath>/</targetPath> + <directory>${project.build.directory}</directory> + <include>${project.build.finalName}.jar</include> + </resource> + </resources> + </configuration> + </plugin> + + </plugins> + + </build> + +</project> diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be1/widget-keystore.p12 b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be1/widget-keystore.p12 Binary files differnew file mode 100644 index 00000000..9dcdb1a0 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be1/widget-keystore.p12 diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be2/widget-keystore.p12 b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be2/widget-keystore.p12 Binary files differnew file mode 100644 index 00000000..600dc01d --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be2/widget-keystore.p12 diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/docker/Dockerfile b/ecomp-portal-widget-ms/widget-ms/src/main/docker/Dockerfile new file mode 100644 index 00000000..7e25c222 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/docker/Dockerfile @@ -0,0 +1,6 @@ +FROM frolvlad/alpine-oraclejdk8:slim +VOLUME /tmp +ADD widget-ms.jar app.jar +RUN sh -c 'touch /app.jar' +ENV JAVA_OPTS="" +ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/MicroserviceApplication.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/MicroserviceApplication.java new file mode 100644 index 00000000..6516c364 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/MicroserviceApplication.java @@ -0,0 +1,19 @@ + package org.openecomp.portalapp.widget; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +@ComponentScan(basePackages = "org.openecomp.portalapp.widget") +public class MicroserviceApplication { + @Bean + public RestTemplate getRestTemplate(){ + return new RestTemplate(); + } + public static void main(String[] args) { + SpringApplication.run(MicroserviceApplication.class, args); + } +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/constant/WidgetConstant.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/constant/WidgetConstant.java new file mode 100644 index 00000000..b1a939b1 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/constant/WidgetConstant.java @@ -0,0 +1,11 @@ +package org.openecomp.portalapp.widget.constant; + +public final class WidgetConstant { + + public static final String WIDGET_MARKUP_LOCATION = "markup/markup.html"; + public static final String WIDGET_CONTROLLER_LOCATION = "js/controller.js"; + public static final String WIDGET_STYLE_LOCATION = "styles/styles.css"; + public static final String VALIDATION_MESSAGE_ZIP = "Please upload a zip file"; + public static final String VALIDATION_MESSAGE_FILES = "Please check your files (should contains js, styles and markup folder)"; +} + diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/DatabaseFileUploadController.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/DatabaseFileUploadController.java new file mode 100644 index 00000000..ec32e42f --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/DatabaseFileUploadController.java @@ -0,0 +1,79 @@ +package org.openecomp.portalapp.widget.controller; + +import java.io.UnsupportedEncodingException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.openecomp.portalapp.widget.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class DatabaseFileUploadController { + + @Autowired + private StorageService storageService; + + private static final Logger logger = LoggerFactory.getLogger(DatabaseFileUploadController.class); + + @ResponseBody + @RequestMapping(value = "/microservices/markup/{widgetId}", method = RequestMethod.GET) + public String getWidgetMarkup(HttpServletRequest request, HttpServletResponse response, @PathVariable("widgetId") long widgetId){ + String markup = null; + try{ + logger.debug("DatabaseFileUploadController.getWidgetMarkup: getting markup.html for widget with widgetId = {}" , widgetId); + markup = storageService.getWidgetMarkup(widgetId); + }catch(Exception e){ + logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetMarkup in widget microservices. Details:" + e.getMessage()); + } + return markup; + } + + @ResponseBody + @RequestMapping(value = "/microservices/{widgetId}/controller.js", method = RequestMethod.GET) + public String getWidgetController(HttpServletRequest request, HttpServletResponse response, @PathVariable("widgetId") long widgetId){ + String controller = null; + try{ + logger.debug("DatabaseFileUploadController.getWidgetController: getting controller.js for widget with widgetId = {}" , widgetId); + controller = storageService.getWidgetController(widgetId); + }catch(Exception e){ + logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetController in widget microservices. Details:" + e.getMessage()); + } + return controller; + } + + @ResponseBody + @RequestMapping(value = "/microservices/{widgetId}/framework.js", method = RequestMethod.GET) + public String getWidgetFramework(HttpServletRequest request, HttpServletResponse response, + @PathVariable("widgetId") long widgetId){ + String framework = null; + try{ + logger.debug("DatabaseFileUploadController.getWidgetFramework: getting framework.js for widget with widgetId = {}" , widgetId); + framework = storageService.getWidgetFramework(widgetId); + }catch(Exception e){ + logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetFramework in widget microservices. Details:" + e.getMessage()); + } + return framework; + } + + @ResponseBody + @RequestMapping(value = "/microservices/{widgetId}/styles.css", method = RequestMethod.GET) + public String getWidgetCSS(HttpServletRequest request, HttpServletResponse response, + @PathVariable("widgetId") long widgetId){ + String css = null; + try { + logger.debug("DatabaseFileUploadController.getWidgetCSS: getting styles.css for widget with widgetId = {}" , widgetId); + css = storageService.getWidgetCSS(widgetId); + } catch (UnsupportedEncodingException e) { + logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetCSS in widget microservices. Details:" + e.getMessage()); + } + return css; + } +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/HealthController.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/HealthController.java new file mode 100644 index 00000000..fc324ab1 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/HealthController.java @@ -0,0 +1,35 @@ +package org.openecomp.portalapp.widget.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HealthController { + + @RequestMapping(value = { "/health" }, method = RequestMethod.GET, produces = "application/json") + public HealthStatus getWidgetCatalog(HttpServletRequest request, HttpServletResponse response) { + return new HealthStatus("ok"); + } + + class HealthStatus { + private String status; + + public HealthStatus(String status){ + this.status = status; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + + } +}
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/WidgetsCatalogController.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/WidgetsCatalogController.java new file mode 100644 index 00000000..1af5a3cc --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/WidgetsCatalogController.java @@ -0,0 +1,261 @@ +package org.openecomp.portalapp.widget.controller; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.openecomp.portalapp.widget.domain.ValidationRespond; +import org.openecomp.portalapp.widget.domain.WidgetCatalog; +import org.openecomp.portalapp.widget.service.StorageService; +import org.openecomp.portalapp.widget.service.WidgetCatalogService; +import org.openecomp.portalapp.widget.utils.AuthorizationUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.multipart.MultipartFile; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@Controller +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +public class WidgetsCatalogController { + + @Value("${server.port}") + String port; + @Value("${server.contextPath}") + String context; + + @Value("${security.user.name}") + String security_user; + @Value("${security.user.password}") + String security_pass; + + @Autowired + WidgetCatalogService widgetCatalogService; + + @Autowired + StorageService storageService; + + @Autowired + RestTemplate restTemplate; + + AuthorizationUtil util = new AuthorizationUtil(); + + private static final Logger logger = LoggerFactory.getLogger(WidgetsCatalogController.class); + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog" }, method = RequestMethod.GET, produces = "application/json") + public List<WidgetCatalog> getWidgetCatalog(HttpServletRequest request, HttpServletResponse response + ,@RequestHeader(value="Authorization") String auth) throws IOException{ + + List<WidgetCatalog> widgetCatalog = null; + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.getWidgetCatalog in widget microserivce. Please check your username and password."); + return widgetCatalog; + } + try { + widgetCatalog = widgetCatalogService.getWidgetCatalog(); + logger.debug("WidgetsCatalogController.getWidgetCatalog: getting widget list {}", widgetCatalog); + } catch (Exception e) { + logger.error("Exception occurred while performing WidgetsCatalogController.getWidgetCatalog in widget microservices. Details:" + e.getMessage()); + } + return widgetCatalog; + } + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog/{loginName}" }, method = RequestMethod.GET, produces = "application/json") + public List<WidgetCatalog> getUserWidgetCatalog(HttpServletRequest request, HttpServletResponse response, + @PathVariable("loginName") String loginName, @RequestHeader(value="Authorization") String auth) throws IOException { + List<WidgetCatalog> widgetCatalog = null; + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.getUserWidgetCatalog in widget microserivce. Please check your username and password."); + return widgetCatalog; + } + try { + widgetCatalog = widgetCatalogService.getUserWidgetCatalog(loginName); + logger.debug("WidgetsCatalogController.getUserWidgetCatalog: getting widget list {}", widgetCatalog); + } catch (Exception e) { + logger.error("Exception occurred while performing WidgetsCatalogController.getUserWidgetCatalog in widget microservices. Details:" + e.getMessage()); + } + return widgetCatalog; + } + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog/{widgetId}" }, method = RequestMethod.PUT, produces = "application/json") + public void updateWidgetCatalog(HttpServletRequest request, HttpServletResponse response, + @RequestBody WidgetCatalog newWidgetCatalog, @PathVariable("widgetId") long widgetId, + @RequestHeader(value="Authorization") String auth) throws IOException { + + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.updateWidgetCatalog in widget microserivce. Please check your username and password."); + return; + } + try { + widgetCatalogService.updateWidgetCatalog(widgetId, newWidgetCatalog); + logger.debug("WidgetsCatalogController.updateWidgetCatalog: updating widget {}", newWidgetCatalog); + } catch (Exception e) { + logger.error("Exception occurred while performing WidgetsCatalogController.updateWidgetCatalog in widget microservices. Details:" + e.getMessage()); + e.printStackTrace(); + } + } + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog" }, method = RequestMethod.POST, produces = "application/json") + public ValidationRespond saveWidgetCatalog(HttpServletRequest request, HttpServletResponse response, @RequestHeader(value="Authorization") String auth, + @RequestParam("file") MultipartFile file, @RequestParam("widget") String widget) throws IOException { + + ValidationRespond respond = null; + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.saveWidgetCatalog in widget microserivce. Please check your username and password."); + return new ValidationRespond(false, "Basic Authentication Error, please check your username and password."); + } + try { + //check the zip file structure first + respond = storageService.checkZipFile(file); + + if(respond.isValid()){ + //save the widget catalog + WidgetCatalog newWidget = new ObjectMapper().readValue(widget, WidgetCatalog.class); + + long widgetId = widgetCatalogService.saveWidgetCatalog(newWidget); + logger.debug("WidgetsCatalogController.saveWidgetCatalog: saving widget={}", newWidget); + //save the widget zip file ; + storageService.save(file, newWidget, widgetId); + } + + } catch (Exception e) { + logger.error("Exception occurred while performing WidgetsCatalogController.saveWidgetCatalog in widget microservices. Details:", e); + } + return respond; + } + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog/{widgetId}" }, method = RequestMethod.POST, produces = "application/json") + public ValidationRespond updateWidgetCatalogwithFiles(HttpServletRequest request, HttpServletResponse response, @RequestHeader(value="Authorization") String auth, + @RequestParam("file") MultipartFile file, @RequestParam("widget") String widget, @PathVariable("widgetId") long widgetId) throws IOException { + System.out.println("microserivces updating with files" + widgetId); + ValidationRespond respond = null; + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.saveWidgetCatalog in widget microserivce. Please check your username and password."); + return new ValidationRespond(false, "Basic Authentication Error, please check your username and password."); + } + try { + //check the zip file structure first + respond = storageService.checkZipFile(file); + if(respond.isValid()){ + //update the widget catalog + WidgetCatalog newWidget = new ObjectMapper().readValue(widget, WidgetCatalog.class); + widgetCatalogService.updateWidgetCatalog(widgetId, newWidget); + logger.debug("WidgetsCatalogController.saveWidgetCatalog: updating widget with widgetId={}", widgetId); + //update the widget zip file + storageService.update(file, newWidget, widgetId); + } + } catch (Exception e) { + logger.error("Exception occurred while performing WidgetsCatalogController.saveWidgetCatalog in widget microservices. Details:" + e.getMessage()); + e.printStackTrace(); + } + return respond; + } + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog/{widgetId}" }, method = { + RequestMethod.DELETE }, produces = "application/json") + public void deleteOnboardingWidget(HttpServletRequest request, HttpServletResponse response, + @PathVariable("widgetId") long widgetId, @RequestHeader(value="Authorization") String auth) throws IOException{ + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.deleteOnboardingWidget in widget microserivce. Please check your username and password."); + return; + } + try { + logger.debug("WidgetsCatalogController.deleteOnboardingWidget: deleting widget {}", widgetId); + //WidgetCatalog widget = widgetCatalogService.getWidgetCatalog(widgetId); + widgetCatalogService.deleteWidgetCatalog(widgetId); + storageService.deleteWidgetFile(widgetId); + } catch (Exception e) { + logger.error("Exception occurred while performing WidgetsCatalogController.deleteOnboardingWidget in widget microservices. Details:" + e.getMessage()); + } + } + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog/parameters/{widgetId}" }, method = RequestMethod.GET, produces = "application/json") + public Long getServiceIdByWidget(HttpServletRequest request, HttpServletResponse response, + @PathVariable("widgetId") Long widgetId, @RequestHeader(value="Authorization") String auth) throws IOException { + + Long serviceId = null; + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.getServiceIdByWidget in widget microserivce. Please check your username and password."); + return serviceId; + } + try{ + logger.debug("WidgetsCatalogController.getServiceIdByWidget: getting service Id for widget {}", widgetId); + serviceId = widgetCatalogService.getServiceIdByWidget(widgetId); + }catch(Exception e){ + logger.error("Exception occurred while performing WidgetsCatalogController.getServiceIdByWidget in widget microservices. Details:" + e.getMessage()); + } + return serviceId; + } + + + @ResponseBody + @RequestMapping(value = { "/microservices/widgetCatalog/service/{serviceId}" }, method = RequestMethod.GET, produces = "application/json") + public List<WidgetCatalog> getWidgetByServiceId(HttpServletRequest request, HttpServletResponse response, + @PathVariable("serviceId") Long serviceId, @RequestHeader(value="Authorization") String auth) throws IOException { + List<WidgetCatalog> list = new ArrayList<WidgetCatalog>(); + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.getWidgetByServiceId in widget microserivce. Please check your username and password."); + return null; + } + try{ + logger.debug("WidgetsCatalogController.getWidgetByServiceId: getting service Id for widget {}", serviceId); + list = widgetCatalogService.getWidgetsByServiceId(serviceId); + }catch(Exception e){ + logger.error("Exception occurred while performing WidgetsCatalogController.getWidgetByServiceId in widget microservices. Details:" + e.getMessage()); + } + return list; + } + + + @ResponseBody + @RequestMapping(value = { "/microservices/download/{widgetId}" }, method = RequestMethod.GET, produces = "application/json") + public byte[] getWidgetZipFile(HttpServletRequest request, HttpServletResponse response, + @PathVariable("widgetId") long widgetId, @RequestHeader(value="Authorization") String auth) throws Exception { + byte[] byteFile = null; + if(!util.authorization(auth, security_user, security_pass)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + logger.error("Basic Authentication Error while performing WidgetsCatalogController.getWidgetZipFile in widget microserivce. Please check your username and password."); + return byteFile; + } + try { + byteFile = storageService.getWidgetCatalogContent(widgetId); + logger.debug("WidgetsCatalogController.getWidgetZipFile: getting widget zip file for widget with id {}", widgetId); + } catch (Exception e) { + logger.error("Exception occurred while performing WidgetsCatalogController.getWidgetZipFile in widget microservices. Details:" + e.getMessage()); + } + return byteFile; + } + + +}
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/dao/WidgetDataSource.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/dao/WidgetDataSource.java new file mode 100644 index 00000000..0a950c54 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/dao/WidgetDataSource.java @@ -0,0 +1,34 @@ +package org.openecomp.portalapp.widget.dao; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.stereotype.Component; + +@Component +public class WidgetDataSource{ + + @Value("${spring.database.driver.classname}") + private String dbDriverClassName; + + @Value("${spring.datasource.url}") + private String dbUrl; + + @Value("${spring.datasource.username}") + private String dbUsername; + + @Value("${spring.datasource.password}") + private String dbPassword; + + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(dbDriverClassName); + dataSource.setUrl(dbUrl); + dataSource.setUsername(dbUsername); + dataSource.setPassword(dbPassword); + return dataSource; + } +}
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/App.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/App.java new file mode 100644 index 00000000..19c6311b --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/App.java @@ -0,0 +1,47 @@ +package org.openecomp.portalapp.widget.domain; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "FN_APP") +public class App implements Serializable{ + + private static final long serialVersionUID = 1L; + + @Id + @Column(name = "APP_ID") + @GeneratedValue(strategy=GenerationType.AUTO) + private Long appId; + + @Column(name = "APP_Name") + private String appName; + + public Long getAppId() { + return appId; + } + + public void setAppId(Long appId) { + this.appId = appId; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + @Override + public String toString() { + return "App [appId=" + appId + ", appName=" + appName + "]"; + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceData.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceData.java new file mode 100644 index 00000000..831b1e65 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceData.java @@ -0,0 +1,126 @@ +package org.openecomp.portalapp.widget.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * TODO: moved all microservice-related code (domain, controller, service) + * from ecomp portal Backend to widget microservice + */ +@Entity +@Table(name="EP_MICROSERVICE") +public class MicroserviceData { + + @Id + @Column(name = "id") + @GeneratedValue(strategy=GenerationType.AUTO) + private Long id; + + @Column(name = "name") + private String name; + + @Column(name = "description") + private String desc; + + @Column(name = "appId") + private long appId; + + @Column(name = "endpoint_url") + private String url; + + @Column(name = "security_type") + private String securityType; + + @Column(name = "username") + private String username; + + @Column(name = "password") + private String password; + + @Column(name = "active") + private String active; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public long getAppId() { + return appId; + } + + public void setAppId(long appId) { + this.appId = appId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getSecurityType() { + return securityType; + } + + public void setSecurityType(String securityType) { + this.securityType = securityType; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getActive() { + return active; + } + + public void setActive(String active) { + this.active = active; + } + + @Override + public String toString() { + return "MicroserviceData [name=" + name + ", desc=" + desc + ", appId=" + appId + ", url=" + url + + ", securityType=" + securityType + ", username=" + username + ", password=" + password + ", active=" + + active + "]"; + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceParameter.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceParameter.java new file mode 100644 index 00000000..9f19c0d4 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceParameter.java @@ -0,0 +1,70 @@ +package org.openecomp.portalapp.widget.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * TODO: moved all microservice-related code (domain, controller, service) + * from ecomp portal Backend to widget microservice + */ +@Entity +@Table(name="EP_MICROSERVICE_PARAMETER") +public class MicroserviceParameter { + + @Id + @Column(name = "id") + @GeneratedValue(strategy=GenerationType.AUTO) + private Long id; + + @Column(name = "service_id") + private long serviceId; + + @Column(name = "para_key") + private String para_key; + + @Column(name = "para_value") + private String para_value; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public long getServiceId() { + return serviceId; + } + + public void setServiceId(long serviceId) { + this.serviceId = serviceId; + } + + public String getPara_key() { + return para_key; + } + + public void setPara_key(String para_key) { + this.para_key = para_key; + } + + public String getPara_value() { + return para_value; + } + + public void setPara_value(String para_value) { + this.para_value = para_value; + } + + @Override + public String toString() { + return "MicroserviceParameter [serviceId=" + serviceId + ", para_key=" + para_key + ", para_value=" + para_value + + "]"; + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/RoleApp.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/RoleApp.java new file mode 100644 index 00000000..ca73f313 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/RoleApp.java @@ -0,0 +1,95 @@ +package org.openecomp.portalapp.widget.domain; + +import java.io.Serializable; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +@Entity +@Table(name = "FN_ROLE") +public class RoleApp implements Serializable{ + private static final long serialVersionUID = 1L; + + @Id + @Column(name = "ROLE_ID") + @GeneratedValue(strategy=GenerationType.AUTO) + private Long roleId; + + + @Column(name = "ROLE_Name") + private String roleName; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name="APP_ID") + private App app; + + @JsonIgnore + @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, mappedBy="widgetRoles") + private Set<WidgetCatalog> widgets; + + /*@PreRemove + private void removeGroupsFromUsers() { + for (WidgetCatalog w : widgets) { + w.getWidgetRoles().remove(this); + } + }*/ + + /*@ManyToOne + @JoinColumn(name = "WIDGET_ID", nullable = false) + WidgetCatalog widgetCatalog;*/ + + //@JsonIgnore + //@ManyToMany(mappedBy = "widgetRoles") + //@ManyToMany(fetch = FetchType.EAGER, mappedBy = "widgetRoles") + //private Set<WidgetCatalog> widgets = new HashSet<WidgetCatalog>(); + + public Long getRoleId() { + return roleId; + } + + public void setRoleId(Long roleId) { + this.roleId = roleId; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public App getApp() { + return app; + } + + public void setApp(App app) { + this.app = app; + } + + public Set<WidgetCatalog> getWidgets() { + return widgets; + } + + public void setWidgets(Set<WidgetCatalog> widgets) { + this.widgets = widgets; + } + + @Override + public String toString() { + return "RoleApp [roleId=" + roleId + ", roleName=" + roleName + ", app=" + app + "]"; + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/ValidationRespond.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/ValidationRespond.java new file mode 100644 index 00000000..25c74af1 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/ValidationRespond.java @@ -0,0 +1,34 @@ +package org.openecomp.portalapp.widget.domain; + +public class ValidationRespond { + private boolean valid; + private String error; + + public ValidationRespond(boolean valid, String error){ + this.valid = valid; + this.error = error; + } + + public boolean isValid() { + return valid; + } + + public void setValid(boolean valid) { + this.valid = valid; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + @Override + public String toString() { + return "ValidationRespond [valid=" + valid + ", error=" + error + "]"; + } + + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetCatalog.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetCatalog.java new file mode 100644 index 00000000..6b7823e6 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetCatalog.java @@ -0,0 +1,134 @@ +package org.openecomp.portalapp.widget.domain; + +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.Table; +import javax.persistence.Transient; + + +@Entity +@Table(name="EP_WIDGET_CATALOG") +public class WidgetCatalog{ + + @Id + @Column(name = "widget_id") + @GeneratedValue(strategy=GenerationType.AUTO) + private long id; + + @Column(name = "wdg_name") + private String name; + + @Column(name = "wdg_desc") + private String desc; + + @Column(name = "wdg_file_loc") + private String fileLocation; + + @Column(name = "all_user_flag") + private String allowAllUser; + + @Column(name = "service_id") + private Long serviceId; + + @Transient + private String sortOrder; + + @Transient + private String statusCode; + + @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) + @JoinTable(name = "ep_widget_catalog_role", + joinColumns = {@JoinColumn(name = "WIDGET_ID")}, + inverseJoinColumns = {@JoinColumn(name = "ROLE_ID")} + ) + private Set<RoleApp> widgetRoles; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getFileLocation() { + return fileLocation; + } + + public void setFileLocation(String fileLocation) { + this.fileLocation = fileLocation; + } + + public Set<RoleApp> getWidgetRoles() { + return widgetRoles; + } + + public void setWidgetRoles(Set<RoleApp> widgetRoles) { + this.widgetRoles = widgetRoles; + } + + public String getAllowAllUser() { + return allowAllUser; + } + + public void setAllowAllUser(String allowAllUser) { + this.allowAllUser = allowAllUser; + } + + public String getSortOrder() { + return sortOrder; + } + + public void setSortOrder(String sortOrder) { + this.sortOrder = sortOrder; + } + + public String getStatusCode() { + return statusCode; + } + + public void setStatusCode(String statusCode) { + this.statusCode = statusCode; + } + + public Long getServiceId() { + return serviceId; + } + + public void setServiceId(Long serviceId) { + this.serviceId = serviceId; + } + + @Override + public String toString() { + return "WidgetCatalog [id=" + id + ", name=" + name + ", desc=" + desc + ", fileLocation=" + fileLocation + + ", allowAllUser=" + allowAllUser + ", serviceId=" + serviceId + ", sortOrder=" + sortOrder + + ", statusCode=" + statusCode + ", widgetRoles=" + widgetRoles + "]"; + } +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetFile.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetFile.java new file mode 100644 index 00000000..7eb3c1ef --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetFile.java @@ -0,0 +1,96 @@ +package org.openecomp.portalapp.widget.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "ep_widget_catalog_files") +public class WidgetFile { + @Id + @Column (name = "file_id") + private int id; + + @Column(name = "widget_name") + private String name; + + @Column(name = "widget_id") + private long widgetId; + + @Column(name = "markup_html") + private byte[] markup; + + @Column(name = "controller_js") + private byte[] controller; + + @Column(name = "framework_js") + private byte[] framework; + + @Column(name = "widget_css") + private byte[] css; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public byte[] getMarkup() { + return markup; + } + + public void setMarkup(byte[] markup) { + this.markup = markup; + } + + public byte[] getController() { + return controller; + } + + public void setController(byte[] controller) { + this.controller = controller; + } + + public byte[] getFramework() { + return framework; + } + + public void setFramework(byte[] framework) { + this.framework = framework; + } + + public byte[] getCss() { + return css; + } + + public void setCss(byte[] css) { + this.css = css; + } + + public long getWidgetId() { + return widgetId; + } + + public void setWidgetId(long widgetId) { + this.widgetId = widgetId; + } + + @Override + public String toString() { + return "WidgetFile [name=" + name + ", widgetId=" + widgetId + "]"; + } + + + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageException.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageException.java new file mode 100644 index 00000000..65b71454 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageException.java @@ -0,0 +1,15 @@ +package org.openecomp.portalapp.widget.excetpion; + +public class StorageException extends RuntimeException { + + + private static final long serialVersionUID = 4142203582273176386L; + + public StorageException(String message) { + super(message); + } + + public StorageException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageFileNotFoundException.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageFileNotFoundException.java new file mode 100644 index 00000000..44fb7286 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageFileNotFoundException.java @@ -0,0 +1,14 @@ +package org.openecomp.portalapp.widget.excetpion; + +public class StorageFileNotFoundException extends StorageException { + + private static final long serialVersionUID = -930114778119283188L; + + public StorageFileNotFoundException(String message) { + super(message); + } + + public StorageFileNotFoundException(String message, Throwable cause) { + super(message, cause); + } +}
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/filters/CorsConfiguration.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/filters/CorsConfiguration.java new file mode 100644 index 00000000..2fdb5480 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/filters/CorsConfiguration.java @@ -0,0 +1,15 @@ +package org.openecomp.portalapp.widget.filters; + +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class CorsConfiguration extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/microservices/widgetCatalog/").permitAll(); + http.csrf().disable(); + } +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/hibernate/HibernateConfiguration.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/hibernate/HibernateConfiguration.java new file mode 100644 index 00000000..a376da0a --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/hibernate/HibernateConfiguration.java @@ -0,0 +1,44 @@ +package org.openecomp.portalapp.widget.hibernate; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * Provides a Hibernate session factory. + */ +@org.springframework.context.annotation.Configuration +public class HibernateConfiguration { + + @Autowired + private DataSource dataSource; + + @Bean + public LocalSessionFactoryBean sessionFactory() { + + LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.setHibernateProperties(hibernateProperties()); + sessionFactory.setPackagesToScan(new String[] { "org.openecomp.portalapp.widget.domain" }); + return sessionFactory; + } + + private Properties hibernateProperties() { + Properties properties = new Properties(); + properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); + properties.put("hibernate.show_sql", "false"); + return properties; + } + + @Bean + public PlatformTransactionManager transactionManager() { + return new JpaTransactionManager(); + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/listener/WidgetEventListener.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/listener/WidgetEventListener.java new file mode 100644 index 00000000..25eadfa7 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/listener/WidgetEventListener.java @@ -0,0 +1,36 @@ +package org.openecomp.portalapp.widget.listener; + +import org.openecomp.portalapp.widget.service.InitializationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Component +public class WidgetEventListener implements ApplicationListener<ApplicationReadyEvent>{ + + private static final Logger logger = LoggerFactory.getLogger(WidgetEventListener.class); + + @Autowired + InitializationService initializationService; + + @Value("${initialization.default.widgets}") + String init_default_widget; + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + + logger.debug("Listening event " + event.toString()); + try { + if(Boolean.parseBoolean(init_default_widget)) + initializationService.initialize(); + } catch (Exception e) { + logger.error("onApplicationEvent: InitializationService#initialize failed", e); + } + + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/InitializationService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/InitializationService.java new file mode 100644 index 00000000..4a34606a --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/InitializationService.java @@ -0,0 +1,7 @@ +package org.openecomp.portalapp.widget.service; + +public interface InitializationService { + + void initialize(); + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/MicroserviceService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/MicroserviceService.java new file mode 100644 index 00000000..32eb48b1 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/MicroserviceService.java @@ -0,0 +1,17 @@ +package org.openecomp.portalapp.widget.service; + +import org.openecomp.portalapp.widget.domain.MicroserviceData; +import org.openecomp.portalapp.widget.domain.MicroserviceParameter; + +/** + * TODO: moved all microservice-related code (domain, controller, service) + * from ecomp portal Backend to widget microservice + */ +public interface MicroserviceService { + + Long saveMicroserivce(MicroserviceData newService); + + void saveMicroserviceParameter(MicroserviceParameter newParameter); + + Long getMicroserviceIdByName(String newServiceName); +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/StorageService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/StorageService.java new file mode 100644 index 00000000..1eb14704 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/StorageService.java @@ -0,0 +1,34 @@ +package org.openecomp.portalapp.widget.service; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import org.openecomp.portalapp.widget.domain.ValidationRespond; +import org.openecomp.portalapp.widget.domain.WidgetCatalog; +import org.openecomp.portalapp.widget.domain.WidgetFile; +import org.springframework.web.multipart.MultipartFile; + +public interface StorageService { + + void deleteWidgetFile(long widgetId); + + WidgetFile getWidgetFile(long widgetId); + + String getWidgetMarkup(long widgetId) throws UnsupportedEncodingException; + + String getWidgetController(long widgetId) throws UnsupportedEncodingException; + + String getWidgetFramework(long widgetId) throws UnsupportedEncodingException; + + String getWidgetCSS(long widgetId) throws UnsupportedEncodingException; + + ValidationRespond checkZipFile(MultipartFile file); + + void save(MultipartFile file, WidgetCatalog newWidget, long widgetId); + + void initSave(File file, WidgetCatalog newWidget, long widgetId); + + void update(MultipartFile file, WidgetCatalog newWidget, long widgetId); + + byte[] getWidgetCatalogContent(long widgetId) throws Exception; +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/WidgetCatalogService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/WidgetCatalogService.java new file mode 100644 index 00000000..e9bd0f33 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/WidgetCatalogService.java @@ -0,0 +1,28 @@ +package org.openecomp.portalapp.widget.service; + +import java.util.List; + +import org.openecomp.portalapp.widget.domain.WidgetCatalog; + +public interface WidgetCatalogService { + + List<WidgetCatalog> getWidgetCatalog(); + + List<WidgetCatalog> getUserWidgetCatalog(String loginName); + + WidgetCatalog getWidgetCatalog(Long widgetCatalogId); + + void deleteWidgetCatalog(long WidgetCatalogId); + + long saveWidgetCatalog(WidgetCatalog newWidgetCatalog); + + void updateWidgetCatalog(Long widgetCatalogId, WidgetCatalog newWidgetCatalog); + + Long getServiceIdByWidget(Long widgetCatalogId); + + boolean getWidgetIdByName(String newWidgetName); + + List<WidgetCatalog> getWidgetsByServiceId(Long serviceId); + + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/InitializationServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/InitializationServiceImpl.java new file mode 100644 index 00000000..7a45d71e --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/InitializationServiceImpl.java @@ -0,0 +1,133 @@ +package org.openecomp.portalapp.widget.service.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashSet; + +import javax.transaction.Transactional; + +import org.openecomp.portalapp.widget.domain.MicroserviceData; +import org.openecomp.portalapp.widget.domain.MicroserviceParameter; +import org.openecomp.portalapp.widget.domain.RoleApp; +import org.openecomp.portalapp.widget.domain.WidgetCatalog; +import org.openecomp.portalapp.widget.service.InitializationService; +import org.openecomp.portalapp.widget.service.MicroserviceService; +import org.openecomp.portalapp.widget.service.StorageService; +import org.openecomp.portalapp.widget.service.WidgetCatalogService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; + +/** + * Uploads widget zip archives to Portal. + */ +@Service("initService") +@Transactional +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +public class InitializationServiceImpl implements InitializationService { + + private static final String BASIC_AUTH = "Basic Authentication"; + private static final String PARAMETER_KEY = "resourceType"; + private static final Logger logger = LoggerFactory.getLogger(InitializationServiceImpl.class); + + @Autowired + WidgetCatalogService widgetCatalogService; + + @Autowired + StorageService storageService; + + @Autowired + MicroserviceService microserviceService; + + @Value("${account.user.name}") + String account_user; + + @Value("${account.user.password}") + String account_password; + + @Value("${initialization.widgetData.url}") + String widgetData_url; + + @Override + public void initialize() { + initCommonWidget("News"); + initCommonWidget("Events"); + initCommonWidget("Resources"); + } + + private void initCommonWidget(String name) { + + final String newServiceName = name + " Microservice"; + + Long serviceId = microserviceService.getMicroserviceIdByName(newServiceName); + + if (serviceId == null) { + MicroserviceData newService = new MicroserviceData(); + newService.setName(newServiceName); + newService.setDesc(name); + newService.setAppId(1); + newService.setUrl(widgetData_url); + newService.setSecurityType(BASIC_AUTH); + newService.setUsername(account_user); + newService.setPassword(account_password); + newService.setActive("Y"); + serviceId = microserviceService.saveMicroserivce(newService); + + MicroserviceParameter parameter = new MicroserviceParameter(); + parameter.setServiceId(serviceId); + parameter.setPara_key(PARAMETER_KEY); + String parameter_value = null; + switch (name.toLowerCase()) { + case "news": + parameter_value = "NEWS"; + break; + case "events": + parameter_value = "EVENTS"; + break; + case "resources": + parameter_value = "IMPORTANTRESOURCES"; + break; + } + parameter.setPara_value(parameter_value); + microserviceService.saveMicroserviceParameter(parameter); + } + + if (!widgetCatalogService.getWidgetIdByName(name)) { + WidgetCatalog newWidget = new WidgetCatalog(); + newWidget.setName(name); + newWidget.setDesc(name); + newWidget.setAllowAllUser("1"); + String fileLocation = name.toLowerCase() + "-widget.zip"; + newWidget.setFileLocation(fileLocation); + newWidget.setServiceId(serviceId); + newWidget.setWidgetRoles(new HashSet<RoleApp>()); + long widgetId = widgetCatalogService.saveWidgetCatalog(newWidget); + + File tmpZipFile = new File("/tmp/" + fileLocation); + InputStream fileInputStream = null; + OutputStream outputStream = null; + try { + fileInputStream = this.getClass().getClassLoader().getResourceAsStream(fileLocation); + outputStream = new FileOutputStream(tmpZipFile); + int read = 0; + byte[] bytes = new byte[4096]; + while ((read = fileInputStream.read(bytes)) != -1) { + outputStream.write(bytes, 0, read); + } + outputStream.close(); + fileInputStream.close(); + } catch (Exception e) { + logger.error( + "Exception occurred while performing InitializationServiceImpl.initCommonWidget in widget microservices. Details:", e); + } + storageService.initSave(tmpZipFile, newWidget, widgetId); + tmpZipFile.delete(); + } + } +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/MicroserviceServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/MicroserviceServiceImpl.java new file mode 100644 index 00000000..80c45a2e --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/MicroserviceServiceImpl.java @@ -0,0 +1,86 @@ +package org.openecomp.portalapp.widget.service.impl; + +import java.util.List; + +import javax.transaction.Transactional; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; +import org.openecomp.portalapp.widget.domain.MicroserviceData; +import org.openecomp.portalapp.widget.domain.MicroserviceParameter; +import org.openecomp.portalapp.widget.service.MicroserviceService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; + +/** + * TODO: moved all microservice-related code (domain, controller, service) + * from ecomp portal Backend to widget microservice + */ +@Service("microserviceService") +@Transactional +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +public class MicroserviceServiceImpl implements MicroserviceService{ + + private static final Logger logger = LoggerFactory.getLogger(MicroserviceServiceImpl.class); + + @Autowired + private SessionFactory sessionFactory; + + @Override + public Long saveMicroserivce(MicroserviceData newService) { + try{ + logger.debug("MicroserviceServiceImpl.saveMicroserivce: microservice={}", newService); + Session session = sessionFactory.openSession(); + Transaction tx = session.beginTransaction(); + session.save(newService); + tx.commit(); + session.flush(); + session.close(); + } + catch(Exception e){ + logger.error("Exception occurred while performing MicroserviceServiceImpl.saveMicroserivce in widget microservices. Details:" + e.getMessage()); + } + return newService.getId(); + } + + @Override + public void saveMicroserviceParameter(MicroserviceParameter newParameter) { + try{ + logger.debug("MicroserviceServiceImpl.saveMicroserviceData: microservice={}", newParameter); + Session session = sessionFactory.openSession(); + Transaction tx = session.beginTransaction(); + session.save(newParameter); + tx.commit(); + session.flush(); + session.close(); + } + catch(Exception e){ + logger.error("Exception occurred while performing MicroserviceServiceImpl.saveMicroserviceData in widget microservices. Details:" + e.getMessage()); + } + } + + @SuppressWarnings("unchecked") + @Override + public Long getMicroserviceIdByName(String newServiceName) { + + Session session = sessionFactory.openSession(); + Criteria criteria = session.createCriteria(MicroserviceData.class) + .add(Restrictions.eq("name", newServiceName)) + .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + + List<MicroserviceData> services = criteria.list(); + logger.debug("MicroserviceServiceImpl.getMicroserviceByName: result={}", services); + session.flush(); + session.close(); + + return (services.size() > 0) ? services.get(0).getId() : null; + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/StorageServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/StorageServiceImpl.java new file mode 100644 index 00000000..f459ffc4 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/StorageServiceImpl.java @@ -0,0 +1,493 @@ +package org.openecomp.portalapp.widget.service.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; +import org.openecomp.portalapp.widget.constant.WidgetConstant; +import org.openecomp.portalapp.widget.domain.ValidationRespond; +import org.openecomp.portalapp.widget.domain.WidgetCatalog; +import org.openecomp.portalapp.widget.domain.WidgetFile; +import org.openecomp.portalapp.widget.excetpion.StorageException; +import org.openecomp.portalapp.widget.service.StorageService; +import org.openecomp.portalapp.widget.service.WidgetCatalogService; +import org.openecomp.portalapp.widget.utils.UnzipUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class StorageServiceImpl implements StorageService { + + private static final Logger logger = LoggerFactory.getLogger(StorageServiceImpl.class); + + @Autowired + private SessionFactory sessionFactory; + + @Autowired + WidgetCatalogService widgetCatalogService; + + @Override + @Transactional + public void deleteWidgetFile(long widgetId) { + WidgetFile widgetFile = getWidgetFile(widgetId); + logger.debug("StorageServiceImpl.deleteWidgetFile: deleting widget file {}", widgetId); + if (widgetFile == null) { + logger.debug( + "StorageServiceImpl.deleteWidgetFile: No widget file found in database while performing StorageServiceImpl.deleteWidgetFile."); + return; + } + Session session = sessionFactory.getCurrentSession(); + Transaction tx = session.beginTransaction(); + session.delete(widgetFile); + tx.commit(); + } + + @Override + @SuppressWarnings("unchecked") + @Transactional + public WidgetFile getWidgetFile(long widgetId) { + logger.debug("StorageServiceImpl.getWidgetFile: getting widget file {}", widgetId); + WidgetFile widgetFile = null; + Session session = sessionFactory.openSession(); + Criteria criteria = session.createCriteria(WidgetFile.class); + criteria.add(Restrictions.eq("widgetId", widgetId)); + List<WidgetFile> widgetFiles = criteria.list(); + session.flush(); + session.close(); + if (widgetFiles.size() > 0) + widgetFile = widgetFiles.get(0); + return widgetFile; + } + + @Override + public ValidationRespond checkZipFile(MultipartFile file) { + StringBuilder error_msg = new StringBuilder(); + UnzipUtil unzipper = new UnzipUtil(); + Map<String, byte[]> map; + File convFile; + boolean isValid = true; + if (!file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')).equals(".zip")) { + isValid = false; + error_msg.append(WidgetConstant.VALIDATION_MESSAGE_ZIP); + logger.error("StorageServiceImpl.checkZipFile: invalid file format"); + } + try { + if (file.isEmpty()) { + logger.error( + "StorageServiceImpl.checkZipFile: Failed to store empty file " + file.getOriginalFilename()); + throw new StorageException( + "StorageServiceImpl.checkZipFile: Failed to store empty file " + file.getOriginalFilename()); + } + String fileLocation = file.getOriginalFilename(); + logger.debug("StorageServiceImpl.checkZipFile: store the widget to:" + fileLocation); + convFile = new File(fileLocation); + FileOutputStream fos = new FileOutputStream(convFile); + fos.write(file.getBytes()); + fos.close(); + map = unzipper.unzip_db(fileLocation, ".", "tempWidgets"); + convFile.delete(); + } catch (IOException e) { + logger.error("StorageServiceImpl.checkZipFile: Failed to store file " + file.getOriginalFilename(), e); + throw new StorageException( + "torageServiceImpl.checkZipFile: Failed to store file " + file.getOriginalFilename(), e); + } + + for (byte[] b : map.values()) { + if (isValid && b == null) { + isValid = false; + error_msg.append(WidgetConstant.VALIDATION_MESSAGE_FILES); + break; + } + } + return new ValidationRespond(isValid, error_msg.toString()); + } + + @Override + @Transactional + public void save(MultipartFile file, WidgetCatalog newWidget, long widgetId) { + + UnzipUtil unzipper = new UnzipUtil(); + Map<String, byte[]> map; + File convFile; + try { + if (file.isEmpty()) { + logger.error("Failed to store empty file " + file.getOriginalFilename()); + throw new StorageException("Failed to store empty file " + file.getOriginalFilename()); + } + String fileLocation = file.getOriginalFilename(); + logger.debug("StorageServiceImpl.save: store the widget to:" + fileLocation); + convFile = new File(fileLocation); + FileOutputStream fos = new FileOutputStream(convFile); + fos.write(file.getBytes()); + fos.close(); + map = unzipper.unzip_db(fileLocation, ".", "tempWidgets"); + convFile.delete(); + } catch (IOException e) { + logger.error("StorageServiceImpl.save: Failed to store file " + file.getOriginalFilename(), e); + throw new StorageException("Failed to store file " + file.getOriginalFilename(), e); + } + saveHelper(newWidget, widgetId, map); + } + + @Override + @Transactional + public void initSave(File file, WidgetCatalog newWidget, long widgetId) { + + UnzipUtil unzipper = new UnzipUtil(); + Map<String, byte[]> map; + + try { + String fileLocation = file.getPath(); + logger.debug("StorageServiceImpl.save: store the widget to:" + fileLocation); + map = unzipper.unzip_db(fileLocation, ".", "tempWidgets"); + } catch (IOException e) { + logger.error("StorageServiceImpl.save: Failed to store file " + file.getName(), e); + throw new StorageException("Failed to store file " + file.getName(), e); + } + + saveHelper(newWidget, widgetId, map); + } + + /** + * Helper method for saving widget files (controller.js, framework.js, + * markup.html and style.css) to ep_widget_catalog_files table in database + * + * @param newWidget + * @param widgetId + * @param map + */ + private void saveHelper(WidgetCatalog newWidget, long widgetId, Map<String, byte[]> map) { + + logger.debug("Going to save widget " + newWidget); + WidgetFile widgetFile = new WidgetFile(); + widgetFile.setName(newWidget.getName()); + widgetFile.setWidgetId(widgetId); + + InputStream fileInputStream = this.getClass().getClassLoader().getResourceAsStream("framework-template.js"); + + String sb = null; + try { + byte[] bytes = new byte[fileInputStream.available()]; + fileInputStream.read(bytes); + sb = new String(bytes, "UTF-8"); + } catch (IOException e) { + logger.error("StorageServiceImpl.save: Failed to load framework-template.js file ", e); + e.printStackTrace(); + } finally { + if (fileInputStream != null) { + try { + fileInputStream.close(); + } catch (IOException e) { + logger.error("StorageServiceImpl.update: Failed to close the fileInputStream ", e); + } + } + } + + String namespace = "Portal" + widgetId + "Widget"; + String controllerName = "Portal" + widgetId + "Ctrl"; + String cssName = "portal" + widgetId + "-css-ready"; + String colorArg1 = "color: #fff"; + String framework = sb.replaceAll("ARUGMENT1", namespace).replaceAll("ARUGMENT2", controllerName) + .replaceAll("ARUGMENT3", cssName).replaceAll("CSS_ARG1", colorArg1) + .replaceAll("MICROSERVICE_ID", newWidget.getServiceId().toString()) + .replaceAll("WIDGET_ID", Long.toString(widgetId)); + + widgetFile.setFramework(framework.getBytes()); + + final byte[] controllerLoc = map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION); + if (controllerLoc == null || controllerLoc.length == 0) + throw new IllegalArgumentException( + "Map is missing required key " + WidgetConstant.WIDGET_CONTROLLER_LOCATION); + String javascript = new String(controllerLoc); + String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1); + String functionName = functionHeader.substring(functionHeader.indexOf(" "), functionHeader.indexOf("(")).trim(); + javascript = javascript.replaceFirst(functionName, controllerName); + String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")")); + List<String> paramList = Arrays.asList(functionParam.split(",")); + + int left_bracket_index = javascript.indexOf("{") + 1; + String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;"; + javascript = javascript.substring(0, left_bracket_index) + widgetData + + javascript.substring(left_bracket_index); + + StringBuilder injectStr = new StringBuilder().append("["); + for (int i = 0; i < paramList.size(); i++) { + if (i == paramList.size() - 1) + injectStr.append("'" + paramList.get(i).trim() + "'];"); + else + injectStr.append("'" + paramList.get(i).trim() + "',"); + } + javascript = namespace + ".controller = " + javascript + ";" + namespace + ".controller.$inject = " + + injectStr.toString(); + + String html = new String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName, + controllerName); + ; + + Pattern cssPattern = Pattern.compile("#.*-css-ready"); + Matcher cssMatcher = cssPattern.matcher(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION))); + if (cssMatcher.find()) { + widgetFile.setCss(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION)) + .replace(cssMatcher.group(0), "#" + cssName).getBytes()); + } + + widgetFile.setMarkup(html.getBytes()); + widgetFile.setController(javascript.getBytes()); + Session session = sessionFactory.openSession(); + session.save(widgetFile); + session.flush(); + session.close(); + // sessionFactory.getCurrentSession().save(widgetFile); + logger.debug( + "StorageServiceImpl.save: saved fraemwork.js controller.js, markup.html and style.css files to the database for widget {}", + widgetId); + + } + + @Override + public void update(MultipartFile file, WidgetCatalog newWidget, long widgetId) { + UnzipUtil unzipper = new UnzipUtil(); + Map<String, byte[]> map; + File convFile; + try { + if (file.isEmpty()) { + logger.error("StorageServiceImpl.update: Failed to store empty file " + file.getOriginalFilename()); + throw new StorageException("Failed to store empty file " + file.getOriginalFilename()); + } + String fileLocation = file.getOriginalFilename(); + logger.debug("StorageServiceImpl.update: store the widget to:" + fileLocation); + convFile = new File(fileLocation); + FileOutputStream fos = new FileOutputStream(convFile); + fos.write(file.getBytes()); + fos.close(); + map = unzipper.unzip_db(fileLocation, ".", "tempWidgets"); + convFile.delete(); + } catch (IOException e) { + logger.error("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(), e); + throw new StorageException("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(), + e); + } + WidgetFile widgetFile = getWidgetFile(widgetId); + + InputStream fileInputStream = this.getClass().getClassLoader().getResourceAsStream("framework-template.js"); + String sb = null; + try { + byte[] bytes = new byte[fileInputStream.available()]; + fileInputStream.read(bytes); + sb = new String(bytes, "UTF-8"); + } catch (IOException e) { + logger.error("StorageServiceImpl.save: Failed to load framework-template.js file ", e); + e.printStackTrace(); + } finally { + if (fileInputStream != null) { + try { + fileInputStream.close(); + } catch (IOException e) { + logger.error("StorageServiceImpl.update: Failed to close the fileInputStream ", e); + e.printStackTrace(); + } + } + } + + String namespace = "Portal" + widgetId + "Widget"; + String controllerName = "Portal" + widgetId + "Ctrl"; + String cssName = "portal" + widgetId + "-css-ready"; + String colorArg1 = "color: #fff"; + String framework = sb.replaceAll("ARUGMENT1", namespace).replaceAll("ARUGMENT2", controllerName) + .replaceAll("ARUGMENT3", cssName).replaceAll("CSS_ARG1", colorArg1) + .replaceAll("MICROSERVICE_ID", newWidget.getServiceId().toString()) + .replaceAll("WIDGET_ID", Long.toString(widgetId)); + widgetFile.setFramework(framework.getBytes()); + + String javascript = new String(map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION)); + String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1); + String functionName = functionHeader.substring(functionHeader.indexOf(" "), functionHeader.indexOf("(")).trim(); + javascript = javascript.replaceFirst(functionName, controllerName); + String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")")); + List<String> paramList = Arrays.asList(functionParam.split(",")); + + int left_bracket_index = javascript.indexOf("{") + 1; + String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;"; + javascript = javascript.substring(0, left_bracket_index) + widgetData + + javascript.substring(left_bracket_index); + + StringBuilder injectStr = new StringBuilder().append("["); + for (int i = 0; i < paramList.size(); i++) { + if (i == paramList.size() - 1) + injectStr.append("'" + paramList.get(i).trim() + "'];"); + else + injectStr.append("'" + paramList.get(i).trim() + "',"); + } + javascript = namespace + ".controller = " + javascript + ";" + namespace + ".controller.$inject = " + + injectStr.toString(); + + String html = new String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName, + controllerName); + ; + + Pattern cssPattern = Pattern.compile("#.*-css-ready"); + Matcher cssMatcher = cssPattern.matcher(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION))); + if (cssMatcher.find()) { + widgetFile.setCss(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION)) + .replace(cssMatcher.group(0), "#" + cssName).getBytes()); + } + + widgetFile.setMarkup(html.getBytes()); + widgetFile.setController(javascript.getBytes()); + // widgetFile.setCss(map.get(WidgetConstant.WIDGET_STYLE_LOCATION)); + Session session = sessionFactory.openSession(); + Transaction tx = session.beginTransaction(); + session.update(widgetFile); + tx.commit(); + session.flush(); + session.close(); + logger.debug( + "StorageServiceImpl.save: updated fraemwork.js controller.js, markup.html and style.css files to the database for widget {}", + widgetId); + } + + @Override + @SuppressWarnings("unchecked") + @Transactional + public String getWidgetMarkup(long widgetId) throws UnsupportedEncodingException { + String markup = null; + Session session = sessionFactory.getCurrentSession(); + Criteria criteria = session.createCriteria(WidgetFile.class); + criteria.add(Restrictions.eq("widgetId", widgetId)); + List<WidgetFile> widgetFile = criteria.list(); + logger.debug("StorageServiceImpl.getWidgetMarkup: getting widget markup result={}", widgetFile); + + if (widgetFile.size() > 0) + markup = new String(widgetFile.get(0).getMarkup(), "UTF-8"); + return markup; + } + + @Override + @SuppressWarnings("unchecked") + @Transactional + public String getWidgetController(long widgetId) throws UnsupportedEncodingException { + String controller = null; + Session session = sessionFactory.getCurrentSession(); + Criteria criteria = session.createCriteria(WidgetFile.class); + criteria.add(Restrictions.eq("widgetId", widgetId)); + List<WidgetFile> widgetFile = criteria.list(); + logger.debug("StorageServiceImpl.getWidgetController: getting widget controller result={}", widgetFile); + + if (widgetFile.size() > 0) + controller = new String(widgetFile.get(0).getController(), "UTF-8"); + return controller; + } + + @Override + @SuppressWarnings("unchecked") + @Transactional + public String getWidgetFramework(long widgetId) throws UnsupportedEncodingException { + String framework = null; + Session session = sessionFactory.getCurrentSession(); + Criteria criteria = session.createCriteria(WidgetFile.class); + criteria.add(Restrictions.eq("widgetId", widgetId)); + List<WidgetFile> widgetFile = criteria.list(); + logger.debug("StorageServiceImpl.getWidgetFramework: getting widget framework result={}", widgetFile); + + if (widgetFile.size() > 0) + framework = new String(widgetFile.get(0).getFramework(), "UTF-8"); + return framework; + } + + @Override + @SuppressWarnings("unchecked") + @Transactional + public String getWidgetCSS(long widgetId) throws UnsupportedEncodingException { + String css = null; + Session session = sessionFactory.getCurrentSession(); + Criteria criteria = session.createCriteria(WidgetFile.class); + criteria.add(Restrictions.eq("widgetId", widgetId)); + List<WidgetFile> widgetFile = criteria.list(); + logger.debug("StorageServiceImpl.getWidgetCSS: getting widget css result={}", widgetFile); + + if (widgetFile.size() > 0) + css = new String(widgetFile.get(0).getCss(), "UTF-8"); + return css; + } + + @Override + @Transactional + public byte[] getWidgetCatalogContent(long widgetId) throws Exception { + + WidgetCatalog widget = widgetCatalogService.getWidgetCatalog(widgetId); + String namespace = "Portal" + widgetId + "Widget"; + String controllerName = "Portal" + widgetId + "Ctrl"; + String cssName = "portal" + widgetId + "-css-ready"; + + String styles = getWidgetCSS(widgetId).replaceAll(cssName, widget.getName() + "-css-ready"); + File f = File.createTempFile("temp", ".zip"); + ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f)); + ZipEntry e = new ZipEntry(widget.getName() + "/styles/styles.css"); + out.putNextEntry(new ZipEntry(widget.getName() + "/")); + out.putNextEntry(new ZipEntry(widget.getName() + "/styles/")); + out.putNextEntry(e); + byte[] data = styles.getBytes(); + out.write(data, 0, data.length); + + String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;"; + String javascript = getWidgetController(widgetId).replace(widgetData, "").replace(namespace + ".controller =", + ""); + + String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1); + javascript = javascript.replaceFirst(controllerName, widget.getName() + "Ctrl"); + String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")")); + StringBuilder injectStr = new StringBuilder().append("["); + List<String> paramList = Arrays.asList(functionParam.split(",")); + for (int i = 0; i < paramList.size(); i++) { + if (i == paramList.size() - 1) + injectStr.append("'" + paramList.get(i).trim() + "'];"); + else + injectStr.append("'" + paramList.get(i).trim() + "',"); + } + javascript = javascript.replace(";" + namespace + ".controller.$inject = " + injectStr.toString(), ""); + + e = new ZipEntry(widget.getName() + "/js/controller.js"); + out.putNextEntry(new ZipEntry(widget.getName() + "/js/")); + out.putNextEntry(e); + data = javascript.getBytes(); + out.write(data, 0, data.length); + + String html = getWidgetMarkup(widgetId).replaceFirst(controllerName, widget.getName() + "Ctrl"); + + // new + // String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName, + // controllerName);; + + e = new ZipEntry(widget.getName() + "/markup/markup.html"); + out.putNextEntry(new ZipEntry(widget.getName() + "/markup/")); + out.putNextEntry(e); + data = html.getBytes(); + out.write(data, 0, data.length); + out.closeEntry(); + out.close(); + byte[] result = Files.readAllBytes(Paths.get(f.getPath())); + f.delete(); + return result; + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/WidgetCatalogServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/WidgetCatalogServiceImpl.java new file mode 100644 index 00000000..51f78227 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/WidgetCatalogServiceImpl.java @@ -0,0 +1,243 @@ +package org.openecomp.portalapp.widget.service.impl; + +import java.util.List; +import java.util.Set; + +import javax.transaction.Transactional; + +import org.hibernate.Criteria; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; +import org.openecomp.portalapp.widget.domain.MicroserviceData; +import org.openecomp.portalapp.widget.domain.RoleApp; +import org.openecomp.portalapp.widget.domain.WidgetCatalog; +import org.openecomp.portalapp.widget.service.WidgetCatalogService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; + +@Service("widgetCatalogService") +@Transactional +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +public class WidgetCatalogServiceImpl implements WidgetCatalogService { + + private static final Logger logger = LoggerFactory.getLogger(WidgetCatalogServiceImpl.class); + + @Autowired + private SessionFactory sessionFactory; + + @SuppressWarnings("unchecked") + @Override + @Transactional + public List<WidgetCatalog> getWidgetCatalog(){ + Session session = sessionFactory.getCurrentSession(); + Criteria criteria = session.createCriteria(WidgetCatalog.class) + .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + List<WidgetCatalog> widgets = criteria.list(); + logger.debug("WidgetCatalogServiceImpl.getWidgetCatalog: result={}", widgets); + return widgets; + } + + @SuppressWarnings("unchecked") + @Transactional + public List<WidgetCatalog> getUserWidgetCatalog(String loginName){ + Session session = sessionFactory.getCurrentSession(); + StringBuilder sql = new StringBuilder() + + + .append(" select userWidgets.widget_id, userWidgets.wdg_name, userWidgets.wdg_desc, b.x, b.status_cd, b.y, b.height, b.width from ") + .append(" ( ") + .append(" select distinct w.widget_id, w.wdg_name, w.wdg_desc from ") + .append(" ep_widget_catalog w, ") + .append(" ep_widget_catalog_role wr, ") + .append(" fn_user_role ur, ") + .append(" fn_app app, ") + .append(" fn_user u ") + .append(" where ") + .append(" w.widget_id = wr.WIDGET_ID and ") + .append(" ur.app_id = app.app_id and ") + .append(" app.enabled = 'Y' and ") + .append(" wr.role_id = ur.role_id and ") + .append(" ur.user_id = u.user_id and ") + .append(" u.login_id = '" + loginName + "' and (w.all_user_flag = 'N' or w.all_user_flag is null) ") + .append(" ") + .append(" union all ") + .append(" ") + .append(" ") + .append(" select distinct w.widget_id, w.wdg_name, w.wdg_desc from ") + .append(" ep_widget_catalog w ") + .append(" where w.all_user_flag = 'Y' ") + .append(" ") + .append(" ) userWidgets ") + .append(" ") + .append(" left join ") + .append(" ") + .append(" ( ") + .append(" select case when pers.user_id is null then sel.user_id else pers.user_id end as 'user_id', case when sel.widget_id is null then ") + .append(" pers.widget_id else sel.widget_id end as 'widget_id', pers.x, sel.status_cd, pers.y, pers.height, pers.width ") + .append(" from (select * from ep_pers_user_widget_placement where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) pers ") + .append(" left outer join ") + .append(" (select * from ep_pers_user_widget_sel where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) sel ") + .append(" on (pers.user_id = sel.user_id and pers.widget_id = sel.widget_id) ") + .append(" ") + .append(" union ") + .append(" ") + .append(" select case when pers.user_id is null then sel.user_id else pers.user_id end as 'user_id', case when sel.widget_id is null ") + .append(" then pers.widget_id else sel.widget_id end as 'widget_id', pers.x, sel.status_cd, pers.y, pers.height, pers.width ") + .append(" from (select * from ep_pers_user_widget_placement where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) pers ") + .append(" right outer join ") + .append(" (select * from ep_pers_user_widget_sel where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) sel ") + .append(" on (pers.user_id = sel.user_id and pers.widget_id = sel.widget_id) ") + .append(" ") + .append(" order by user_id, widget_id ") + .append(" )b ") + .append(" on ") + .append(" (userWidgets.widget_id = b.widget_id) order by b.x; "); + + + + Query query = session.createSQLQuery(sql.toString()); + List<WidgetCatalog> widgets = query.list(); + logger.debug("WidgetCatalogServiceImpl.getUserWidgetCatalog: result size={}", widgets); + return widgets; + } + + @Override + public WidgetCatalog getWidgetCatalog(Long widgetCatalogId) { + Session session = sessionFactory.getCurrentSession(); + Transaction tx = session.beginTransaction(); + WidgetCatalog widget = (WidgetCatalog) session.get(WidgetCatalog.class, widgetCatalogId); + tx.commit(); + logger.debug("WidgetCatalogServiceImpl.getWidgetCatalog: getting widget={}", widget); + return widget; + } + + @Override + public void deleteWidgetCatalog(long widgetCatalogId) { + logger.debug("WidgetCatalogServiceImpl.deleteWidgetCatalog: deleting the widget with widgetId={}", widgetCatalogId); + WidgetCatalog widget = getWidgetCatalog(widgetCatalogId); + if (widget == null){ + logger.error("No widget found in database while performing WidgetCatalogServiceImpl.deleteWidgetCatalog."); + return; + } + Session session = sessionFactory.getCurrentSession(); + Transaction tx = session.beginTransaction(); + Query query = session.createSQLQuery("delete from ep_pers_user_widget_sel where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId); + query.executeUpdate(); + query = session.createSQLQuery("delete from ep_pers_user_widget_placement where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId); + query.executeUpdate(); + query = session.createSQLQuery("delete from ep_widget_catalog_files where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId); + query.executeUpdate(); + query = session.createSQLQuery("delete from ep_widget_catalog_parameter where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId); + query.executeUpdate(); + session.delete(widget); + tx.commit(); + } + + @Override + public long saveWidgetCatalog(WidgetCatalog newWidgetCatalog) { + + try{ + if(newWidgetCatalog.getAllowAllUser().equals("1")) + newWidgetCatalog.setAllowAllUser("Y"); + else + newWidgetCatalog.setAllowAllUser("N"); + + logger.debug("WidgetCatalogServiceImpl.saveWidgetCatalog: widget={}", newWidgetCatalog); + Session session = sessionFactory.openSession(); + Transaction tx = session.beginTransaction(); + session.save(newWidgetCatalog); + tx.commit(); + session.flush(); + session.close(); + updateAppId(newWidgetCatalog.getId(), newWidgetCatalog.getWidgetRoles()); + } + catch(Exception e){ + logger.error("Exception occurred while performing WidgetCatalogServiceImpl.saveWidgetCatalog in widget microservices. Details:" + e.getMessage()); + } + return newWidgetCatalog.getId(); + } + + @Override + public void updateWidgetCatalog(Long widgetCatalogId, WidgetCatalog newWidgetCatalog) { + logger.debug("WidgetCatalogServiceImpl.updateWidgetCatalog: widget={}", newWidgetCatalog); + WidgetCatalog oldWidget = getWidgetCatalog(widgetCatalogId); + try{ + if (newWidgetCatalog.getAllowAllUser().equals("1")) + newWidgetCatalog.setAllowAllUser("Y"); + else + newWidgetCatalog.setAllowAllUser("N"); + + newWidgetCatalog.setId(widgetCatalogId); + newWidgetCatalog.setServiceId(oldWidget.getServiceId()); + Session session = sessionFactory.openSession(); + Transaction tx = session.beginTransaction(); + session.update(newWidgetCatalog); + tx.commit(); + session.flush(); + session.close(); + updateAppId(newWidgetCatalog.getId(), newWidgetCatalog.getWidgetRoles()); + }catch(Exception e){ + logger.error("Exception occurred while performing WidgetCatalogServiceImpl.updateWidgetCatalog in widget microservices. Details:" + e.getMessage()); + } + + } + + @Override + public Long getServiceIdByWidget(Long widgetCatalogId) { + Session session = sessionFactory.getCurrentSession(); + WidgetCatalog widget = (WidgetCatalog) session.get(WidgetCatalog.class, widgetCatalogId); + logger.debug("WidgetCatalogServiceImpl.getServiceIdByWidget: result={}", widget); + return widget.getServiceId(); + } + + @Override + public List<WidgetCatalog> getWidgetsByServiceId(Long serviceId) { + Session session = sessionFactory.getCurrentSession(); + Criteria criteria = session.createCriteria(WidgetCatalog.class) + .add(Restrictions.eq("serviceId", serviceId)) + .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + List<WidgetCatalog> widgets = criteria.list(); + logger.debug("WidgetCatalogServiceImpl.getWidgetCatalog: result={}", widgets); + return widgets; + } + + + + + + private void updateAppId(long widgetId, Set<RoleApp> roles){ + Session session = sessionFactory.openSession(); + for(RoleApp role: roles){ + String sql = "UPDATE ep_widget_catalog_role SET app_id = " + role.getApp().getAppId() + " WHERE widget_id = " + widgetId + " AND ROLE_ID = " + role.getRoleId() ; + Query query = session.createSQLQuery(sql); + query.executeUpdate(); + } + session.flush(); + session.close(); + } + + @Override + public boolean getWidgetIdByName(String newWidgetName) { + Session session = sessionFactory.openSession(); + Criteria criteria = session.createCriteria(WidgetCatalog.class) + .add(Restrictions.eq("name", newWidgetName)) + .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + + List<MicroserviceData> widgets = criteria.list(); + logger.debug("WidgetCatalogServiceImpl.getWidgetIdByName: result={}", widgets); + session.flush(); + session.close(); + + return (widgets.size() > 0) ? true : false; + } + + +} + diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/AuthorizationUtil.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/AuthorizationUtil.java new file mode 100644 index 00000000..f25f0db6 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/AuthorizationUtil.java @@ -0,0 +1,19 @@ +package org.openecomp.portalapp.widget.utils; + +import java.nio.charset.Charset; +import java.util.Base64; + +public class AuthorizationUtil { + + public boolean authorization(String auth, String security_user, String security_pass){ + if (auth != null && auth.startsWith("Basic")) { + String base64Credentials = auth.substring("Basic".length()).trim(); + String credentials = new String(Base64.getDecoder().decode(base64Credentials), + Charset.forName("UTF-8")); + final String[] values = credentials.split(":",2); + if(security_user.equals(values[0]) && security_pass.equals(values[1])) + return true; + } + return false; + } +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/UnzipUtil.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/UnzipUtil.java new file mode 100644 index 00000000..1d61d587 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/UnzipUtil.java @@ -0,0 +1,110 @@ +package org.openecomp.portalapp.widget.utils; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.openecomp.portalapp.widget.constant.WidgetConstant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UnzipUtil { + + /** + * Size of the buffer to read/write data + */ + private static final int BUFFER_SIZE = 4096; + private static final Logger logger = LoggerFactory.getLogger(UnzipUtil.class); + + /** + * Extracts a zip file specified by the zipFilePath to a directory specified by + * destDirectory (will be created if does not exists) + * + * @param zipFilePath + * path + * @param destDirectory + * directory + * @param widgetName + * name + * @return Map of contents + * @throws IOException + * On error + */ + public Map<String, byte[]> unzip_db(String zipFilePath, String destDirectory, String widgetName) + throws IOException { + + logger.debug("UnzipUtil.unzip_db: unzip widget file {}", widgetName); + File destDir = new File(destDirectory); + if (!destDir.exists()) + destDir.mkdir(); + ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath)); + ZipEntry entry = zipIn.getNextEntry(); + Map<String, byte[]> map = new HashMap<>(); + + String[] requiredKeys = { WidgetConstant.WIDGET_CONTROLLER_LOCATION, WidgetConstant.WIDGET_MARKUP_LOCATION, + WidgetConstant.WIDGET_STYLE_LOCATION }; + for (String k : requiredKeys) + map.put(k, null); + + // iterates over entries in the zip file + Stack<File> stack = new Stack<>(); + while (entry != null) { + String filePath = destDirectory + File.separator + widgetName + File.separator + + entry.getName().substring(entry.getName().indexOf("/") + 1); + final String entryShortName = entry.getName().substring(entry.getName().indexOf("/") + 1); + logger.debug("UnzipUtil.unzip_db: file path {}, short name {}", filePath, entryShortName); + if (!entry.isDirectory()) { + // if the entry is a file, extracts it + logger.debug("UnzipUtil.unzip_db: unzip and save widget file {}", filePath); + stack.push(new File(filePath)); + extractFile(zipIn, filePath); + } else { + // if the entry is a directory, make the directory + logger.debug("UnzipUtil.unzip_db: unzip and create widget folder {}", filePath); + File dir = new File(filePath); + stack.push(new File(filePath)); + dir.mkdir(); + } + // Is this one we need? + if (map.containsKey(entryShortName)) + map.put(entryShortName, Files.readAllBytes(Paths.get(filePath))); + zipIn.closeEntry(); + entry = zipIn.getNextEntry(); + } + zipIn.close(); + while (!stack.isEmpty()) + stack.pop().delete(); + + for (String k : requiredKeys) + if (!map.containsKey(k)) + logger.warn("UnzipUtil.unzip_db: no zip archive entry found for required key {}", k); + + return map; + } + + /** + * Extracts a zip entry (file entry) + * + * @param zipIn + * @param filePath + * @throws IOException + */ + private void extractFile(ZipInputStream zipIn, String filePath) throws IOException { + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); + byte[] bytesIn = new byte[BUFFER_SIZE]; + int read = 0; + while ((read = zipIn.read(bytesIn)) != -1) { + bos.write(bytesIn, 0, read); + } + bos.close(); + } +}
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/application-properties b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application-properties new file mode 100644 index 00000000..77d2b78d --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application-properties @@ -0,0 +1,28 @@ +## General App Properties +server.contextPath=/widget +server.port=8082 +spring.http.multipart.max-file-size=128MB +spring.http.multipart.max-request-size=128MB +microservice.widget.location=/demeter/WebApps/dev/ECOMPPORTAL/microservices/widgets-dir/ + +## App DB Properties +spring.datasource.url=jdbc:mariadb:failover://demeter.homer.att.com:3306/ecomp_portal_1702&connectTimeout=2000 +spring.datasource.username=portal +spring.datasource.password=ENC(8tWrJAXdOKaMqvrVy5e2Jg==) +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.database.driver.classname=org.mariadb.jdbc.Driver +spring.jpa.show-sql=false +spring.jpa.properties.hibernate.format_sql=false + +## Basic Authentication Properties +security.user.name=widget_user +security.user.password=ENC(IjywcRnI9+nuVEh9+OFFiRWAjBT1n718) + +## Certificate Properties +#server.ssl.key-store=classpath:widget-keystore.p12 +#server.ssl.key-store-password=ENC(DiIYnAMab4u7rEW2yKhF9zBL00uU55q8) +#server.ssl.keyStoreType=PKCS12 +#server.ssl.keyAlias=widget-microservice + +## Jasypt Properties +jasypt.encryptor.password=EncryptionKey diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/application.properties.templated b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application.properties.templated new file mode 100644 index 00000000..ec4803f0 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application.properties.templated @@ -0,0 +1,35 @@ +## General App Properties +server.contextPath=/widget +server.port=8082 +spring.http.multipart.max-file-size=128MB +spring.http.multipart.max-request-size=128MB + +## App DB Properties +spring.datasource.url=jdbc:mariadb:failover://{db_host:db_port/{portal_db} +spring.datasource.username={username} +spring.datasource.password=ENC({encrypted_password}) +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.database.driver.classname=org.mariadb.jdbc.Driver +spring.jpa.show-sql=false +spring.jpa.properties.hibernate.format_sql=false + +## Basic Authentication Properties +security.user.name={basic_auth_username} +security.user.password=ENC({encrypted_basic_auth_password}) + +## Initalization setting +initialization.default.widgets=true +initialization.widgetData.url={widgetData_url} + +## Account Basic Authentication Properties +account.user.name=portal +account.user.password=6APqvG4AU2rfLgCvMdySwQ== + +## Certificate Properties +#server.ssl.key-store=classpath:widget-keystore.p12 +#server.ssl.key-store-password=ENC(DiIYnAMab4u7rEW2yKhF9zBL00uU55q8) +#server.ssl.keyStoreType=PKCS12 +#server.ssl.keyAlias=widget-microservice + +## Jasypt Properties +jasypt.encryptor.password=EncryptionKey
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/framework-template.js b/ecomp-portal-widget-ms/widget-ms/src/main/resources/framework-template.js new file mode 100644 index 00000000..45350d91 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/framework-template.js @@ -0,0 +1,173 @@ +var ARUGMENT1 = (function(window, undefined) { + + var ARUGMENT1 = ARUGMENT1 || {}; + function extractHostPortApp(src) { + ARUGMENT1.microserviceId = MICROSERVICE_ID; + ARUGMENT1.pathArray = src.split( '/' ); + ARUGMENT1.widgetName = ARUGMENT1.pathArray[ARUGMENT1.pathArray.length - 2]; + ARUGMENT1.serviceSeperator = ARUGMENT1.pathArray[ARUGMENT1.pathArray.length - 4]; + ARUGMENT1.commonUrl = src.substring(0, src.lastIndexOf("/" + ARUGMENT1.widgetName)); + ARUGMENT1.recipientDivDataAttrib = 'data-' + ARUGMENT1.widgetName; + ARUGMENT1.controllerName = 'ARUGMENT2'; + ARUGMENT1.readyCssFlag = 'ARUGMENT3'; + ARUGMENT1.readyCssFlagExpectedValue = '#bada55'; + ARUGMENT1.serviceURL = src.substring(0, src.lastIndexOf("/" + ARUGMENT1.serviceSeperator)) + '/portalApi/microservice/proxy/parameter/' + WIDGET_ID; + } + + extractHostPortApp(document.currentScript.src); + + function loadStylesheet(url) { + var link = document.createElement('link'); + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = url; + var entry = document.getElementsByTagName('script')[0]; + entry.parentNode.insertBefore(link, entry); + } + + function isCssReady(callback) { + var testElem = document.createElement('span'); + testElem.id = ARUGMENT1.readyCssFlag; + testElem.style = 'CSS_ARG1'; + var entry = document.getElementsByTagName('script')[0]; + entry.parentNode.insertBefore(testElem, entry); + + (function poll() { + var node = document.getElementById('css-ready'); + var value; + if (window.getComputedStyle) { + value = document.defaultView.getComputedStyle(testElem, null) + .getPropertyValue('color'); + } + else if (node.currentStyle) { + value = node.currentStyle.color; + } + if (value && value === 'rgb(186, 218, 85)' || value.toLowerCase() === ARUGMENT1.readyCssFlagExpectedValue) { + callback(); + } else { + setTimeout(poll, 500); + } + })(); + } + + function injectCss(css) { + var style = document.createElement('style'); + style.type = 'text/css'; + css = css.replace(/\}/g, "}\n"); + + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + var entry = document.getElementsByTagName('script')[0]; + entry.parentNode.insertBefore(style, entry); + } + + function loadScript(url, callback) { + var script = document.createElement('script'); + script.src = url; + var entry = document.getElementsByTagName('script')[0]; + entry.parentNode.insertBefore(script, entry); + script.onload = script.onreadystatechange = function() { + var rdyState = script.readyState; + if (!rdyState || /complete|loaded/.test(script.readyState)) { + callback(); + script.onload = null; + script.onreadystatechange = null; + } + }; + } + + function loadSupportingFiles(callback) { + callback(); + } + + function getWidgetParams() { + + } + + function getWidgetData(widgetUrl, callback) { + var responseData; + try{ + jQuery.ajax({ + url: widgetUrl, + method: "GET", + xhrFields: { + withCredentials: true + }, + crossDomain: true, + success: function (result) { + if (result.isOk == false){ + + }else{ + callback(result); + } + } + }); + } + catch(e){ + + } + + } + + function getMarkupContent(markupLocation, target){ + + jQuery.ajax({ + url: markupLocation, + success: function (result) { + if (result.isOk == false){ + + }else{ + target.innerHTML = result; + } + }, + async: false + }); + } + + function renderWidget(data, location, $controllerProvider) { + var div = document.createElement('div'); + getMarkupContent(ARUGMENT1.commonUrl + "/markup/" + ARUGMENT1.widgetName, div); + location.append(div); + ARUGMENT1.widgetData = data; + app.controllerProvider.register(ARUGMENT1.controllerName, ARUGMENT1.controller); + var mController = angular.element(document.getElementById("widgets")); + mController.scope().activateThis(location); + } + + function printAllArtifacts(moduleName, controllerName) { + var queue = angular.module(moduleName)._invokeQueue; + for(var i=0;i<queue.length;i++) { + var call = queue[i]; + console.log(i + '. ' + call[0] + ' - ' + call[1] + ' - ' + call[2][0]); + } + } + + function get(name){ + if(name=(new RegExp('[?&]'+encodeURIComponent(name)+'=([^&]*)')).exec(location.search)) + return decodeURIComponent(name[1]); + } + + loadSupportingFiles(function() { + loadStylesheet(ARUGMENT1.commonUrl + '/' + ARUGMENT1.widgetName + '/style.css'); + loadScript(ARUGMENT1.commonUrl + '/' + ARUGMENT1.widgetName + '/controller.js', + function() { + $('['+ ARUGMENT1.recipientDivDataAttrib + ']').each(function() { + var location = jQuery(this); + location.removeAttr(ARUGMENT1.recipientDivDataAttrib); + var id = location.attr(ARUGMENT1.recipientDivDataAttrib); + getWidgetData(ARUGMENT1.serviceURL, function(data) { + isCssReady(function(){ + renderWidget(data, location); + }); + }); + }); + } + ); + }); + + return ARUGMENT1; +})(window); +
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/logback.xml b/ecomp-portal-widget-ms/widget-ms/src/main/resources/logback.xml new file mode 100644 index 00000000..204a6598 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/logback.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + + <property name="WIDGET_LOG_HOME" value="logs" /> + + + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.classic.PatternLayout"> + <Pattern> + %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + </Pattern> + </layout> + </appender> + + <logger name="org.springframework.web" level="info" additivity="false"> + <appender-ref ref="STDOUT" /> + </logger> + + <contextName>${HOSTNAME}</contextName> + + + <appender name="ADUIT" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${WIDGET_LOG_HOME}/aduit.log</file> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <Pattern> + %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n" + </Pattern> + </encoder> + <!-- %d{yyyy-MM-dd HH:mm:ss} - %msg%n --> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${WIDGET_LOG_HOME}/archived/aduit.%d{yyyy-MM-dd}.%i.zip + </fileNamePattern> + <maxHistory>30</maxHistory> + <timeBasedFileNamingAndTriggeringPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>100KB</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + </appender> + + <appender name="APPLICATION" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${WIDGET_LOG_HOME}/application.log</file> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <Pattern> + %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n" + </Pattern> + </encoder> + <!-- %d{yyyy-MM-dd HH:mm:ss} - %msg%n --> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${WIDGET_LOG_HOME}/archived/application.%d{yyyy-MM-dd}.%i.zip + </fileNamePattern> + <maxHistory>30</maxHistory> + <timeBasedFileNamingAndTriggeringPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>100KB</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + </appender> + + + <appender name="DEBUG" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${WIDGET_LOG_HOME}/debug.log</file> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <Pattern> + %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n" + </Pattern> + </encoder> + <!-- %d{yyyy-MM-dd HH:mm:ss} - %msg%n --> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${WIDGET_LOG_HOME}/archived/debug.%d{yyyy-MM-dd}.%i.zip + </fileNamePattern> + <maxHistory>30</maxHistory> + <timeBasedFileNamingAndTriggeringPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>100KB</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + </appender> + + + <appender name="ERROR" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${WIDGET_LOG_HOME}/error.log</file> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <Pattern> + %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n" + </Pattern> + </encoder> + + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${WIDGET_LOG_HOME}/archived/error.%d{yyyy-MM-dd}.%i.zip + </fileNamePattern> + <maxHistory>30</maxHistory> + <timeBasedFileNamingAndTriggeringPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>100KB</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + </appender> + + + <appender name="METRICS" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${WIDGET_LOG_HOME}/metrics.log</file> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <Pattern> + %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n" + </Pattern> + </encoder> + + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${WIDGET_LOG_HOME}/archived/metrics.%d{yyyy-MM-dd}.%i.zip + </fileNamePattern> + <maxHistory>30</maxHistory> + <timeBasedFileNamingAndTriggeringPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>100KB</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + </appender> + + <logger name="org.openecomp.portalapp.widget" level="debug" additivity="false"> + <appender-ref ref="ERROR" /> + <appender-ref ref="DEBUG" /> + <appender-ref ref="APPLICATION" /> + <appender-ref ref="STDOUT" /> + </logger> + + <root level="info"> + <appender-ref ref="DEBUG" /> + <appender-ref ref="APPLICATION" /> + <appender-ref ref="STDOUT" /> + </root> + +</configuration>
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/Upload.html b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/Upload.html new file mode 100644 index 00000000..a5e7c632 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/Upload.html @@ -0,0 +1,17 @@ +<html> +<body> + <div align="center"> + <form method="post" action="doUpload/widget-resources" enctype="multipart/form-data"> + <table border="0"> + <tr> + <td>Pick file:</td> + <td><input type="file" name="fileUpload" size="50" /></td> + </tr> + <tr> + <td colspan="2" align="center"><input type="submit" value="Upload" /></td> + </tr> + </table> + </form> + </div> +</body> +</html>
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/widgetsPage.html b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/widgetsPage.html new file mode 100644 index 00000000..440f64ca --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/widgetsPage.html @@ -0,0 +1,15 @@ +<html xmlns:th="http://www.thymeleaf.org"> +<body> + + <p> Uploaded Widgets: </p> + + <div> + <ul> + <li th:each="file : ${files}"> + <a th:href="${file}" th:text="${file}" /> + </li> + </ul> + </div> + +</body> +</html> diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget-keystore.p12 b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget-keystore.p12 Binary files differnew file mode 100644 index 00000000..b2dd42ff --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget-keystore.p12 diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_start.sh b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_start.sh new file mode 100755 index 00000000..8405fe99 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_start.sh @@ -0,0 +1,4 @@ +APP_PROPERTY_LOCATION=/tmp/application.properties +echo "Starting ecomp-portal-widget-ms image in a new container !!!" +docker run -d --name "ecomp-portal-widget-ms" -p 8083:8082 -v $APP_PROPERTY_LOCATION:/application.properties ecompportal-widget-ms + diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_stop.sh b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_stop.sh new file mode 100755 index 00000000..8c9abf56 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_stop.sh @@ -0,0 +1,5 @@ +echo "Stopping ecomp-portal-widget-ms container !!!" +docker stop ecomp-portal-widget-ms +echo "Removing docker image portal-widget-ms !!!" +docker rm ecomp-portal-widget-ms + diff --git a/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetFileControllerTest.java b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetFileControllerTest.java new file mode 100644 index 00000000..2045435c --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetFileControllerTest.java @@ -0,0 +1,74 @@ +package org.openecomp.portalapp.widget.test.controller; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.times; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.runners.MockitoJUnitRunner; +import org.openecomp.portalapp.widget.controller.DatabaseFileUploadController; +import org.openecomp.portalapp.widget.service.impl.StorageServiceImpl; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + + +@RunWith(MockitoJUnitRunner.class) +public class WidgetFileControllerTest { + private MockMvc mockMvc; + + @Mock + private StorageServiceImpl storageService; + + @InjectMocks + private DatabaseFileUploadController controller; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); + } + + @Test + public void getWidgetMarkup_NoError() throws Exception{ + ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class); + Long widgetId = new Long(1); + mockMvc.perform(MockMvcRequestBuilders.get("/microservices/markup/" + widgetId)).andReturn();; + Mockito.verify(storageService, times(1)).getWidgetMarkup(storageServiceArg.capture()); + assertEquals(storageServiceArg.getValue(), widgetId); + } + + @Test + public void getWidgetController_NoError() throws Exception{ + ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class); + Long widgetId = new Long(1); + mockMvc.perform(MockMvcRequestBuilders.get("/microservices/" + widgetId + "/controller.js")).andReturn();; + Mockito.verify(storageService, times(1)).getWidgetController(storageServiceArg.capture()); + assertEquals(storageServiceArg.getValue(), widgetId); + } + + @Test + public void getWidgetFramework_NoError() throws Exception{ + ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class); + Long widgetId = new Long(1); + mockMvc.perform(MockMvcRequestBuilders.get("/microservices/" + widgetId + "/framework.js")).andReturn();; + Mockito.verify(storageService, times(1)).getWidgetFramework(storageServiceArg.capture()); + assertEquals(storageServiceArg.getValue(), widgetId); + } + + @Test + public void getWidgetCSS_NoError() throws Exception{ + ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class); + Long widgetId = new Long(1); + mockMvc.perform(MockMvcRequestBuilders.get("/microservices/" + widgetId + "/styles.css")).andReturn();; + Mockito.verify(storageService, times(1)).getWidgetCSS(storageServiceArg.capture()); + assertEquals(storageServiceArg.getValue(), widgetId); + } + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetsCatalogControllerTest.java b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetsCatalogControllerTest.java new file mode 100644 index 00000000..bd7eba3a --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetsCatalogControllerTest.java @@ -0,0 +1,195 @@ +package org.openecomp.portalapp.widget.test.controller; + + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.times; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.codec.binary.Base64; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.runners.MockitoJUnitRunner; +import org.openecomp.portalapp.widget.controller.WidgetsCatalogController; +import org.openecomp.portalapp.widget.domain.ValidationRespond; +import org.openecomp.portalapp.widget.domain.WidgetCatalog; +import org.openecomp.portalapp.widget.service.StorageService; +import org.openecomp.portalapp.widget.service.WidgetCatalogService; +import org.springframework.http.MediaType; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.multipart.MultipartFile; + +@RunWith(MockitoJUnitRunner.class) +public class WidgetsCatalogControllerTest { + + private MockMvc mockMvc; + + @Mock + private WidgetCatalogService widgetService; + + @Mock + private StorageService storageService; + + @InjectMocks + private WidgetsCatalogController controller; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); + } + + @Test + public void getWidgetCatalog_ValidAuthorization_NoError() throws Exception { + List<WidgetCatalog> list = new ArrayList<WidgetCatalog>(); + WidgetCatalog widget = new WidgetCatalog(); + widget.setId(1); + widget.setName("junit"); + list.add(widget); + Mockito.when(widgetService.getWidgetCatalog()).thenReturn(list); + + String security_user = "user"; + String security_pass = "password"; + + ReflectionTestUtils.setField(controller, "security_user", security_user, String.class); + ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class); + + String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes())); + mockMvc.perform(get("/microservices/widgetCatalog/").header("Authorization", basic_auth)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(1))) + .andExpect(jsonPath("$[0].name", is("junit"))); + } + + @Test + public void getWidgetCatalog_InValidAuthorization_Unauthorized() throws Exception { + + String security_user = "user"; + String security_pass = "password"; + String wrong_pass = "wrong"; + + ReflectionTestUtils.setField(controller, "security_user", security_user, String.class); + ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class); + + String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + wrong_pass).getBytes())); + mockMvc.perform(get("/microservices/widgetCatalog/").header("Authorization", basic_auth)) + .andExpect(status().isUnauthorized()); + } + + @Test + public void getWidgetCatalog_NoAuthorization_BadRequest() throws Exception { + List<WidgetCatalog> list = new ArrayList<WidgetCatalog>(); + WidgetCatalog widget = new WidgetCatalog(); + list.add(widget); + Mockito.when(widgetService.getWidgetCatalog()).thenReturn(list); + + mockMvc.perform(get("/microservices/widgetCatalog/")) + .andExpect(status().isBadRequest()); + } + + + @Test + public void saveWidgetCatalog_ValidAuthorization_NoError() throws Exception { + ValidationRespond respond = new ValidationRespond(true, null); + Mockito.when(storageService.checkZipFile(any(MultipartFile.class))).thenReturn(respond); + + String security_user = "user"; + String security_pass = "password"; + + ReflectionTestUtils.setField(controller, "security_user", security_user, String.class); + ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class); + + String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes())); + mockMvc.perform(MockMvcRequestBuilders.fileUpload("/microservices/widgetCatalog/").file("file", null) + .param("widget", "{}") + .header("Authorization", basic_auth) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(jsonPath("$.valid", is(true))); + + Mockito.verify(widgetService, times(1)).saveWidgetCatalog(any(WidgetCatalog.class)); + } + + + @Test + public void updateWidgetCatalog_ValidAuthorization_NoError() throws Exception { + String security_user = "user"; + String security_pass = "password"; + Long widgetId = new Long(1); + ArgumentCaptor<Long> widgetServiceArg = ArgumentCaptor.forClass(Long.class); + + ReflectionTestUtils.setField(controller, "security_user", security_user, String.class); + ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class); + + String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes())); + mockMvc.perform(put("/microservices/widgetCatalog/" + widgetId).contentType(MediaType.APPLICATION_JSON).content("{}").header("Authorization", basic_auth)); + + Mockito.verify(widgetService, times(1)).updateWidgetCatalog(widgetServiceArg.capture(), any(WidgetCatalog.class)); + assertEquals(widgetServiceArg.getValue(), widgetId); + } + + + @Test + public void updateWidgetCatalogwithFiles_ValidAuthorization_NoError() throws Exception { + ValidationRespond respond = new ValidationRespond(true, null); + Mockito.when(storageService.checkZipFile(any(MultipartFile.class))).thenReturn(respond); + + String security_user = "user"; + String security_pass = "password"; + Long widgetId = new Long(1); + ArgumentCaptor<Long> widgetServiceArg = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class); + + ReflectionTestUtils.setField(controller, "security_user", security_user, String.class); + ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class); + + String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes())); + mockMvc.perform(MockMvcRequestBuilders.fileUpload("/microservices/widgetCatalog/" + widgetId).file("file", null) + .param("widget", "{}") + .header("Authorization", basic_auth) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(jsonPath("$.valid", is(true))); + + Mockito.verify(widgetService, times(1)).updateWidgetCatalog(widgetServiceArg.capture(), any(WidgetCatalog.class)); + assertEquals(widgetServiceArg.getValue(), widgetId); + } + + @Test + public void deleteOnboardingWidget_ValidAuthorization_NoError() throws Exception { + + String security_user = "user"; + String security_pass = "password"; + Long widgetId = new Long(1); + + ReflectionTestUtils.setField(controller, "security_user", security_user, String.class); + ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class); + + String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes())); + mockMvc.perform(MockMvcRequestBuilders.delete("/microservices/widgetCatalog/" + widgetId) + .header("Authorization", basic_auth)); + ArgumentCaptor<Long> widgetServiceArg = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class); + + Mockito.verify(widgetService, times(1)).deleteWidgetCatalog(widgetServiceArg.capture()); + assertEquals(widgetServiceArg.getValue(), widgetId); + Mockito.verify(storageService, times(1)).deleteWidgetFile(storageServiceArg.capture()); + assertEquals(storageServiceArg.getValue(), widgetId); + } + + +} diff --git a/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/service/WidgetCatalogServiceTest.java b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/service/WidgetCatalogServiceTest.java new file mode 100644 index 00000000..3def6062 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/service/WidgetCatalogServiceTest.java @@ -0,0 +1,124 @@ +package org.openecomp.portalapp.widget.test.service; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.runners.MockitoJUnitRunner; +import org.openecomp.portalapp.widget.domain.RoleApp; +import org.openecomp.portalapp.widget.domain.WidgetCatalog; +import org.openecomp.portalapp.widget.service.impl.WidgetCatalogServiceImpl; + + +@RunWith(MockitoJUnitRunner.class) +public class WidgetCatalogServiceTest { + + @Mock + private SessionFactory mockedSessionFactory; + + @InjectMocks + private WidgetCatalogServiceImpl widgetCatalogService; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void getWidgetCatalog_NoError() throws Exception{ + Session mockedSession = Mockito.mock(Session.class); + Criteria mockedCriteria = Mockito.mock(Criteria.class); + + List<WidgetCatalog> list = new ArrayList<WidgetCatalog>(); + WidgetCatalog widget = new WidgetCatalog(); + widget.setId(1); + widget.setName("junit"); + list.add(widget); + + Mockito.when(mockedSessionFactory.getCurrentSession()).thenReturn(mockedSession); + Mockito.when(mockedSession.createCriteria(WidgetCatalog.class)).thenReturn(mockedCriteria); + Mockito.when(mockedCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)).thenReturn(mockedCriteria); + Mockito.when(mockedCriteria.list()).thenReturn(list); + + List<WidgetCatalog> result = widgetCatalogService.getWidgetCatalog(); + assertNotNull(result); + assertEquals(result, list); + } + + + @Test + public void saveWidgetCatalog_NoError() throws Exception{ + Set<RoleApp> set = new HashSet<RoleApp>(); + WidgetCatalog widget = new WidgetCatalog(); + widget.setId(1); + widget.setName("junit"); + widget.setAllowAllUser("1"); + widget.setWidgetRoles(set); + + Session mockedSession = Mockito.mock(Session.class); + Transaction mockedTransaction = Mockito.mock(Transaction.class); + Mockito.when(mockedSessionFactory.openSession()).thenReturn(mockedSession); + Mockito.when(mockedSession.beginTransaction()).thenReturn(mockedTransaction); + long widgetId = widgetCatalogService.saveWidgetCatalog(widget); + assertNotNull(widgetId); + assertEquals(widgetId, 1); + } + + @Rule public ExpectedException thrown = ExpectedException.none(); + + + @Test + public void deleteWidgetCatalog_NoError() throws Exception{ + long widgetId =1 ; + WidgetCatalog widget = new WidgetCatalog(); + widget.setId(1); + widget.setName("junit"); + + Session mockedSession = Mockito.mock(Session.class, RETURNS_DEEP_STUBS); + Transaction mockedTransaction = Mockito.mock(Transaction.class); + + Mockito.when(mockedSessionFactory.getCurrentSession()).thenReturn(mockedSession); + Mockito.when(mockedSession.beginTransaction()).thenReturn(mockedTransaction); + Mockito.when(mockedSession.get(WidgetCatalog.class, widgetId)).thenReturn(widget); + + widgetCatalogService.deleteWidgetCatalog(widgetId); + } + + @Test + public void updateWidgetCatalog_NoError() throws Exception{ + long widgetId =1 ; + WidgetCatalog widget = new WidgetCatalog(); + widget.setId(1); + widget.setName("junit"); + + Session mockedSession = Mockito.mock(Session.class, RETURNS_DEEP_STUBS); + Transaction mockedTransaction = Mockito.mock(Transaction.class); + + Mockito.when(mockedSessionFactory.getCurrentSession()).thenReturn(mockedSession); + Mockito.when(mockedSession.beginTransaction()).thenReturn(mockedTransaction); + Mockito.when(mockedSession.get(WidgetCatalog.class, widgetId)).thenReturn(widget); + + widgetCatalogService.deleteWidgetCatalog(widgetId); + } + + +} diff --git a/ecomp-portal-widget-ms/widget-ms/testadd.txt b/ecomp-portal-widget-ms/widget-ms/testadd.txt new file mode 100644 index 00000000..bdf08de0 --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/testadd.txt @@ -0,0 +1 @@ +test file
\ No newline at end of file diff --git a/ecomp-portal-widget-ms/widget-ms/website.url b/ecomp-portal-widget-ms/widget-ms/website.url Binary files differnew file mode 100644 index 00000000..4b50369c --- /dev/null +++ b/ecomp-portal-widget-ms/widget-ms/website.url |