New Auth Service in Mod2 72/112172/8
authorMantena, Ravi (rx908f) <rx908f@att.com>
Thu, 3 Sep 2020 21:14:41 +0000 (17:14 -0400)
committerRavi Mantena <rx908f@att.com>
Tue, 22 Sep 2020 16:54:22 +0000 (12:54 -0400)
Issue-ID: DCAEGEN2-2317
Change-Id: I34b08d7731cc23028f469376ef2147bb28a28b7f
Signed-off-by: Ravi Mantena <rx908f@att.com>
41 files changed:
mod2/auth-service/Dockerfile [new file with mode: 0644]
mod2/auth-service/pom.xml [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java [new file with mode: 0644]
mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java [new file with mode: 0644]
mod2/auth-service/src/main/resources/application.properties [new file with mode: 0644]
mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/AuthObjectMother.java [new file with mode: 0644]
mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/RoleObjectMother.java [new file with mode: 0644]
mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/UserObjectMother.java [new file with mode: 0644]
mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/util/TestUtil.java [new file with mode: 0644]
mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/AuthControllerTest.java [new file with mode: 0644]
mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/RoleControllerTest.java [new file with mode: 0644]
mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/UserControllerTest.java [new file with mode: 0644]
mod2/auth-service/src/test/resources/application.properties [new file with mode: 0644]
mod2/auth-service/src/test/resources/http/requests/AuthLoginRequest.json [new file with mode: 0644]
mod2/auth-service/src/test/resources/http/requests/AuthSignupRequest.json [new file with mode: 0644]
mod2/auth-service/src/test/resources/specification/componentSpec_hello_world-with-dmaap.json [new file with mode: 0644]
mod2/auth-service/src/test/resources/specification/policy_json_sample_3.json [new file with mode: 0644]

diff --git a/mod2/auth-service/Dockerfile b/mod2/auth-service/Dockerfile
new file mode 100644 (file)
index 0000000..c427bda
--- /dev/null
@@ -0,0 +1,11 @@
+FROM onap/integration-java11:7.1.0
+WORKDIR /usr/app
+VOLUME /tmp
+
+ADD target/auth-service-1.0.0-SNAPSHOT.jar auth-service-1.0.0-SNAPSHOT.jar
+
+EXPOSE 8082
+
+ENTRYPOINT ["java", \
+            "-Djava.security.egd=file:/dev/./urandom", \
+            "-jar", "auth-service-1.0.0-SNAPSHOT.jar"]
\ No newline at end of file
diff --git a/mod2/auth-service/pom.xml b/mod2/auth-service/pom.xml
new file mode 100644 (file)
index 0000000..1fd4f02
--- /dev/null
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ /*
+  ~  * ============LICENSE_START=======================================================
+  ~  *  org.onap.dcae
+  ~  *  ================================================================================
+  ~  *  Copyright (c) 2020 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.
+  ~  *  ============LICENSE_END=========================================================
+  ~  */
+  -->
+
+<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.onap.oparent</groupId>
+               <artifactId>oparent</artifactId>
+               <version>2.0.0</version>
+       </parent>
+       <groupId>org.onap.dcaegen2.platform.mod</groupId>
+       <artifactId>auth-service</artifactId>
+       <version>1.0.0-SNAPSHOT</version>
+       <name>auth-service</name>
+       <description>REST APIs to serve Auth Service</description>
+
+       <properties>
+               <java.version>11</java.version>
+               <maven.compiler.source>${java.version}</maven.compiler.source>
+               <maven.compiler.target>${java.version}</maven.compiler.target>
+       </properties>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-data-mongodb</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.gson</groupId>
+                       <artifactId>gson</artifactId>
+                       <version>2.8.6</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-security</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>io.jsonwebtoken</groupId>
+                       <artifactId>jjwt</artifactId>
+                       <version>0.9.1</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-web</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-webflux</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-validation</artifactId>
+               </dependency>
+               <!-- CODE GENERATION -->
+               <dependency>
+                       <groupId>org.projectlombok</groupId>
+                       <artifactId>lombok</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.squareup.okhttp3</groupId>
+                       <artifactId>okhttp</artifactId>
+                       <version>4.0.1</version>
+               </dependency>
+
+               <!--TEST DEPENDENCIES-->
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-test</artifactId>
+                       <scope>test</scope>
+                       <exclusions>
+                               <exclusion>
+                                       <groupId>org.junit.vintage</groupId>
+                                       <artifactId>junit-vintage-engine</artifactId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.security</groupId>
+                       <artifactId>spring-security-test</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>com.squareup.okhttp3</groupId>
+                       <artifactId>mockwebserver</artifactId>
+                       <version>4.0.1</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.security</groupId>
+                       <artifactId>spring-security-test</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>io.projectreactor</groupId>
+                       <artifactId>reactor-test</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>javax.xml.bind</groupId>
+                       <artifactId>jaxb-api</artifactId>
+                       <version>2.3.1</version>
+               </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>RELEASE</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+       <dependencyManagement>
+               <dependencies>
+                       <dependency>
+                               <!-- Import dependency management from Spring Boot -->
+                               <groupId>org.springframework.boot</groupId>
+                               <artifactId>spring-boot-dependencies</artifactId>
+                               <version>2.2.5.RELEASE</version>
+                               <type>pom</type>
+                               <scope>import</scope>
+                       </dependency>
+               </dependencies>
+       </dependencyManagement>
+
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               <artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>2.2.5.RELEASE</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-surefire-plugin</artifactId>
+                               <version>2.22.2</version>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java
new file mode 100644 (file)
index 0000000..5b147bf
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Auth Service Application
+ */
+@SpringBootApplication
+public class AuthServiceApplication {
+
+       public static void main(String[] args) {
+               SpringApplication.run(AuthServiceApplication.class, args);
+       }
+
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java
new file mode 100644 (file)
index 0000000..959b450
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * To Initialize Roles and create Default Admin User
+ */
+@Component
+public class DataLoader implements ApplicationRunner {
+
+    @Autowired
+    private RoleRepository roleRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    PasswordEncoder passwordEncoder;
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        populateRoles();
+        populateAdminUser();
+    }
+
+    private void populateRoles() {
+        List<Role> roles = createRoles();
+        roles.forEach((role) -> {
+            boolean roleNotPresent = !roleRepository.findByName(role.getName()).isPresent();
+            if(roleNotPresent)
+                roleRepository.save(role);
+        });
+
+    }
+
+    private List<Role> createRoles() {
+        Role admin = new Role("ROLE_ADMIN");
+        Role user = new Role("ROLE_USER");
+        Role developer = new Role("ROLE_DEVELOPER");
+        return Arrays.asList(admin, user, developer);
+    }
+
+    private void populateAdminUser() {
+        boolean adminNotPresent = !userRepository.findByUsername("admin").isPresent();
+        if(adminNotPresent) {
+            ModUser admin = createAdmin();
+            userRepository.save(admin);
+        }
+    }
+
+    private ModUser createAdmin() {
+        ModUser admin = new ModUser();
+        admin.setUsername("admin");
+        admin.setFullName("Admin");
+        admin.setPassword(passwordEncoder.encode("admin@mod"));
+        HashSet<Role> roleAdmin = new HashSet<>();
+        roleAdmin.add(roleRepository.findByName("ROLE_ADMIN").get());
+        admin.setRoles(roleAdmin);
+        return admin;
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java
new file mode 100644 (file)
index 0000000..6612138
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.controllers;
+
+import org.onap.dcaegen2.platform.mod.exceptions.RoleNotExistsException;
+import org.onap.dcaegen2.platform.mod.exceptions.UserAlreadyExistsException;
+import org.onap.dcaegen2.platform.mod.models.LoginRequest;
+import org.onap.dcaegen2.platform.mod.models.JwtResponse;
+import org.onap.dcaegen2.platform.mod.models.SignupRequest;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.GenericResponse;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+
+import javax.validation.Valid;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Authentication Operations
+ */
+@RestController
+@RequestMapping("/api/auth")
+@CrossOrigin(origins = "*")
+public class AuthController {
+
+    @Autowired
+    AuthenticationManager authenticationManager;
+
+    @Autowired
+    UserRepository userRepository;
+
+    @Autowired
+    RoleRepository roleRepository;
+
+    @Autowired
+    PasswordEncoder passwordEncoder;
+
+    @Autowired
+    JwtUtils jwtUtils;
+
+    @PreAuthorize("isAuthenticated()")
+    @PostMapping("/validate-token")
+    public ResponseEntity<?> validateToken() {
+        return new ResponseEntity("true", HttpStatus.OK);
+    }
+
+    @PostMapping("/signin")
+    public ResponseEntity<?> authenticateUser(@RequestBody @Valid LoginRequest loginRequest) {
+        Authentication authentication = authenticateLoginRequest(loginRequest);
+        SecurityContextHolder.getContext().setAuthentication(authentication);
+        String jwt = jwtUtils.generateJwtToken(authentication);
+        return setUserContext(authentication, jwt);
+    }
+
+    private Authentication authenticateLoginRequest(@RequestBody @Valid LoginRequest loginRequest) {
+        return authenticationManager.authenticate(
+                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
+        );
+    }
+
+    private ResponseEntity<?> setUserContext(Authentication authentication, String jwt) {
+        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
+        List<String> roles = setRolesFromUserDetails(userDetails);
+        return buildUserContext(jwt, userDetails, roles);
+    }
+
+    private List<String> setRolesFromUserDetails(UserDetailsImpl userDetails) {
+        return userDetails.getAuthorities().stream()
+                .map(item -> ((GrantedAuthority) item).getAuthority())
+                .collect(Collectors.toList());
+    }
+
+    private ResponseEntity<JwtResponse> buildUserContext(String jwt, UserDetailsImpl userDetails, List<String> roles) {
+        return ResponseEntity.ok(JwtResponse.builder()
+                .id(userDetails.getId())
+                .roles(roles)
+                .username(userDetails.getUsername())
+                .token(jwt)
+                .fullName(userDetails.getFullName())
+                .build()
+        );
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/signup")
+    public ResponseEntity<?> registerUser(@RequestBody @Valid SignupRequest request) {
+        checkIfUserExists(request);
+        ModUser user = createNewUser(request);
+        userRepository.save(user);
+        return ResponseEntity.ok(new GenericResponse("User registered successfully!"));
+    }
+
+    private void checkIfUserExists(@RequestBody @Valid SignupRequest signUpRequest) {
+        if (userRepository.existsByUsername(signUpRequest.getUsername()))
+            throw new UserAlreadyExistsException("Username already exists!");
+    }
+
+    private ModUser createNewUser(@RequestBody @Valid SignupRequest request) {
+        ModUser user = new ModUser();
+        user.setUsername(request.getUsername());
+        user.setFullName(request.getFullName());
+        user.setPassword(getEncodedPassword(request));
+        Set<Role> roles = createRoles(request.getRoles());
+        user.setRoles(roles);
+        return user;
+    }
+
+    private String getEncodedPassword(@RequestBody @Valid SignupRequest request) {
+        return passwordEncoder.encode(request.getPassword());
+    }
+
+    public Set<Role> createRoles(Set<String> roleStrings) {
+        Set<Role> roles = new HashSet<>();
+        for (String roleStr : roleStrings) {
+            roles.add(getRole(roleStr));
+        }
+        return roles;
+    }
+
+    private Role getRole(String roleStr) {
+        return roleRepository.findByName(roleStr).orElseThrow(
+                () -> new RoleNotExistsException(String.format("Role %s does not exist", roleStr)));
+    }
+}
+
+
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java
new file mode 100644 (file)
index 0000000..e129cda
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.controllers;
+
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Role Operations
+ */
+@RestController
+@RequestMapping("/api/roles")
+@CrossOrigin(origins = "*")
+public class RoleController {
+
+    @Autowired
+    RoleRepository roleRepository;
+
+    @GetMapping
+    @ResponseStatus(HttpStatus.OK)
+    public List<String> getRoles(){
+        return roleRepository.findAll()
+                .stream()
+                .map(role -> role.getName())
+                .collect(Collectors.toList());
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java
new file mode 100644 (file)
index 0000000..90e7b62
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.controllers;
+
+import org.onap.dcaegen2.platform.mod.exceptions.UserNotFoundException;
+import org.onap.dcaegen2.platform.mod.models.GenericResponse;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.onap.dcaegen2.platform.mod.services.MODUserDetailService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+
+/**
+ * @author
+ * @date 09/08/2020
+ * User Operations
+ */
+@RestController
+@RequestMapping("/api/users")
+@CrossOrigin(origins = "*")
+public class UserController {
+
+    @Autowired
+    private MODUserDetailService modUserDetailService;
+
+    @Autowired
+    private UserDetailsServiceImpl userDetailsService;
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/getAll")
+    @ResponseStatus(HttpStatus.OK)
+    public List<ModUser> getAllUsers() {
+        return modUserDetailService.findAll();
+    }
+
+    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
+    @GetMapping("/{username}")
+    public UserDetails getUser(@PathVariable String username) {
+        return userDetailsService.loadUserByUsername(username);
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @PatchMapping("/admin/{username}")
+    public ModUser adminUpdateUserProfile(@PathVariable String username, @RequestBody @Valid UpdateUserRequest
+            userRequest, @RequestHeader (name="Authorization") String token) {
+        return userDetailsService.adminUpdateUser(username, userRequest, token);
+    }
+
+    @PreAuthorize("hasRole('USER') or hasRole('DEVELOPER')")
+    @PatchMapping("/user/{username}")
+    public ModUser userUpdateOwnProfile(@PathVariable String username, @RequestBody @Valid UpdateUserRequest
+            userRequest, @RequestHeader (name="Authorization") String token) {
+        return userDetailsService.userUpdateOwnProfile(username, userRequest, token);
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @DeleteMapping("/{username}")
+    public ResponseEntity<?> deleteUser(@PathVariable String username) {
+        modUserDetailService.deleteUserByUsername(username);
+        return ResponseEntity.ok(new GenericResponse("User " + username + " was removed"));
+    }
+
+    @ExceptionHandler
+    @ResponseStatus(HttpStatus.NOT_FOUND)
+    public void userNotFoundHandler(UserNotFoundException ex) {
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java
new file mode 100644 (file)
index 0000000..e029e69
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+import org.onap.dcaegen2.platform.mod.models.GenericResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception handler for the Auth Service Application
+ */
+@ControllerAdvice
+@Slf4j
+public class AppExceptionHandler {
+
+    @ExceptionHandler
+    public ResponseEntity<GenericResponse> resolveRuntimeException(UserAlreadyExistsException ex){
+        log.error(ex.getMessage());
+        return new ResponseEntity<>(new GenericResponse(ex.getMessage()), HttpStatus.CONFLICT);
+    }
+
+    @ExceptionHandler
+    public ResponseEntity<GenericResponse> resolveRoleNotFoundException(RoleNotExistsException ex){
+        log.error(ex.getMessage());
+        return new ResponseEntity<>(new GenericResponse(ex.getMessage()), HttpStatus.BAD_REQUEST);
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java
new file mode 100644 (file)
index 0000000..4a5837a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for Illegal Operation
+ */
+public class IllegalUserOperationException extends RuntimeException {
+    public IllegalUserOperationException(String s) {
+        super(s);
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java
new file mode 100644 (file)
index 0000000..dfa6efb
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for Role not exist
+ */
+public class RoleNotExistsException extends RuntimeException {
+    public RoleNotExistsException(String message) {
+        super(message);
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java
new file mode 100644 (file)
index 0000000..475dc44
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for User already exists
+ */
+public class UserAlreadyExistsException extends RuntimeException {
+    public UserAlreadyExistsException(String message) {
+        super(message);
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java
new file mode 100644 (file)
index 0000000..95c6a70
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for User Not Found
+ */
+public class UserNotFoundException extends RuntimeException {
+    public UserNotFoundException(String s) {
+        super(s);
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java
new file mode 100644 (file)
index 0000000..c4625a4
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Generic Response for the Auth Service Request
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+public class GenericResponse {
+
+    private String message;
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java
new file mode 100644 (file)
index 0000000..8855245
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * JWT Response for the Auth Service Request
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class JwtResponse {
+
+    private String token;
+    private String type = "Bearer";
+    private String id;
+    private String username;
+    private String fullName;
+    private List<String> roles;
+
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java
new file mode 100644 (file)
index 0000000..af0f710
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Login request
+ */
+@Data
+public class LoginRequest {
+
+    @NotBlank
+    private String username;
+
+    @NotBlank
+    private String password;
+
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java
new file mode 100644 (file)
index 0000000..4da5c98
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Assigning Roles to User
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Document(collection = "users")
+public class ModUser implements Serializable {
+
+    @Id
+    public String _id;
+
+    @NotBlank
+    @Size(max = 10)
+    private String username;
+
+    @NotBlank
+    private String password;
+
+    @NotBlank
+    private String fullName;
+
+    @DBRef
+    private Set<Role> roles = new HashSet<>();
+
+    public ModUser(@NotBlank @Size(max = 10) String username, @NotBlank String password, @NotBlank String fullName) {
+        this.username = username;
+        this.password = password;
+        this.fullName=fullName;
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java
new file mode 100644 (file)
index 0000000..8cce344
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Roles
+ */
+@Document(collection = "roles")
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Role {
+
+    @Id
+    private String id;
+
+    private String name;
+
+    public Role(String name) {
+        this.name = name;
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java
new file mode 100644 (file)
index 0000000..f705d76
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * To validate User enter Details
+ */
+@Data
+public class SignupRequest {
+
+    @NotBlank(message = "username must not be blank")
+    @Size(min = 5, max = 10, message = "username must be between 5 and 10 characters.")
+    private String username;
+
+    @NotNull(message = "username must not be null")
+    @Size(min = 1, message = "At least 1 role must be passed")
+    private Set<String> roles;
+
+    @NotBlank(message = "password must not be blank")
+    private String password;
+
+    @NotBlank(message = "Full name must not be blank")
+    private String fullName;
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java
new file mode 100644 (file)
index 0000000..6e3abf6
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * To update User Details of Name and Password
+ */
+@Data
+public class UpdateUserRequest {
+
+    @Size(min = 1, message = "At least 1 role must be passed")
+    private Set<String> roles;
+
+    @Pattern(regexp = "^(?!\\s*$).+", message = "password must not be blank")
+    private String password;
+
+    @Pattern(regexp = "^(?!\\s*$).+", message = "fullName must not be blank")
+    private String fullName;
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java
new file mode 100644 (file)
index 0000000..6efad17
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.repositories;
+
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+import java.util.Optional;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Interface to find user exists or not
+ */
+public interface RoleRepository extends MongoRepository<Role, String> {
+    Optional<Role> findByName(String name);
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java
new file mode 100644 (file)
index 0000000..442ebf1
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.repositories;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+import java.util.Optional;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Interface to Find/Valid/Delete user
+ */
+public interface UserRepository extends MongoRepository<ModUser, String>{
+    Optional<ModUser> findByUsername(String username);
+    Boolean existsByUsername(String username);
+    void deleteByUsername(String username);
+}
+
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java
new file mode 100644 (file)
index 0000000..cfccce4
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security;
+
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthTokenFilter;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Allows customization to the Spring WebSecurity
+ */
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
+
+    @Autowired
+    UserDetailsServiceImpl userDetailsService;
+
+    @Autowired
+    private AuthEntryPointJwt unauthorizedHandler;
+
+    @Bean
+    public AuthTokenFilter authenticationJwtTokenFilter(){
+        return new AuthTokenFilter();
+    }
+
+    @Override
+    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
+        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
+    }
+
+    @Bean
+    @Override
+    public AuthenticationManager authenticationManagerBean() throws Exception{
+        return super.authenticationManagerBean();
+    }
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http.cors().and().csrf().disable()
+                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
+                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+                .authorizeRequests().antMatchers("/api/auth/**").permitAll()
+                .antMatchers("/api/users/**").permitAll()
+                .anyRequest().authenticated();
+
+        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java
new file mode 100644 (file)
index 0000000..310d487
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.jwt;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * JWT Authentication Entry Point
+ */
+
+@Slf4j
+@Component
+public class AuthEntryPointJwt implements AuthenticationEntryPoint {
+
+    @Override
+    public void commence(HttpServletRequest request, HttpServletResponse response,
+                         AuthenticationException authException) throws IOException, ServletException {
+        log.error("Unauthorized error: {}", authException.getMessage());
+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java
new file mode 100644 (file)
index 0000000..012c333
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.jwt;
+
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Authentication Token Filter
+ */
+@Slf4j
+public class AuthTokenFilter extends OncePerRequestFilter {
+
+    @Autowired
+    private JwtUtils jwtUtils;
+
+    @Autowired
+    private UserDetailsServiceImpl userDetailsService;
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
+        try{
+            String jwt = parseJwt(httpServletRequest);
+            if (jwt != null && jwtUtils.validateJwtToken(jwt)){
+                String username = jwtUtils.getUserNameFromJwtToken(jwt);
+                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
+                UsernamePasswordAuthenticationToken authenticationToken =
+                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
+                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+            }
+        }catch (Exception e){
+            logger.error("Cannot set user authentication: {}", e);
+        }
+        filterChain.doFilter(httpServletRequest, httpServletResponse);
+    }
+
+    private String parseJwt(HttpServletRequest httpServletRequest) {
+        String headerAuth = httpServletRequest.getHeader("Authorization");
+
+        if(StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")){
+            return headerAuth.substring(7, headerAuth.length());
+        }
+        return null;
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java
new file mode 100644 (file)
index 0000000..3b6d311
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.jwt;
+
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.SignatureException;
+import io.jsonwebtoken.MalformedJwtException;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.UnsupportedJwtException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * JWT Utils
+ */
+@Slf4j
+@Component
+public class JwtUtils {
+
+    @Value("${mod-portal.jwt.secret}")
+    private String jwtSecret;
+
+    @Value("${mod-portal.jwt.jwtExpirationMs}")
+    private int jwtExpirationMs;
+
+    public String generateJwtToken(Authentication authentication) {
+
+        UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
+
+        return Jwts.builder()
+                .setSubject((userPrincipal.getUsername()))
+                .claim("roles", userPrincipal.getAuthoritiesAsList())
+                .claim("fullName", userPrincipal.getFullName())
+                .setIssuedAt(new Date())
+                .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
+                .signWith(SignatureAlgorithm.HS512, jwtSecret)
+                .compact();
+    }
+
+    public String getUserNameFromJwtToken(String token) {
+        return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
+    }
+
+    public boolean validateJwtToken(String authToken) {
+        try {
+            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
+            return true;
+        } catch (SignatureException e) {
+            log.error("Invalid JWT signature: {}", e.getMessage());
+        } catch (MalformedJwtException e) {
+            log.error("Invalid JWT token: {}", e.getMessage());
+        } catch (ExpiredJwtException e) {
+            log.error("JWT token is expired: {}", e.getMessage());
+        } catch (UnsupportedJwtException e) {
+            log.error("JWT token is unsupported: {}", e.getMessage());
+        } catch (IllegalArgumentException e) {
+            log.error("JWT claims string is empty: {}", e.getMessage());
+        }
+
+        return false;
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java
new file mode 100644 (file)
index 0000000..82cb577
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.services;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.EqualsAndHashCode;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * User Details Implementation
+ */
+@EqualsAndHashCode
+public class UserDetailsImpl implements UserDetails{
+
+    private static final long serialVersionUID = 1L;
+
+    private String id;
+
+    private String username;
+
+    private String fullName;
+
+    @JsonIgnore
+    private String password;
+
+    private Collection<? extends GrantedAuthority> authorities;
+
+    public UserDetailsImpl(String id, String username, String fullName, String password, Collection<?
+            extends GrantedAuthority> authorities) {
+        this.id = id;
+        this.username = username;
+        this.fullName = fullName;
+        this.password = password;
+        this.authorities = authorities;
+    }
+
+    public static UserDetails build(ModUser user) {
+        List<GrantedAuthority> authorities = user.getRoles().stream()
+                .map(role -> new SimpleGrantedAuthority(role.getName()))
+                .collect(Collectors.toList());
+
+        return new UserDetailsImpl(
+                user.get_id(),
+                user.getUsername(),
+                user.getFullName(),
+                user.getPassword(),
+                authorities
+        );
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        return authorities;
+    }
+
+    public List<String> getAuthoritiesAsList(){
+        return  authorities.stream().map(GrantedAuthority::getAuthority)
+                    .collect(Collectors.toList());
+    }
+
+    @Override
+    public String getPassword() {
+        return password;
+    }
+
+    @Override
+    public String getUsername() {
+        return username;
+    }
+
+    public String getFullName() {
+        return fullName;
+    }
+
+    @Override
+    public boolean isAccountNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isAccountNonLocked() {
+        return true;
+    }
+
+    @Override
+    public boolean isCredentialsNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return true;
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java
new file mode 100644 (file)
index 0000000..5c13e11
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.services;
+
+import org.onap.dcaegen2.platform.mod.controllers.AuthController;
+import org.onap.dcaegen2.platform.mod.exceptions.UserNotFoundException;
+import org.onap.dcaegen2.platform.mod.exceptions.IllegalUserOperationException;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import lombok.Setter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * User Details Service
+ */
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService {
+
+    @Autowired
+    @Setter
+    UserRepository userRepository;
+
+    @Autowired
+    PasswordEncoder passwordEncoder;
+
+    @Autowired
+    AuthController authController;
+
+    @Autowired
+    private JwtUtils jwtUtils;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        ModUser user = userRepository.findByUsername(username)
+                .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
+
+        return UserDetailsImpl.build(user);
+    }
+
+    public ModUser adminUpdateUser(String username, UpdateUserRequest userRequest, String token) {
+        return updateUserProfile(username, userRequest);
+    }
+
+    public ModUser userUpdateOwnProfile(String username, UpdateUserRequest userRequest, String token) {
+        String usernameFromToken = jwtUtils.getUserNameFromJwtToken(token.substring(7));
+        if (usernameFromToken.equals(username)) {
+            return updateUserProfile(username, userRequest);
+        } else {
+            throw new IllegalUserOperationException("Permission denied to update user profile of " + username);
+        }
+    }
+
+    private ModUser updateUserProfile(String username, UpdateUserRequest userRequest) {
+        ModUser modUser = userRepository.findByUsername(username).orElseThrow(() -> new UserNotFoundException(String.format("User %s not found", username)));
+        modUser = updateUserFields(modUser, userRequest);
+        return userRepository.save(modUser);
+    }
+
+    private ModUser updateUserFields(ModUser modUser, UpdateUserRequest userRequest) {
+        if (userRequest.getFullName() != null) modUser.setFullName(userRequest.getFullName());
+        if (userRequest.getPassword() != null) modUser.setPassword(passwordEncoder.encode(userRequest.getPassword()));
+        if (userRequest.getRoles() != null) {
+            Set<Role> roles = authController.createRoles(userRequest.getRoles());
+            modUser.setRoles(roles);
+        }
+        return modUser;
+    }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java
new file mode 100644 (file)
index 0000000..a6a6de5
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.services;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * This Service provides APIs to manage User Entity
+ */
+
+@Service
+public class MODUserDetailService {
+
+    @Autowired
+    private UserRepository userRepository;
+
+    public MODUserDetailService(UserRepository userRepository) {
+        this.userRepository = userRepository;
+    }
+
+    public List<ModUser> findAll() {
+        return userRepository.findAll();
+    }
+
+    public void deleteUserByUsername(String username) {
+        userRepository.deleteByUsername(username);
+    }
+
+}
diff --git a/mod2/auth-service/src/main/resources/application.properties b/mod2/auth-service/src/main/resources/application.properties
new file mode 100644 (file)
index 0000000..f3f5d37
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# /*
+#  * ============LICENSE_START=======================================================
+#  *  org.onap.dcae
+#  *  ================================================================================
+#  *  Copyright (c) 2020 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.
+#  *  ============LICENSE_END=========================================================
+#  */
+#
+
+server.port=8082
+
+#spring.data.mongodb.host=mongo_db
+spring.data.mongodb.host=localhost
+#spring.data.mongodb.host=zlecdyh2bdcc1s2dokr05.ec53e7.dyh2b.tci.att.com
+spring.data.mongodb.port=27017
+spring.data.mongodb.database=dcae_mod
+
+mod-portal.jwt.secret=mod2020!
+mod-portal.jwt.jwtExpirationMs=43200000
\ No newline at end of file
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/AuthObjectMother.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/AuthObjectMother.java
new file mode 100644 (file)
index 0000000..3a22af3
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.objectmothers;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onap.dcaegen2.platform.mod.models.LoginRequest;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.models.SignupRequest;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import org.onap.dcaegen2.platform.mod.util.TestUtil;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock for AuthenticationController Test Case
+ */
+
+public class AuthObjectMother {
+    public static final String LOGIN_REQUEST = "src/test/resources/http/requests/AuthLoginRequest.json";
+    public static final String SIGNUP_REQUEST = "src/test/resources/http/requests/AuthSignupRequest.json";
+
+    public static String asJsonString(final Object object) {
+        try {
+            return new ObjectMapper().writeValueAsString(object);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static LoginRequest getLoginRequest() {
+        return TestUtil.deserializeJsonFileToModel(LOGIN_REQUEST, LoginRequest.class);
+    }
+
+    public static SignupRequest getSignupRequest() {
+        return TestUtil.deserializeJsonFileToModel(SIGNUP_REQUEST, SignupRequest.class);
+    }
+
+    public static UserDetailsImpl getUserDetailsImpl() {
+        SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_ADMIN");
+        List authorities = new ArrayList();
+        authorities.add(simpleGrantedAuthority);
+        return new UserDetailsImpl("admin123", "admin123", "admin123", "admin123", authorities);
+    }
+
+    public static ModUser getModUser() {
+        ModUser user = new ModUser();
+        user.setUsername("test");
+        user.setFullName("test");
+        user.setPassword("password");
+        Set<Role> roles = new HashSet<>();
+        Role role = new Role();
+        role.setName("test");
+        role.setId("123");
+        roles.add(role);
+        user.setRoles(roles);
+        return user;
+    }
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/RoleObjectMother.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/RoleObjectMother.java
new file mode 100644 (file)
index 0000000..68002ac
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.objectmothers;
+
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock for RoleController Test Case
+ */
+public class RoleObjectMother {
+
+    public static List<Role> getRoles() {
+        List<Role> roles = new ArrayList();
+        Role role1 = new Role();
+        role1.setId("123");
+        role1.setName("Admin123");
+
+        Role role2 = new Role();
+        role2.setId("1234");
+        role2.setName("Admin1234");
+
+        roles.add(role1);
+        roles.add(role2);
+
+        return roles;
+    }
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/UserObjectMother.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/UserObjectMother.java
new file mode 100644 (file)
index 0000000..301b81f
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.objectmothers;
+
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock for UserController Test Case
+ */
+public class UserObjectMother {
+
+    public static final String userId = "admin";
+
+    public static List<ModUser> getUsers() {
+        List<ModUser> users = new ArrayList();
+        ModUser modUser1 = new ModUser();
+        modUser1.set_id("123");
+        modUser1.setFullName("Admin123");
+        modUser1.setPassword("Admin123");
+        Set<Role> roles = new HashSet<>();
+        Role role = new Role();
+        role.setName("test");
+        role.setId("123");
+        roles.add(role);
+        modUser1.setRoles(roles);
+
+        ModUser modUser2 = new ModUser();
+        modUser2.set_id("1234");
+        modUser2.setFullName("Admin1234");
+        modUser2.setPassword("Admin1234");
+        Set<Role> roles1 = new HashSet<>();
+        Role role1 = new Role();
+        role.setName("test1");
+        role.setId("1234");
+        roles.add(role1);
+        modUser2.setRoles(roles1);
+
+        users.add(modUser1);
+        users.add(modUser2);
+
+        return users;
+    }
+
+    public static ModUser getModUser() {
+        ModUser user = new ModUser();
+        user.setUsername("test");
+        user.setFullName("test");
+        user.setPassword("password");
+        Set<Role> roles = new HashSet<>();
+        Role role = new Role();
+        role.setName("test");
+        role.setId("123");
+        roles.add(role);
+        user.setRoles(roles);
+        return user;
+    }
+
+    public static UpdateUserRequest getUpdateUserRequest(){
+        UpdateUserRequest user = new UpdateUserRequest();
+        user.setFullName("test");
+        user.setPassword("password");
+        Set<String> roles = new HashSet<>();
+        roles.add("ROLE_PST");
+        user.setRoles(roles);
+        return user;
+    }
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/util/TestUtil.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/util/TestUtil.java
new file mode 100644 (file)
index 0000000..111653f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.util;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * TestUtils for test cases
+ */
+public class TestUtil {
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    private TestUtil() {}
+
+    public static Map<String, Object> readJsonFileAsObjectMap(String filePath) {
+        try {
+            return MAPPER.readValue(new File(filePath), new TypeReference<Map<String, Object>>() {});
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+    }
+
+    public static <T> T deserializeJsonFileToModel(String filePath, Class<T> modelClass) {
+        try {
+            return MAPPER.readValue(new File(filePath), modelClass);
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+    }
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/AuthControllerTest.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/AuthControllerTest.java
new file mode 100644 (file)
index 0000000..2aad289
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.onap.dcaegen2.platform.mod.controllers.AuthController;
+import org.onap.dcaegen2.platform.mod.models.*;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.*;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.web.client.RestTemplate;
+import org.testng.annotations.BeforeTest;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.mockito.Mockito.*;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock Test cases for AuthenticationController
+ */
+@WebMvcTest(AuthController.class)
+public class AuthControllerTest {
+
+    @Autowired
+    private MockMvc mockMvc;
+
+    @MockBean
+    JwtUtils jwtUtils;
+
+    @MockBean
+    AuthenticationManager authenticationManager;
+
+    @MockBean
+    UserRepository userRepository;
+
+    @MockBean
+    RoleRepository roleRepository;
+
+    @MockBean
+    PasswordEncoder passwordEncoder;
+
+    @MockBean
+    UserDetailsServiceImpl userDetailsService;
+
+    @MockBean
+    AuthEntryPointJwt authEntryPointJwt;
+
+    @Mock
+    Authentication authentication;
+
+    @BeforeEach
+    void setUp() {
+    }
+
+
+    @Test
+    void test_signin_returnsSuccessResponse() throws Exception {
+
+        LoginRequest loginRequest = getLoginRequest();
+
+        when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()))).thenReturn(authentication);
+        when(authentication.getPrincipal()).thenReturn(getUserDetailsImpl());
+        when(jwtUtils.generateJwtToken(any())).thenReturn("Demo");
+
+        mockMvc.perform(post("/api/auth/signin")
+                .contentType(MediaType.APPLICATION_JSON)
+                .content(asJsonString(loginRequest)).accept(MediaType.APPLICATION_JSON))
+                .andExpect(jsonPath("$.token", notNullValue()))
+                .andExpect(status().isOk());
+
+        verify(authenticationManager, times(1)).authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
+        verify(jwtUtils, times(1)).generateJwtToken(any());
+    }
+
+
+    @WithMockUser(roles="ADMIN")
+    @Test
+    void test_signup_returnsSuccessResponse() throws Exception {
+
+        SignupRequest signUpRequest = getSignupRequest();
+
+        when(userRepository.existsByUsername(signUpRequest.getUsername())).thenReturn(false);
+        when(passwordEncoder.encode(signUpRequest.getPassword())).thenReturn("password");
+        when(roleRepository.findByName(anyString())).thenReturn(Optional.of(new Role()));
+        when(userRepository.save(any())).thenReturn(getModUser());
+
+        mockMvc.perform(post("/api/auth/signup")
+                .contentType(MediaType.APPLICATION_JSON)
+                .content(asJsonString(signUpRequest)).accept(MediaType.APPLICATION_JSON))
+                .andExpect(jsonPath("$.message", notNullValue()))
+                .andExpect(status().isOk());
+
+        verify(userRepository, times(1)).existsByUsername(signUpRequest.getUsername());
+        verify(passwordEncoder, times(1)).encode(signUpRequest.getPassword());
+        verify(roleRepository, times(1)).findByName(anyString());
+        verify(userRepository, times(1)).save(any());
+    }
+
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/RoleControllerTest.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/RoleControllerTest.java
new file mode 100644 (file)
index 0000000..48b5d4b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.web;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.dcaegen2.platform.mod.controllers.RoleController;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.asJsonString;
+import static org.onap.dcaegen2.platform.mod.objectmothers.RoleObjectMother.getRoles;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock Test cases for RoleController
+ */
+@WebMvcTest(RoleController.class)
+public class RoleControllerTest {
+
+    @Autowired
+    private MockMvc mockMvc;
+
+    @MockBean
+    RoleRepository roleRepository;
+
+    @MockBean
+    UserDetailsServiceImpl userDetailsService;
+
+    @MockBean
+    AuthEntryPointJwt authEntryPointJwt;
+
+    @MockBean
+    JwtUtils jwtUtils;
+
+    @Mock
+    Authentication authentication;
+
+    @BeforeEach
+    void setUp() {
+    }
+
+
+    @Test
+    void test_getRoles() throws Exception {
+
+        Mockito.when(roleRepository.findAll()).thenReturn(getRoles());
+
+        MvcResult result =  mockMvc.perform(get("/api/roles")
+            .contentType(MediaType.APPLICATION_JSON))
+            .andExpect(status().isOk()).andReturn();
+
+        Assert.assertNotNull(result.getResponse().getContentAsString());
+
+    }
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/UserControllerTest.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/UserControllerTest.java
new file mode 100644 (file)
index 0000000..1374e0e
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ *
+ *  * ============LICENSE_START=======================================================
+ *  *  org.onap.dcae
+ *  *  ================================================================================
+ *  *  Copyright (c) 2020 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.
+ *  *  ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.web;
+
+import org.apache.tools.ant.taskdefs.optional.extension.Specification;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.Request;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.dcaegen2.platform.mod.controllers.RoleController;
+import org.onap.dcaegen2.platform.mod.controllers.UserController;
+import org.onap.dcaegen2.platform.mod.models.LoginRequest;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.onap.dcaegen2.platform.mod.services.MODUserDetailService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.web.client.RequestMatcher;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultMatcher;
+
+import java.util.Optional;
+
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.asJsonString;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.getModUser;
+import static org.onap.dcaegen2.platform.mod.objectmothers.RoleObjectMother.getRoles;
+import static org.onap.dcaegen2.platform.mod.objectmothers.UserObjectMother.*;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock Test cases for UserController
+ */
+@WebMvcTest(UserController.class)
+public class UserControllerTest {
+
+
+    @Autowired
+    private MockMvc mockMvc;
+
+    @MockBean
+    UserDetailsServiceImpl userDetailsService;
+
+    @MockBean
+    UserRepository userRepository;
+
+    @MockBean
+    MODUserDetailService modUserDetailService;
+
+    @MockBean
+    RoleRepository roleRepository;
+
+    @MockBean
+    AuthEntryPointJwt authEntryPointJwt;
+
+    @MockBean
+    JwtUtils jwtUtils;
+
+    @Mock
+    Authentication authentication;
+
+
+    @BeforeEach
+    void setUp() {
+    }
+
+    @WithMockUser(roles="ADMIN")
+    @Test
+    void test_getUsername() throws Exception {
+
+        when(userRepository.findByUsername(any())).thenReturn(Optional.of(new ModUser()));
+
+        MvcResult result =  mockMvc.perform(get("/api/users/" + userId)
+                .contentType(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk()).andReturn();
+
+        Assert.assertNotNull(result.getResponse().getContentAsString());
+        verify(userRepository, times(1)).findByUsername(any());
+    }
+
+    @Test
+    void test_getAllUsers() throws Exception {
+
+        when(modUserDetailService.findAll()).thenReturn(getUsers());
+
+        MvcResult result =  mockMvc.perform(get("/api/users/getAll")
+                .contentType(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk()).andReturn();
+
+        Assert.assertNotNull(result.getResponse().getContentAsString());
+        verify(modUserDetailService, times(1)).findAll();
+    }
+
+
+    @WithMockUser(roles="ADMIN")
+    @Test
+    void test_deleteUser() throws Exception {
+
+        doNothing().when(modUserDetailService).deleteUserByUsername(any(String.class));
+
+        MvcResult result =  mockMvc.perform(delete("/api/users/" + userId)
+                .contentType(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk()).andReturn();
+
+        Assert.assertNotNull(result.getResponse().getContentAsString());
+        verify(modUserDetailService, times(1)).deleteUserByUsername(any(String.class));
+    }
+
+
+    @WithMockUser(username="ADMIN")
+    @Test
+    void test_userUpdateOwnProfile_returnsSuccessResponse() throws Exception {
+        //arrange
+        UpdateUserRequest updateUserRequest = getUpdateUserRequest();
+
+        when(userDetailsService.adminUpdateUser(userId,updateUserRequest,"token")).thenReturn(getModUser());
+
+        mockMvc.perform(patch("/api/users/admin/" + userId)
+                //.header("Authorization", "token")
+                .contentType(MediaType.APPLICATION_JSON)
+                .content(asJsonString(updateUserRequest)).accept(MediaType.APPLICATION_JSON))
+                //.andExpect(jsonPath("$.message", notNullValue()))
+                .andExpect(status().isOk()).andReturn();
+
+        verify(userDetailsService, times(1)).adminUpdateUser(anyString(),updateUserRequest,anyString());
+    }
+
+
+}
\ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/application.properties b/mod2/auth-service/src/test/resources/application.properties
new file mode 100644 (file)
index 0000000..d6a913c
--- /dev/null
@@ -0,0 +1 @@
+#spring.data.mongodb.port=0
\ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/http/requests/AuthLoginRequest.json b/mod2/auth-service/src/test/resources/http/requests/AuthLoginRequest.json
new file mode 100644 (file)
index 0000000..fbdc4a9
--- /dev/null
@@ -0,0 +1,4 @@
+{
+       "username": "admin",
+       "password": "admin@mod"
+}
diff --git a/mod2/auth-service/src/test/resources/http/requests/AuthSignupRequest.json b/mod2/auth-service/src/test/resources/http/requests/AuthSignupRequest.json
new file mode 100644 (file)
index 0000000..25be086
--- /dev/null
@@ -0,0 +1,6 @@
+{
+       "username": "admin1",
+       "fullName": "Administrator",
+       "password": "admin@mod",
+       "roles": ["ROLE_PST"]
+}
\ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/specification/componentSpec_hello_world-with-dmaap.json b/mod2/auth-service/src/test/resources/specification/componentSpec_hello_world-with-dmaap.json
new file mode 100644 (file)
index 0000000..0ad6b6e
--- /dev/null
@@ -0,0 +1,149 @@
+{
+       "self": {
+               "component_type": "docker",
+               "description": "Hello World mS for subscribing the data from local DMaaP, DR or MR, processing them and publishing them as PM files to local DMaaP DR",
+               "name": "dcae-collectors-vcc-helloworld-pm",
+               "version": "1.0.1"
+       },
+
+       "services": {
+               "calls": [],
+               "provides": []
+       },
+
+       "streams": {
+               "publishes": [{
+                       "config_key": "DCAE-HELLO-WORLD-PUB-DR",
+                       "format": "dataformat_Hello_World_PM",
+                       "type": "data_router",
+                       "version": "1.0.0"
+               },
+                       {
+                               "config_key": "DCAE-HELLO-WORLD-PUB-MR",
+                               "format": "dataformat_Hello_World_PM",
+                               "type": "message_router",
+                               "version": "1.0.0"
+                       }
+               ],
+
+               "subscribes": [{
+                       "config_key": "DCAE-HELLO-WORLD-SUB-MR",
+                       "format": "dataformat_Hello_World_PM",
+                       "route": "/DCAE_HELLO_WORLD_SUB_MR",
+                       "type": "message_router",
+                       "version": "1.0.0"
+               },
+                       {
+                               "config_key": "DCAE-HELLO-WORLD-SUB-DR",
+                               "format": "dataformat_Hello_World_PM",
+                               "route": "/DCAE-HELLO-WORLD-SUB-DR",
+                               "type": "data_router",
+                               "version": "1.0.0"
+                       }
+               ]
+       },
+
+       "parameters":
+       [
+               {
+                       "name": "vcc_hello_name",
+                       "value": "120",
+                       "type": "integer",
+                       "description": "the name entered for specific person",
+                       "sourced_at_deployment": false,
+                       "designer_editable": false,
+                       "policy_editable": false
+               },
+
+               {
+                       "name": "useDtiConfig",
+                       "value": false,
+                       "type" : "boolean",
+                       "description": "component depends on configuration from dti.",
+                       "sourced_at_deployment": false,
+                       "designer_editable": true,
+                       "policy_editable": false,
+                       "required" : true
+               },
+
+               {
+                       "name": "isSelfServeComponent",
+                       "value": false,
+                       "type": "boolean",
+                       "description": "Is this used as self serve component.",
+                       "sourced_at_deployment": false,
+                       "designer_editable": true,
+                       "policy_editable": false,
+                       "required" : true
+               }
+       ],
+
+       "auxilary": {
+               "healthcheck": {
+                       "interval": "60s",
+                       "initialDelaySeconds": "120s",
+                       "timeout": "20s",
+                       "script": "/opt/app/vcc/bin/common/HealthCheck_HelloWorld.sh",
+                       "type": "docker"
+               },
+               "livehealthcheck": {
+                       "interval": "60s",
+                       "initialDelaySeconds": "120s",
+                       "timeout": "20s",
+                       "script": "/opt/app/vcc/bin/common/HealthCheck_HelloWorld.sh",
+                       "type": "docker"
+               },
+               "reconfigs":{
+                       "app_reconfig" : "abc"
+               },
+
+               "volumes": [
+                       {
+                               "container": {
+                                       "bind": "/opt/app/dcae-certificate"
+                               },
+                               "host": {
+                                       "path": "/opt/app/dcae-certificate"
+                               }
+                       },
+                       {
+                               "container": {
+                                       "bind": "/opt/logs/DCAE/dmd/AGENT"
+                               },
+                               "host": {
+                                       "path": "/opt/logs/DCAE/helloworldpm/dmd/AGENT"
+                               }
+                       },
+                       {
+                               "container": {
+                                       "bind": "/opt/logs/DCAE/dmd/WATCHER"
+                               },
+                               "host": {
+                                       "path": "/opt/logs/DCAE/helloworldpm/dmd/WATCHER"
+                               }
+                       },
+                       {
+                               "container": {
+                                       "bind": "/opt/app/vcc/logs/DCAE"
+                               },
+                               "host": {
+                                       "path": "/opt/logs/DCAE/helloworldpm/vcc-logs"
+                               }
+                       },
+                       {
+                               "container": {
+                                       "bind": "/opt/app/vcc/archive/data"
+                               },
+                               "host": {
+                                       "path": "/opt/data/DCAE/helloworldpm/vcc-archive"
+                               }
+                       }
+
+               ]
+
+       },
+       "artifacts": [{
+               "type": "docker image",
+               "uri": "dockercentral.it.att.com:5100/com.att.sample/dcae-controller-vcc-helloworld-pm:18.02-001"
+       }]
+}
\ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/specification/policy_json_sample_3.json b/mod2/auth-service/src/test/resources/specification/policy_json_sample_3.json
new file mode 100644 (file)
index 0000000..4a8c76f
--- /dev/null
@@ -0,0 +1,28 @@
+{
+       "policies": [
+               {
+                       "configAttributes": "",
+               "configName": "",
+               "onapName": "DCAE",
+               "policyName": "DCAE.Config_",
+               "unique": false
+               },
+               {
+                       "onapName": "DCAE",
+                       "policyName": "DCAE.Config_",
+                       "unique": true
+               },
+               {
+                       "configAttributes": "",
+                       "configName": "",
+                       "onapName": "DCAE",
+                       "policyName": "DCAE.Config_*",
+                       "unique": false
+               }
+       ],
+       "policy": [
+               {
+                       "policy_id" : "id_0"
+               }
+       ]
+}
\ No newline at end of file