From dd9aba154223d878309b7185a345363939559d56 Mon Sep 17 00:00:00 2001 From: Ioakeim Samaras Date: Thu, 26 Sep 2019 19:59:59 +0300 Subject: [PATCH] [UI] Support user creation Creation of users is supported. The AES PKCS#5 is used for encrypting/decrypting passwords in database. JIRA: VAL-57 Signed-off-by: Ioakeim Samaras Change-Id: I2469eac0c2b7ab99f3853ac3a023b325c51285f2 --- .coafile | 3 +- docker/README.rst | 9 +- docker/mariadb/deploy.sh | 27 +--- docker/ui/deploy.sh | 18 ++- ui/CHANGELOG.md | 9 ++ ui/README.rst | 17 +- ui/db-scripts/EcompSdkDMLMySql_2_4_OS.sql | 5 +- ui/pom.xml | 3 +- .../akraino/validation/ui/conf/UiInitializer.java | 38 +++++ .../ui/controller/ModelsViewsController.java | 6 + .../validation/ui/controller/UserController.java | 101 ++++++++++++ .../validation/ui/login/LoginStrategyImpl.java | 68 +++----- ui/src/main/webapp/WEB-INF/defs/definitions.xml | 3 + .../webapp/app/BluvalUI/CreateUser/CreateUser.html | 179 +++++++++++++++++++++ .../webapp/app/BluvalUI/CreateUser/CreateUser.js | 19 +++ .../BluvalUI/CreateUser/CreateUserController.js | 57 +++++++ .../BluvalUI/CreateUser/CreateUserTemplate.html | 53 ++++++ .../main/webapp/app/BluvalUI/CreateUser/Route.js | 22 +++ 18 files changed, 550 insertions(+), 87 deletions(-) create mode 100644 ui/src/main/java/org/akraino/validation/ui/controller/UserController.java create mode 100644 ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.html create mode 100644 ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.js create mode 100644 ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserController.js create mode 100644 ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserTemplate.html create mode 100644 ui/src/main/webapp/app/BluvalUI/CreateUser/Route.js diff --git a/.coafile b/.coafile index 39d09fa..3e655dd 100644 --- a/.coafile +++ b/.coafile @@ -95,4 +95,5 @@ ignore = ui/src/main/webapp/app/fusion/**, ui/src/main/webapp/app/BluvalUI/GetBlueprintInstances/GetBlueprintInstances.js, ui/src/main/webapp/app/BluvalUI/GetLabs/GetLabs.js, ui/src/main/webapp/app/BluvalUI/GetLayers/GetLayers.js, - ui/src/main/webapp/app/BluvalUI/GetTimeslots/GetTimeslots.js + ui/src/main/webapp/app/BluvalUI/GetTimeslots/GetTimeslots.js, + ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.js diff --git a/docker/README.rst b/docker/README.rst index a86db5d..17e84ba 100644 --- a/docker/README.rst +++ b/docker/README.rst @@ -101,14 +101,11 @@ In order for the container to be easily created, the deploy.sh script has been d CONTAINER_NAME, name of the container, default value is akraino-validation-mariadb MARIADB_ROOT_PASSWORD, the desired mariadb root user password, this variable is required MARIADB_AKRAINO_PASSWORD, the desired mariadb akraino user password, this variable is required -UI_ADMIN_PASSWORD, the desired Blueprint Validation UI password for the admin user, this variable is required -UI_AKRAINO_PASSWORD, the desired Blueprint Validation UI password for the akraino user, this variable is required REGISTRY, registry of the mariadb image, default value is akraino NAME, name of the mariadb image, default value is validation TAG_PRE, first part of the image version, default value is mariadb TAG_VER, last part of the image version, default value is latest MARIADB_HOST_PORT, port on which mariadb is exposed on host, default value is 3307 -ENCRYPTION_KEY, the key that should be used by the AES algorithm for encrypting passwords stored in database, this variable is required In order to deploy the container, this script can be executed with the appropriate parameters. @@ -117,7 +114,7 @@ Example (assuming the default variables have been utilized for building the imag .. code-block:: console cd validation/docker/mariadb - ./deploy.sh MARIADB_ROOT_PASSWORD=root_password MARIADB_AKRAINO_PASSWORD=akraino_password UI_ADMIN_PASSWORD=admin UI_AKRAINO_PASSWORD=akraino ENCRYPTION_KEY=key + ./deploy.sh MARIADB_ROOT_PASSWORD=root_password MARIADB_AKRAINO_PASSWORD=akraino_password Also, in order to re-deploy the database (it is assumed that the corresponding mariadb container has been stopped and deleted) while the persistent storage already exists (currently, the directory /var/lib/mariadb of the host is used), a different approach should be used after the image build process. @@ -178,6 +175,8 @@ NEXUS_PROXY, the needed proxy in order for the Nexus server to be reachable, def JENKINS_PROXY, the needed proxy in order for the Jenkins server to be reachable, default value is none CERTDIR, the directory where the SSL certificates can be found, default value is the working directory where self signed certificates exist only for demo purposes ENCRYPTION_KEY, the key that should be used by the AES algorithm for encrypting passwords stored in database, this variable is required +UI_ADMIN_PASSWORD, the desired Blueprint Validation UI password for the admin user, this variable is required +UI_AKRAINO_PASSWORD, the desired Blueprint Validation UI password for the akraino user, this variable is required Note that, for a functional UI, the following prerequisites are needed: @@ -194,7 +193,7 @@ Example (assuming the default variables have been utilized for building the imag .. code-block:: console cd validation/docker/ui - ./deploy.sh DB_IP_PORT=172.17.0.3:3306 MARIADB_AKRAINO_PASSWORD=akraino_password ENCRYPTION_KEY=key + ./deploy.sh DB_IP_PORT=172.17.0.3:3306 MARIADB_AKRAINO_PASSWORD=akraino_password ENCRYPTION_KEY=AGADdG4D04BKm2IxIWEr8o== UI_ADMIN_PASSWORD=admin UI_AKRAINO_PASSWORD=akraino The kube-conformance container ============================== diff --git a/docker/mariadb/deploy.sh b/docker/mariadb/deploy.sh index b3fea76..f727ed5 100755 --- a/docker/mariadb/deploy.sh +++ b/docker/mariadb/deploy.sh @@ -24,9 +24,6 @@ CONTAINER_NAME="akraino-validation-mariadb" # Container input variables MARIADB_ROOT_PASSWORD="" MARIADB_AKRAINO_PASSWORD="" -UI_ADMIN_PASSWORD="" -UI_AKRAINO_PASSWORD="" -ENCRYPTION_KEY="" # Image data REGISTRY=akraino NAME=validation @@ -47,9 +44,6 @@ do MARIADB_AKRAINO_PASSWORD) MARIADB_AKRAINO_PASSWORD=${VALUE} ;; CONTAINER_NAME) CONTAINER_NAME=${VALUE} ;; MARIADB_HOST_PORT) MARIADB_HOST_PORT=${VALUE} ;; - UI_ADMIN_PASSWORD) UI_ADMIN_PASSWORD=${VALUE} ;; - UI_AKRAINO_PASSWORD) UI_AKRAINO_PASSWORD=${VALUE} ;; - ENCRYPTION_KEY) ENCRYPTION_KEY=${VALUE} ;; *) esac done @@ -66,26 +60,7 @@ if [ -z "$MARIADB_AKRAINO_PASSWORD" ] exit 1 fi -if [ -z "$UI_ADMIN_PASSWORD" ] - then - echo "ERROR: You must specify the password of the UI admin user" - exit 1 -fi - -if [ -z "$UI_AKRAINO_PASSWORD" ] - then - echo "ERROR: You must specify the password for the UI akraino user" - exit 1 -fi - -if [ -z "$ENCRYPTION_KEY" ] - then - echo "ERROR: You must specify the encryption key" - exit 1 -fi - IMAGE="$REGISTRY"/"$NAME":"$TAG_PRE"-"$TAG_VER" chmod 0444 "/$(pwd)/mariadb.conf" -docker run --detach --name $CONTAINER_NAME --publish $MARIADB_HOST_PORT:3306 -v $DOCKER_VOLUME_NAME:/var/lib/mysql -v "/$(pwd)/mariadb.conf:/etc/mysql/conf.d/my.cnf" -e MYSQL_ROOT_PASSWORD="$MARIADB_ROOT_PASSWORD" -e MYSQL_DATABASE="akraino" -e MYSQL_USER="akraino" -e MYSQL_PASSWORD="$MARIADB_AKRAINO_PASSWORD" -e UI_ADMIN_PASSWORD="$UI_ADMIN_PASSWORD" -e UI_AKRAINO_PASSWORD="$UI_AKRAINO_PASSWORD" -e ENCRYPTION_KEY="$ENCRYPTION_KEY" $IMAGE -docker exec $CONTAINER_NAME /bin/bash -c 'sed -i 's/admin_password/'"$UI_ADMIN_PASSWORD"'/g' /docker-entrypoint-initdb.d/EcompSdkDMLMySql_2_4_OS.sql ; sed -i 's/akraino_password/'"$UI_AKRAINO_PASSWORD"'/g' /docker-entrypoint-initdb.d/EcompSdkDMLMySql_2_4_OS.sql; echo "UPDATE fn_user SET LOGIN_PWD = HEX(AES_ENCRYPT(LOGIN_PWD, \"$ENCRYPTION_KEY\"))" >> /docker-entrypoint-initdb.d/EcompSdkDMLMySql_2_4_OS.sql ;continue=`ps aux | grep mysql` ; while [ -z "$continue" ]; do continue=`ps aux | grep mysql`; sleep 5; done ; sleep 10 ;' +docker run --detach --name $CONTAINER_NAME --publish $MARIADB_HOST_PORT:3306 -v $DOCKER_VOLUME_NAME:/var/lib/mysql -v "/$(pwd)/mariadb.conf:/etc/mysql/conf.d/my.cnf" -e MYSQL_ROOT_PASSWORD="$MARIADB_ROOT_PASSWORD" -e MYSQL_DATABASE="akraino" -e MYSQL_USER="akraino" -e MYSQL_PASSWORD="$MARIADB_AKRAINO_PASSWORD" $IMAGE sleep 10 diff --git a/docker/ui/deploy.sh b/docker/ui/deploy.sh index 43bd5bc..2ff6587 100755 --- a/docker/ui/deploy.sh +++ b/docker/ui/deploy.sh @@ -34,6 +34,8 @@ NEXUS_PROXY="" JENKINS_PROXY="" CERTDIR=$(pwd) ENCRYPTION_KEY="" +UI_ADMIN_PASSWORD="" +UI_AKRAINO_PASSWORD="" for ARGUMENT in "$@" do @@ -55,6 +57,8 @@ do JENKINS_PROXY) JENKINS_PROXY=${VALUE} ;; CERTDIR) CERTDIR=${VALUE} ;; ENCRYPTION_KEY) ENCRYPTION_KEY=${VALUE} ;; + UI_ADMIN_PASSWORD) UI_ADMIN_PASSWORD=${VALUE} ;; + UI_AKRAINO_PASSWORD) UI_AKRAINO_PASSWORD=${VALUE} ;; *) esac done @@ -77,6 +81,18 @@ if [ -z "$ENCRYPTION_KEY" ] exit 1 fi +if [ -z "$UI_ADMIN_PASSWORD" ] + then + echo "ERROR: You must specify the UI admin password" + exit 1 +fi + +if [ -z "$UI_AKRAINO_PASSWORD" ] + then + echo "ERROR: You must specify the UI akraino password" + exit 1 +fi + IMAGE="$REGISTRY"/"$NAME":"$TAG_PRE"-"$TAG_VER" -docker run --detach --name $CONTAINER_NAME --network="host" -v "$(pwd)/server.xml:/usr/local/tomcat/conf/server.xml" -v "$CERTDIR/bluval.key:/usr/local/tomcat/bluval.key" -v "$CERTDIR/bluval.crt:/usr/local/tomcat/bluval.crt" -v "$(pwd)/root_index.jsp:/usr/local/tomcat/webapps/ROOT/index.jsp" -e DB_IP_PORT="$DB_IP_PORT" -e MARIADB_AKRAINO_PASSWORD="$MARIADB_AKRAINO_PASSWORD" -e JENKINS_URL="$JENKINS_URL" -e JENKINS_USERNAME="$JENKINS_USERNAME" -e JENKINS_USER_PASSWORD="$JENKINS_USER_PASSWORD" -e JENKINS_JOB_NAME="$JENKINS_JOB_NAME" -e NEXUS_PROXY="$NEXUS_PROXY" -e JENKINS_PROXY="$JENKINS_PROXY" -e ENCRYPTION_KEY="$ENCRYPTION_KEY" $IMAGE +docker run --detach --name $CONTAINER_NAME --network="host" -v "$(pwd)/server.xml:/usr/local/tomcat/conf/server.xml" -v "$CERTDIR/bluval.key:/usr/local/tomcat/bluval.key" -v "$CERTDIR/bluval.crt:/usr/local/tomcat/bluval.crt" -v "$(pwd)/root_index.jsp:/usr/local/tomcat/webapps/ROOT/index.jsp" -e DB_IP_PORT="$DB_IP_PORT" -e MARIADB_AKRAINO_PASSWORD="$MARIADB_AKRAINO_PASSWORD" -e JENKINS_URL="$JENKINS_URL" -e JENKINS_USERNAME="$JENKINS_USERNAME" -e JENKINS_USER_PASSWORD="$JENKINS_USER_PASSWORD" -e JENKINS_JOB_NAME="$JENKINS_JOB_NAME" -e NEXUS_PROXY="$NEXUS_PROXY" -e JENKINS_PROXY="$JENKINS_PROXY" -e ENCRYPTION_KEY="$ENCRYPTION_KEY" -e UI_ADMIN_PASSWORD="$UI_ADMIN_PASSWORD" -e UI_AKRAINO_PASSWORD="$UI_AKRAINO_PASSWORD" $IMAGE sleep 10 diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index de1afb2..403c958 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -198,3 +198,12 @@ All notable changes to this project will be documented in this file. ### Changed ### Removed + +## [0.4.0-SNAPSHOT] - 26 September 2019 +### Added +- User creation +- Support of AES PKCS#5 for encrypting/decrypting passwords in database + +### Changed + +### Removed diff --git a/ui/README.rst b/ui/README.rst index 33ecb23..26d5f68 100644 --- a/ui/README.rst +++ b/ui/README.rst @@ -170,16 +170,13 @@ Also, a script has been developed, namely validation/docker/mariadb/deploy.sh wh CONTAINER_NAME, name of the container, default value is akraino-validation-mariadb MARIADB_ROOT_PASSWORD, the desired mariadb root user password, this variable is required MARIADB_AKRAINO_PASSWORD, the desired mariadb akraino user password, this variable is required -UI_ADMIN_PASSWORD, the desired Blueprint Validation UI password for the admin user, this variable is required -UI_AKRAINO_PASSWORD, the desired Blueprint Validation UI password for the akraino user, this variable is required REGISTRY, registry of the mariadb image, default value is akraino NAME, name of the mariadb image, default value is validation TAG_PRE, first part of the image version, default value is mariadb TAG_VER, last part of the image version, default value is latest MARIADB_HOST_PORT, port on which mariadb is exposed on host, default value is 3307 -ENCRYPTION_KEY, the key that should be used by the AES algorithm for encrypting passwords stored in database, this variable is required -Currently, two users are supported by the UI, namely admin (full privileges) and akraino (limited privileges). Their passwords must be defined in the database. +Currently, two users are supported by the UI, namely admin (full privileges) and akraino (limited privileges). Their passwords are changed and stored at UI deployment (refer to UI deployment section). In order to build and deploy the image using only the required parameters, the below instructions should be followed: @@ -190,7 +187,7 @@ The mariadb root password, mariadb akraino user password (currently the UI conne cd validation/ui mvn docker:build -Ddocker.filter=akraino/validation:dev-mariadb-latest cd ../docker/mariadb - ./deploy.sh TAG_PRE=dev-mariadb MARIADB_ROOT_PASSWORD= MARIADB_AKRAINO_PASSWORD= UI_ADMIN_PASSWORD= UI_AKRAINO_PASSWORD= ENCRYPTION_KEY= + ./deploy.sh TAG_PRE=dev-mariadb MARIADB_ROOT_PASSWORD= MARIADB_AKRAINO_PASSWORD= mysql -p -uakraino -h < ../../ui/db-scripts/examples/initialize_db_example.sql In order to retrieve the IP of the mariadb container, the following command should be executed: @@ -229,7 +226,7 @@ To this end, after the image build process, the following commands should be exe docker volume rm akraino-validation-mariadb cd validation/docker/mariadb - ./deploy.sh TAG_PRE=dev-mariadb MARIADB_ROOT_PASSWORD= MARIADB_AKRAINO_PASSWORD= UI_ADMIN_PASSWORD= UI_AKRAINO_PASSWORD= + ./deploy.sh TAG_PRE=dev-mariadb MARIADB_ROOT_PASSWORD= MARIADB_AKRAINO_PASSWORD= mysql -p -uakraino -h < ../../ui/db-scripts/examples/initialize_db_example.sql In the context of the UI application, the following tables exist in the database: @@ -411,6 +408,8 @@ NEXUS_PROXY, the needed proxy in order for the Nexus server to be reachable, def JENKINS_PROXY, the needed proxy in order for the Jenkins server to be reachable, default value is none CERTDIR, the directory where the SSL certificates can be found, default value is the working directory where self signed certificates exist only for demo purposes ENCRYPTION_KEY, the key that should be used by the AES algorithm for encrypting passwords stored in database, this variable is required +UI_ADMIN_PASSWORD, the desired Blueprint Validation UI password for the admin user, this variable is required +UI_AKRAINO_PASSWORD, the desired Blueprint Validation UI password for the akraino user, this variable is required So, for a functional UI, the following prerequisites are needed: @@ -422,14 +421,16 @@ Then, the following commands can be executed in order to deploy the UI container .. code-block:: console cd ../docker/ui - ./deploy.sh TAG_PRE=dev-ui DB_IP_PORT= MARIADB_AKRAINO_PASSWORD= ENCRYPTION_KEY= + ./deploy.sh TAG_PRE=dev-ui DB_IP_PORT= MARIADB_AKRAINO_PASSWORD= ENCRYPTION_KEY= UI_ADMIN_PASSWORD= UI_AKRAINO_PASSWORD= -The content of the DB_IP_PORT can be for example '172.17.0.3:3306'. Also, the value of the encryption key should be the same as the value of the encryption key used in database deployment. +The content of the DB_IP_PORT can be for example '172.17.0.3:3306'. Also, the value of the encryption key can be for example 'AGADdG4D04BKm2IxIWEr8o=='. Furthermore, the TAG_PRE variable should be defined as the default value is 'ui' (note that the 'dev-ui' is used for development purposes - look at pom.xml file). If no proxy exists, the proxy ip and port variables should not be defined. +More users can be created using the 'Create User' tab of the UI. This tab is available only for the admin user. + The UI should be available in the following url: https://:8443/bluvalui/ diff --git a/ui/db-scripts/EcompSdkDMLMySql_2_4_OS.sql b/ui/db-scripts/EcompSdkDMLMySql_2_4_OS.sql index a1b3767..0497529 100644 --- a/ui/db-scripts/EcompSdkDMLMySql_2_4_OS.sql +++ b/ui/db-scripts/EcompSdkDMLMySql_2_4_OS.sql @@ -53,10 +53,11 @@ Insert into fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, Insert into fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (45, 'Layers', 42, 10, 'getlayers', 'menu_tab', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/reports.png'); Insert into fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (46, 'Timeslots', 42, 10, 'gettimeslots', 'menu_tab', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/reports.png'); Insert into fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (47, 'Blueprint Instances', 42, 10, 'getblueprintinstances', 'menu_tab', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/reports.png'); +Insert into fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (48, 'Create User', 1, 10, 'createuser', 'menu_sample', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'icon-building-home'); -- fn_user -Insert into fn_user (USER_ID,ORG_ID,MANAGER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,PHONE,FAX,CELLULAR,EMAIL,ADDRESS_ID,ALERT_METHOD_CD,HRID,ORG_USER_ID,ORG_CODE,LOGIN_ID,LOGIN_PWD,LAST_LOGIN_DATE,ACTIVE_YN,CREATED_ID,CREATED_DATE,MODIFIED_ID,MODIFIED_DATE,IS_INTERNAL_YN,ADDRESS_LINE_1,ADDRESS_LINE_2,CITY,STATE_CD,ZIP_CODE,COUNTRY_CD,LOCATION_CLLI,ORG_MANAGER_USERID,COMPANY,DEPARTMENT_NAME,JOB_TITLE,TIMEZONE,DEPARTMENT,BUSINESS_UNIT,BUSINESS_UNIT_NAME,COST_CENTER,FIN_LOC_CODE,SILO_STATUS) values (1,null,null,'admin',null,'User',null,null,null,'admin@email.com',null,null,null,'admin',null,'admin','admin_password',str_to_date('24-OCT-16','%d-%M-%Y'),'Y',null,str_to_date('17-OCT-16','%d-%M-%Y'),1,str_to_date('24-OCT-16','%d-%M-%Y'),'N',null,null,null,'NJ',null,'US',null,null,null,null,null,10,null,null,null,null,null,null); -Insert into fn_user (USER_ID,ORG_ID,MANAGER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,PHONE,FAX,CELLULAR,EMAIL,ADDRESS_ID,ALERT_METHOD_CD,HRID,ORG_USER_ID,ORG_CODE,LOGIN_ID,LOGIN_PWD,LAST_LOGIN_DATE,ACTIVE_YN,CREATED_ID,CREATED_DATE,MODIFIED_ID,MODIFIED_DATE,IS_INTERNAL_YN,ADDRESS_LINE_1,ADDRESS_LINE_2,CITY,STATE_CD,ZIP_CODE,COUNTRY_CD,LOCATION_CLLI,ORG_MANAGER_USERID,COMPANY,DEPARTMENT_NAME,JOB_TITLE,TIMEZONE,DEPARTMENT,BUSINESS_UNIT,BUSINESS_UNIT_NAME,COST_CENTER,FIN_LOC_CODE,SILO_STATUS) values (2,null,null,'akraino',null,'User',null,null,null,'akraino@email.com',null,null,null,'akraino',null,'akraino','akraino_password',str_to_date('24-OCT-16','%d-%M-%Y'),'Y',null,str_to_date('17-OCT-16','%d-%M-%Y'),1,str_to_date('24-OCT-16','%d-%M-%Y'),'N',null,null,null,'NJ',null,'US',null,null,null,null,null,10,null,null,null,null,null,null); +Insert into fn_user (USER_ID,ORG_ID,MANAGER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,PHONE,FAX,CELLULAR,EMAIL,ADDRESS_ID,ALERT_METHOD_CD,HRID,ORG_USER_ID,ORG_CODE,LOGIN_ID,LOGIN_PWD,LAST_LOGIN_DATE,ACTIVE_YN,CREATED_ID,CREATED_DATE,MODIFIED_ID,MODIFIED_DATE,IS_INTERNAL_YN,ADDRESS_LINE_1,ADDRESS_LINE_2,CITY,STATE_CD,ZIP_CODE,COUNTRY_CD,LOCATION_CLLI,ORG_MANAGER_USERID,COMPANY,DEPARTMENT_NAME,JOB_TITLE,TIMEZONE,DEPARTMENT,BUSINESS_UNIT,BUSINESS_UNIT_NAME,COST_CENTER,FIN_LOC_CODE,SILO_STATUS) values (1,null,null,'admin',null,null,null,null,null,null,null,null,null,'admin',null,'admin','admin_password',null,'Y',null,NOW(),1,NOW(),'N',null,null,null,null,null,null,null,null,null,null,null,10,null,null,null,null,null,null); +Insert into fn_user (USER_ID,ORG_ID,MANAGER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,PHONE,FAX,CELLULAR,EMAIL,ADDRESS_ID,ALERT_METHOD_CD,HRID,ORG_USER_ID,ORG_CODE,LOGIN_ID,LOGIN_PWD,LAST_LOGIN_DATE,ACTIVE_YN,CREATED_ID,CREATED_DATE,MODIFIED_ID,MODIFIED_DATE,IS_INTERNAL_YN,ADDRESS_LINE_1,ADDRESS_LINE_2,CITY,STATE_CD,ZIP_CODE,COUNTRY_CD,LOCATION_CLLI,ORG_MANAGER_USERID,COMPANY,DEPARTMENT_NAME,JOB_TITLE,TIMEZONE,DEPARTMENT,BUSINESS_UNIT,BUSINESS_UNIT_NAME,COST_CENTER,FIN_LOC_CODE,SILO_STATUS) values (2,null,null,'akraino',null,null,null,null,null,null,null,null,null,'akraino',null,'akraino','akraino_password',null,'Y',null,NOW(),1,NOW(),'N',null,null,null,null,null,null,null,null,null,null,null,10,null,null,null,null,null,null); -- fn_app Insert into fn_app (APP_ID,APP_NAME,APP_IMAGE_URL,APP_DESCRIPTION,APP_NOTES,APP_URL,APP_ALTERNATE_URL,APP_REST_ENDPOINT,ML_APP_NAME,ML_APP_ADMIN_ID,MOTS_ID,APP_PASSWORD,OPEN,ENABLED,THUMBNAIL,APP_USERNAME,UEB_KEY,UEB_SECRET,UEB_TOPIC_NAME) VALUES (1,'Default',null,'Some Default Description','Some Default Note',null,null,null,'ECPP','?','1','JuCerIRKt/faEcx8QdgncLEEv+IOZjpHe7Pi5DEPqKs=','N','N',null,'Default',null,null,'ECOMP-PORTAL-INBOX'); diff --git a/ui/pom.xml b/ui/pom.xml index 870b3a1..285884e 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -14,7 +14,7 @@ org.akraino.validation ui - 0.3.4-SNAPSHOT + 0.4.0-SNAPSHOT Bluval UI Maven Webapp war @@ -373,5 +373,6 @@ commons-httpclient ${commons-httpclient.version} + diff --git a/ui/src/main/java/org/akraino/validation/ui/conf/UiInitializer.java b/ui/src/main/java/org/akraino/validation/ui/conf/UiInitializer.java index febafe1..e93c25b 100644 --- a/ui/src/main/java/org/akraino/validation/ui/conf/UiInitializer.java +++ b/ui/src/main/java/org/akraino/validation/ui/conf/UiInitializer.java @@ -15,9 +15,11 @@ */ package org.akraino.validation.ui.conf; +import java.io.IOException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; +import java.util.List; import java.util.Map; import javax.net.ssl.HostnameVerifier; @@ -27,6 +29,11 @@ import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.onboarding.exception.CipherUtilException; +import org.onap.portalsdk.core.onboarding.util.CipherUtil; +import org.onap.portalsdk.core.service.UserProfileService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @@ -37,6 +44,9 @@ import com.sun.jersey.client.urlconnection.HTTPSProperties; @Component public class UiInitializer { + @Autowired + UserProfileService userService; + // Create all-trusting host name verifier private final HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override @@ -75,4 +85,32 @@ public class UiInitializer { properties.put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, httpsProperties); } + @EventListener(ContextRefreshedEvent.class) + public void updateUsers() throws RuntimeException, IOException, CipherUtilException { + User admin = null; + List users = userService.findAllActive(); + for (User user : users) { + if (user.getLoginId().equals("admin")) { + admin = user; + } + } + if (admin == null) { + throw new RuntimeException("Admin user does not exist"); + } + admin.setLoginPwd(CipherUtil.encryptPKC(System.getenv("UI_ADMIN_PASSWORD"), System.getenv("ENCRYPTION_KEY"))); + userService.saveUser(admin); + User akraino = null; + for (User user : users) { + if (user.getLoginId().equals("akraino")) { + akraino = user; + } + } + if (akraino == null) { + throw new RuntimeException("Akraino user does not exist"); + } + akraino.setLoginPwd( + CipherUtil.encryptPKC(System.getenv("UI_AKRAINO_PASSWORD"), System.getenv("ENCRYPTION_KEY"))); + userService.saveUser(akraino); + } + } diff --git a/ui/src/main/java/org/akraino/validation/ui/controller/ModelsViewsController.java b/ui/src/main/java/org/akraino/validation/ui/controller/ModelsViewsController.java index 3d75a4a..2ae1c4f 100644 --- a/ui/src/main/java/org/akraino/validation/ui/controller/ModelsViewsController.java +++ b/ui/src/main/java/org/akraino/validation/ui/controller/ModelsViewsController.java @@ -173,6 +173,12 @@ public class ModelsViewsController extends RestrictedBaseController { return new ModelAndView(defaultViewName); } + @RequestMapping(value = { "/createuser" }, method = RequestMethod.GET) + public ModelAndView createUser(HttpServletRequest request) { + final String defaultViewName = null; + return new ModelAndView(defaultViewName); + } + @RequestMapping(value = { "/logout.htm" }, method = RequestMethod.GET) public ModelAndView login() { Map model = new HashMap<>(); diff --git a/ui/src/main/java/org/akraino/validation/ui/controller/UserController.java b/ui/src/main/java/org/akraino/validation/ui/controller/UserController.java new file mode 100644 index 0000000..552ae94 --- /dev/null +++ b/ui/src/main/java/org/akraino/validation/ui/controller/UserController.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.akraino.validation.ui.controller; + +import java.io.IOException; +import java.util.Date; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.onap.portalsdk.core.controller.RestrictedBaseController; +import org.onap.portalsdk.core.domain.Role; +import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.onboarding.exception.CipherUtilException; +import org.onap.portalsdk.core.onboarding.util.CipherUtil; +import org.onap.portalsdk.core.service.RoleService; +import org.onap.portalsdk.core.service.UserProfileService; +import org.onap.portalsdk.core.web.support.UserUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +@RequestMapping("/api/v1/user") +public class UserController extends RestrictedBaseController { + + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(UserController.class); + + @Autowired + UserProfileService userService; + + @Autowired + RoleService roleService; + + public UserController() { + super(); + } + + @RequestMapping(value = { "/" }, method = RequestMethod.POST) + public ResponseEntity createUser(@RequestBody User user) { + try { + return new ResponseEntity<>(createUser(user.getFirstName(), user.getLoginId(), user.getLoginPwd()), + HttpStatus.OK); + } catch (Exception e) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "Creation of user failed. " + UserUtils.getStackTrace(e)); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + private User createUser(String firstName, String loginId, String loginPwd) throws IOException, CipherUtilException { + User newUser = new User(); + newUser.setActive(true); + newUser.setCreated(new Date()); + newUser.setFirstName(firstName); + newUser.setInternal(false); + newUser.setLoginId(loginId); + newUser.setOrgUserId(loginId); + newUser.setLoginPwd(CipherUtil.encryptPKC(loginPwd, System.getenv("ENCRYPTION_KEY"))); + newUser.setModified(new Date()); + newUser.setModifiedId(1L); + newUser.setOnline(true); + newUser.setTimeZoneId(10L); + userService.saveUser(newUser); + Role actualRole = null; + List roles = roleService.getActiveRoles(null); + for (Role role : roles) { + if (role.getName().equals("Blueprint Validation UI user")) { + actualRole = role; + break; + } + } + if (actualRole == null) { + throw new RuntimeException("Blueprint Validation UI user role does not exist"); + } + SortedSet actualRoles = new TreeSet(); + actualRoles.add(actualRole); + newUser.setRoles(actualRoles); + userService.saveUser(newUser); + return newUser; + } + +} diff --git a/ui/src/main/java/org/akraino/validation/ui/login/LoginStrategyImpl.java b/ui/src/main/java/org/akraino/validation/ui/login/LoginStrategyImpl.java index b6a78fc..ea14483 100644 --- a/ui/src/main/java/org/akraino/validation/ui/login/LoginStrategyImpl.java +++ b/ui/src/main/java/org/akraino/validation/ui/login/LoginStrategyImpl.java @@ -17,25 +17,14 @@ package org.akraino.validation.ui.login; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.codec.binary.Hex; import org.onap.portalsdk.core.auth.LoginStrategy; import org.onap.portalsdk.core.command.LoginBean; import org.onap.portalsdk.core.domain.RoleFunction; @@ -76,16 +65,14 @@ public class LoginStrategyImpl extends LoginStrategy { LoginBean commandBean = new LoginBean(); String loginId = request.getParameter("loginId"); String password = request.getParameter("password"); - String key = System.getenv("ENCRYPTION_KEY"); - password = aesEncrypt(password, key); commandBean.setLoginId(loginId); commandBean.setLoginPwd(password); - // commandBean.setUserid(loginId); + commandBean.setUserid(loginId); commandBean = loginService.findUser(commandBean, (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap()); List roleFunctionList = roleService.getRoleFunctions(loginId); - - if (commandBean.getUser() == null) { + if (commandBean.getUser() == null || !CipherUtil + .decryptPKC(commandBean.getUser().getLoginPwd(), System.getenv("ENCRYPTION_KEY")).equals(password)) { String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage() : "login.error.external.invalid"; Map model = new HashMap<>(); @@ -110,22 +97,34 @@ public class LoginStrategyImpl extends LoginStrategy { LoginBean commandBean = new LoginBean(); String loginId = request.getParameter("loginId"); String password = request.getParameter("password"); - String key = System.getenv("ENCRYPTION_KEY"); - password = aesEncrypt(password, key); commandBean.setLoginId(loginId); commandBean.setLoginPwd(password); - // commandBean.setUserid(loginId); + commandBean.setUserid(loginId); commandBean = loginService.findUser(commandBean, (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap()); List roleFunctionList = roleService.getRoleFunctions(loginId); - if (commandBean.getUser() == null) { - String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage() - : "login.error.external.invalid"; - Map model = new HashMap<>(); - model.put("error", loginErrorMessage); - return new ModelAndView("login_external", "model", model); - } else { + try { + if (commandBean.getUser() == null + || !CipherUtil.decryptPKC(commandBean.getUser().getLoginPwd(), System.getenv("ENCRYPTION_KEY")) + .equals(password)) { + String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) + ? commandBean.getLoginErrorMessage() + : "login.error.external.invalid"; + Map model = new HashMap<>(); + model.put("error", loginErrorMessage); + return new ModelAndView("login_external", "model", model); + } else { + // store the currently logged in user's information in the session + UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(), + commandBean.getBusinessDirectMenu(), + SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_BACKDOOR), roleFunctionList); + initateSessionMgtHandler(request); + // user has been authenticated, now take them to the welcome page + return new ModelAndView("redirect:welcome"); + } + } catch (CipherUtilException e) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "Error in Cipher." + UserUtils.getStackTrace(e)); // store the currently logged in user's information in the session UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(), commandBean.getBusinessDirectMenu(), @@ -192,21 +191,4 @@ public class LoginStrategyImpl extends LoginStrategy { return null; } - private String aesEncrypt(String password, String strKey) { - try { - byte[] keyBytes = Arrays.copyOf(strKey.getBytes("ASCII"), 16); - SecretKey key = new SecretKeySpec(keyBytes, "AES"); - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.ENCRYPT_MODE, key); - byte[] cleartext = password.getBytes("UTF-8"); - byte[] ciphertextBytes = cipher.doFinal(cleartext); - return new String(Hex.encodeHex(ciphertextBytes)); - } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | UnsupportedEncodingException - | IllegalBlockSizeException | BadPaddingException e) { - LOGGER.error(EELFLoggerDelegate.errorLogger, - "Error when encrypting password key" + UserUtils.getStackTrace(e)); - return null; - } - } - } diff --git a/ui/src/main/webapp/WEB-INF/defs/definitions.xml b/ui/src/main/webapp/WEB-INF/defs/definitions.xml index c8cca69..dd5296e 100644 --- a/ui/src/main/webapp/WEB-INF/defs/definitions.xml +++ b/ui/src/main/webapp/WEB-INF/defs/definitions.xml @@ -86,4 +86,7 @@ + + diff --git a/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.html b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.html new file mode 100644 index 0000000..c6c2d13 --- /dev/null +++ b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.html @@ -0,0 +1,179 @@ + + + + + + + + + + +Create User + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + \ No newline at end of file diff --git a/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.js b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.js new file mode 100644 index 0000000..814a10f --- /dev/null +++ b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUser.js @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var appDS2 = angular.module("CreateUser", [ 'ngRoute', 'ngMessages', + 'modalServices', 'ngCookies', 'b2b.att', 'gridster', 'ui.bootstrap', + 'ui.bootstrap.modal', 'App.Services' ]); \ No newline at end of file diff --git a/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserController.js b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserController.js new file mode 100644 index 0000000..91a4b50 --- /dev/null +++ b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserController.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var app = angular.module('CreateUser'); +app + .controller( + 'CreateUserController', + function($scope, restAPISvc) { + + initialize(); + + function initialize() { + $scope.definedLoginId = ''; + $scope.definedFirstName = ''; + $scope.definedLoginPwd = ''; + } + + $scope.register = function() { + if (!$scope.definedLoginId || !$scope.definedFirstName + || !$scope.definedLoginPwd) { + confirm("You must specify all data fields"); + return; + } + var userInfo = { + "loginId" : $scope.definedLoginId, + "loginPwd" : $scope.definedLoginPwd, + "firstName" : $scope.definedFirstName + }; + restAPISvc + .postRestAPI( + "/api/v1/user/", + userInfo, + function(data) { + if (data) { + var confirmText = "The user has been registered successfully. User id:" + + data.id; + confirm(confirmText); + } else { + confirm("Error when registering the user"); + } + initialize(); + }); + } + }); diff --git a/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserTemplate.html b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserTemplate.html new file mode 100644 index 0000000..e601725 --- /dev/null +++ b/ui/src/main/webapp/app/BluvalUI/CreateUser/CreateUserTemplate.html @@ -0,0 +1,53 @@ + + +
+
+

Create User

+ +
+
+ +
+
+
+ +
+
+ + +
+
+
+ +
+
+ +
+
+
+ +
+ +
+
+
diff --git a/ui/src/main/webapp/app/BluvalUI/CreateUser/Route.js b/ui/src/main/webapp/app/BluvalUI/CreateUser/Route.js new file mode 100644 index 0000000..c50b31f --- /dev/null +++ b/ui/src/main/webapp/app/BluvalUI/CreateUser/Route.js @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +appDS2.config(function($routeProvider) { + $routeProvider.otherwise({ + templateUrl : 'app/BluvalUI/CreateUser/CreateUserTemplate.html', + controller : "CreateUserController" + }); +}); \ No newline at end of file -- 2.16.6