diff --git a/pom.xml b/pom.xml
index a908f28..799cce9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,13 @@
1.0.0-M3
+
+
+ io.micrometer
+ micrometer-core
+
+
+
org.springframework.boot
spring-boot-starter-web
@@ -39,6 +46,17 @@
org.springframework.boot
spring-boot-starter-webflux
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
org.springframework.ai
spring-ai-openai-spring-boot-starter
@@ -55,26 +73,92 @@
org.springframework.ai
spring-ai-redis-store-spring-boot-starter
-
- org.springframework.ai
- spring-ai-transformers-spring-boot-starter
-
+
+
+
+
+
+
redis.clients
jedis
- 5.2.0
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
org.springframework.boot
- spring-boot-starter-test
- test
+ spring-boot-starter-data-jpa
+
+
- io.projectreactor
- reactor-test
- test
+ com.mysql
+ mysql-connector-j
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.11.5
+ runtime
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.11.5
+ runtime
+
+
+
+
+ org.mapstruct
+ mapstruct
+ 1.5.5.Final
+
+
+ org.mapstruct
+ mapstruct-processor
+ 1.5.5.Final
+ provided
+
+
+
+
+ jakarta.annotation
+ jakarta.annotation-api
+
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+ 10.1.25
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+ 6.0.0
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
@@ -93,6 +177,15 @@
org.springframework.boot
spring-boot-maven-plugin
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.10.1
+
+ 17
+ 17
+
+
diff --git a/src/main/java/com/openAi/ai/OpenAiApi.java b/src/main/java/com/openAi/ai/OpenAiApi.java
new file mode 100644
index 0000000..a91238b
--- /dev/null
+++ b/src/main/java/com/openAi/ai/OpenAiApi.java
@@ -0,0 +1,22 @@
+package com.openAi.ai;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+public class OpenAiApi {
+ @Data public static class EmbeddingList {
+ @JsonProperty("data")
+ private List data;
+
+ // Getters and setters
+ }
+
+ @Data public static class Embedding {
+ @JsonProperty("embedding")
+ private List embedding;
+
+ // Getters and setters
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/ai/RedisConfig.java b/src/main/java/com/openAi/ai/RedisConfig.java
deleted file mode 100644
index c92d643..0000000
--- a/src/main/java/com/openAi/ai/RedisConfig.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.openAi.ai;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
-import org.springframework.data.redis.serializer.StringRedisSerializer;
-
-@Configuration
-public class RedisConfig {
-
- @Bean
- public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
- RedisTemplate template = new RedisTemplate<>();
- template.setConnectionFactory(connectionFactory);
-
- // Key serializer
- template.setKeySerializer(new StringRedisSerializer());
- // Value serializer
- //template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
-
- return template;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/ai/RedisService.java b/src/main/java/com/openAi/ai/RedisService.java
deleted file mode 100644
index 51469a7..0000000
--- a/src/main/java/com/openAi/ai/RedisService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.openAi.ai;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.connection.DataType;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.stereotype.Service;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-@Service
-public class RedisService {
-
- @Autowired
- private RedisTemplate redisTemplate;
-
- @Autowired
- private ObjectMapper objectMapper;
-
- public List getKeysByJsonNodeValue(String nodeName, String nodeValue) {
- List matchingKeys = new ArrayList<>();
- Set keys = redisTemplate.keys("*");
-
- if (keys != null) {
- for (String key : keys) {
- System.out.println("key: " + key);
-
- Object value = redisTemplate.opsForValue().get(key);
- if (value != null) {
- try {
- JsonNode jsonNode = objectMapper.readTree(value.toString());
- if (jsonNode.has(nodeName) && jsonNode.get(nodeName).asText().equals(nodeValue)) {
- matchingKeys.add(key);
- }
- } catch (Exception e) {
- System.err.println("Error parsing JSON for key: " + key + " - " + e.getMessage());
- }
- }
- }
-
-
- }
-
-
- return matchingKeys;
- }
- /* public List getKeysByJsonNodeValue(String nodeName, String nodeValue) {
- return new ArrayList<>();
- }*/
-}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/application/OpenAiApplication.java b/src/main/java/com/openAi/application/OpenAiApplication.java
index 4a008f4..f5e6026 100644
--- a/src/main/java/com/openAi/application/OpenAiApplication.java
+++ b/src/main/java/com/openAi/application/OpenAiApplication.java
@@ -1,13 +1,43 @@
package com.openAi.application;
-
+import com.openAi.security.AuthenticationFilter;
+import org.springframework.ai.chat.model.ChatModel;
+import org.springframework.ai.openai.OpenAiChatModel;
+import org.springframework.ai.openai.api.OpenAiApi;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
-
-@SpringBootApplication(scanBasePackages = "com.openAi")
+@SpringBootApplication(scanBasePackages = "com.openAi", exclude = {SecurityAutoConfiguration.class})
+@EnableJpaRepositories(basePackages = "com.openAi.security.repository")
+@EntityScan(basePackages = "com.openAi.security.entity")
public class OpenAiApplication {
- public static void main(String[] args) {
- SpringApplication.run(OpenAiApplication.class, args);
- }
-}
+
+ public static void main(String[] args) {
+ SpringApplication.run(OpenAiApplication.class, args);
+ }
+
+ @Bean
+ ChatModel chatModel(@Value("${spring.ai.openai.api-key}") String apiKey) {
+ return new OpenAiChatModel(new OpenAiApi(apiKey));
+ }
+
+ @Bean
+ public FilterRegistrationBean filterRegistrationBean() {
+ AuthenticationFilter filter = new AuthenticationFilter();
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
+ registrationBean.setFilter(filter);
+ registrationBean.setEnabled(false);
+ return registrationBean;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/security/AuthenticationFilter.java b/src/main/java/com/openAi/security/AuthenticationFilter.java
new file mode 100644
index 0000000..86362d3
--- /dev/null
+++ b/src/main/java/com/openAi/security/AuthenticationFilter.java
@@ -0,0 +1,134 @@
+package com.openAi.security;
+
+import com.openAi.security.exceptions.InvalidAuthenticationException;
+import com.openAi.security.model.UserModel;
+import com.openAi.security.service.UserService;
+import com.openAi.security.utils.JwtUtils;
+import io.jsonwebtoken.Claims;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.context.support.SpringBeanAutowiringSupport;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.Objects;
+import java.util.UUID;
+
+import static com.openAi.security.enums.EntityStatus.ACTIVE;
+
+@Slf4j
+@Component
+
+public class AuthenticationFilter extends OncePerRequestFilter {
+
+ @Autowired
+ private JwtUtils jwtUtils;
+ @Autowired
+ private UserService userService;
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ @Value("${security.apiKey}")
+ private String apiKey;
+ private AuthenticationManager authenticationManager;
+
+ public AuthenticationFilter() {
+ SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
+ }
+
+ @Override
+ @SneakyThrows
+ protected void doFilterInternal(
+ HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
+
+ String path = request.getRequestURI();
+ log.info(
+ String.format("Requested path: %s at %s by %s", path, new Date(), request.getRemoteHost()));
+ if (
+ new AntPathMatcher().match("/getToken", path)
+ || HttpMethod.OPTIONS.name().equalsIgnoreCase(request.getMethod())
+ || new AntPathMatcher().match("/", path)
+ && apiKey.equals(request.getHeader("Api-Key"))) {
+ filterChain.doFilter(request, response);
+ return;
+ }
+
+ String jwt;
+ try {
+ jwt = parseJwt();
+ jwtUtils.validateJwtToken(jwt);
+ } catch (Exception e) {
+ log.error(
+ String.format(
+ "%s | AUTHORIZATION Header: %s",
+ e.getMessage(), request.getHeader(HttpHeaders.AUTHORIZATION)));
+ response.setStatus(HttpStatus.UNAUTHORIZED.value());
+ return;
+ }
+
+ Claims claims = jwtUtils.getAllClaimsFromToken(jwt);
+ String email = claims.getSubject();
+ UserModel userModel;
+ try {
+ userModel = userService.findUserByEmailOrAttendance(email);
+ } catch (Exception e) {
+ log.error("User not found for email {}", email);
+ response.setStatus(HttpStatus.UNAUTHORIZED.value());
+ return;
+ }
+
+ boolean enabled = ACTIVE.equals(userModel.getStatus());
+ User user =
+ new User(
+ userModel.getEmail(),
+ UUID.randomUUID().toString(),
+ enabled,
+ true,
+ true,
+ true,
+ Collections.singletonList(new SimpleGrantedAuthority(userModel.getRole().name())));
+
+ final UsernamePasswordAuthenticationToken authentication =
+ new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+
+ filterChain.doFilter(request, response);
+ }
+
+ public String parseJwt() {
+
+ Cookie[] cookieAuth = httpServletRequest.getCookies();
+ if (Objects.nonNull(cookieAuth)) {
+ for (Cookie cookie : cookieAuth) {
+ if (cookie.getName().equals("auth-token")) {
+ return cookie.getValue();
+ }
+ }
+ }
+
+ throw InvalidAuthenticationException.invalidToken("Failed to parse JWT Token");
+ }
+
+ public void setAuthenticationManager(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ }
+}
+
+
diff --git a/src/main/java/com/openAi/security/ConfigController.java b/src/main/java/com/openAi/security/ConfigController.java
new file mode 100644
index 0000000..7fbd1d2
--- /dev/null
+++ b/src/main/java/com/openAi/security/ConfigController.java
@@ -0,0 +1,27 @@
+package com.openAi.security;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.cors.CorsConfiguration;
+
+@RestController
+@RequestMapping("/security-config")
+@EnableCaching
+@Slf4j
+@RequiredArgsConstructor
+public class ConfigController {
+
+ private final com.openAi.security.WebSecurityConfig webSecurityConfig;
+
+ @PostMapping("/refresh-cors-config")
+ public ResponseEntity refreshCorsConfig() {
+ CorsConfiguration configuration = new CorsConfiguration();
+ webSecurityConfig.updateCorsConfiguration(configuration);
+ return ResponseEntity.ok("CORS configuration updated successfully");
+ }
+}
diff --git a/src/main/java/com/openAi/security/CustomHttpServletRequestFactory.java b/src/main/java/com/openAi/security/CustomHttpServletRequestFactory.java
new file mode 100644
index 0000000..c952977
--- /dev/null
+++ b/src/main/java/com/openAi/security/CustomHttpServletRequestFactory.java
@@ -0,0 +1,14 @@
+package com.openAi.security;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CustomHttpServletRequestFactory {
+
+ public SecurityContextHolderAwareRequestWrapper create(HttpServletRequest request, HttpServletResponse response) {
+ return new SecurityContextHolderAwareRequestWrapper(request, response.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/security/CustomSecurityContextHolderAwareRequestFilter.java b/src/main/java/com/openAi/security/CustomSecurityContextHolderAwareRequestFilter.java
new file mode 100644
index 0000000..ef7b139
--- /dev/null
+++ b/src/main/java/com/openAi/security/CustomSecurityContextHolderAwareRequestFilter.java
@@ -0,0 +1,31 @@
+package com.openAi.security;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
+import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CustomSecurityContextHolderAwareRequestFilter extends SecurityContextHolderAwareRequestFilter {
+
+ private final CustomHttpServletRequestFactory customHttpServletRequestFactory;
+
+ public CustomSecurityContextHolderAwareRequestFilter(CustomHttpServletRequestFactory customHttpServletRequestFactory) {
+ this.customHttpServletRequestFactory = customHttpServletRequestFactory;
+ }
+// @Override
+ protected SecurityContextHolderAwareRequestWrapper wrapRequest(HttpServletRequest request) {
+ return customHttpServletRequestFactory.create(request, null);
+ }
+
+// @Override
+ protected SecurityContextHolderAwareRequestWrapper wrapRequest(HttpServletRequest request, HttpServletResponse response) {
+ return customHttpServletRequestFactory.create(request, response);
+ }
+
+// @Override
+ protected SecurityContextHolderAwareRequestWrapper create(HttpServletRequest request, HttpServletResponse response) {
+ return customHttpServletRequestFactory.create(request, response);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/security/PasswordEncryptor.java b/src/main/java/com/openAi/security/PasswordEncryptor.java
new file mode 100644
index 0000000..000b9f9
--- /dev/null
+++ b/src/main/java/com/openAi/security/PasswordEncryptor.java
@@ -0,0 +1,15 @@
+package com.openAi.security;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@Configuration
+public class PasswordEncryptor {
+
+ @Bean
+ public PasswordEncoder passwordEncoder(){
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/src/main/java/com/openAi/security/WebSecurityConfig.java b/src/main/java/com/openAi/security/WebSecurityConfig.java
new file mode 100644
index 0000000..ef459b1
--- /dev/null
+++ b/src/main/java/com/openAi/security/WebSecurityConfig.java
@@ -0,0 +1,141 @@
+//package com.openAi.security;
+//
+//import com.openAi.security.entity.AllowedDomain;
+//import com.openAi.security.repository.AllowedDomainRepository;
+//import lombok.RequiredArgsConstructor;
+//
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.context.annotation.Profile;
+//import org.springframework.http.HttpStatus;
+//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.http.SessionCreationPolicy;
+//import org.springframework.security.web.authentication.HttpStatusEntryPoint;
+//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+//import org.springframework.web.cors.CorsConfiguration;
+//import org.springframework.web.cors.CorsConfigurationSource;
+//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+//
+//import java.util.Arrays;
+//import java.util.List;
+//
+//@Configuration
+//@EnableWebSecurity
+//@EnableGlobalMethodSecurity(prePostEnabled = true)
+//@RequiredArgsConstructor
+//public class WebSecurityConfig {
+//
+// private final AuthenticationFilter filter;
+//
+// private final AllowedDomainRepository allowedDomainRepository;
+//
+// private CorsConfiguration configuration = new CorsConfiguration();
+//
+//
+//// @Override
+// protected void configure(HttpSecurity http) throws Exception {
+// http.cors(cors -> cors.configurationSource(corsConfigurationSource()))
+// .csrf(csrf -> csrf.disable())
+// .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+// .authorizeHttpRequests(authorize -> authorize
+// .requestMatchers(
+// "/getToken",
+// "/cicero/cicero-compliance-data",
+// "/cicero/importCiceroData",
+// "/technology/getTechDigest/label",
+// "/valueAdd/valueAddsByTag",
+// "/tech/categories",
+// "/tech/categories/*",
+// "/tech/category/*/value-adds",
+// "/tech/category/*/blogs",
+// "/tech/category/*/teams",
+// "/tech/category/**",
+// "/tech/**",
+// "/getTokenUserAuth",
+// "/user/generatePassword",
+// "/resetPassword",
+// "/getTokenGoogleAuth"
+// ).permitAll()
+// .anyRequest().authenticated()
+// )
+// .exceptionHandling(exception -> exception.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)))
+// .addFilterBefore(filter, AuthenticationFilter.class);
+// }
+// @Bean
+// @Profile({"dev","staging","prod"})
+// public CorsConfigurationSource corsConfigurationSource() {
+// updateCorsConfiguration();
+// configuration.addExposedHeader("Set-Cookie");
+// configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "PUT", "DELETE"));
+// // setAllowCredentials(true) is important, otherwise:
+// // The value of the 'Access-Control-Allow-Origin' header in the response must not be the
+// // wildcard '*' when the request's credentials mode is 'include'.
+// // setAllowedHeaders is important! Without it, OPTIONS preflight request
+// // will fail with 403 Invalid CORS request
+// configuration.setAllowedHeaders(
+// List.of(
+// "Api-Key",
+// "Authorization",
+// "Cache-Control",
+// "Content-Type",
+// "Access-Control-Allow-Origin",
+// "Access-Control-Allow-Credentials"));
+// configuration.setAllowCredentials(true);
+//
+// final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+// source.registerCorsConfiguration("/**", configuration);
+// return source;
+// }
+//
+// @Bean
+// @Profile("test")
+// public CorsConfigurationSource corsConfigurationSourceTest() {
+// final CorsConfiguration corsConfiguration = new CorsConfiguration();
+// corsConfiguration.setAllowedOrigins(
+// List.of(
+// "https://playbook.talentica.com/",
+// "https://orion.talentica.com/",
+// "https://prod-orion.talentica.com/",
+// "http://localhost:3000/",
+// "http://localhost/",
+// "https://stagingplaybook.talentica.com",
+// "https://dev-orion.talentica.com/",
+// "https://stagingorion.talentica.com",
+// "https://staging-orion.talentica.com/",
+// "http://localhost:3001/",
+// "https://stagingknowledgebase.talentica.com/",
+// "https://stagingknowledgebase-sales.talentica.com/",
+// "https://staging.kb.talentica.com/",
+// "https://stagingknowledgebase.talentica.com/",
+// "https://nexus.talentica.com/",
+// "https://kb.talentica.com/"));
+// corsConfiguration.addExposedHeader("Set-Cookie");
+// corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "PUT", "DELETE"));
+// // setAllowCredentials(true) is important, otherwise:
+// // The value of the 'Access-Control-Allow-Origin' header in the response must not be the
+// // wildcard '*' when the request's credentials mode is 'include'.
+// // setAllowedHeaders is important! Without it, OPTIONS preflight request
+// // will fail with 403 Invalid CORS request
+// corsConfiguration.setAllowedHeaders(
+// List.of(
+// "Api-Key",
+// "Authorization",
+// "Cache-Control",
+// "Content-Type",
+// "Access-Control-Allow-Origin",
+// "Access-Control-Allow-Credentials"));
+// corsConfiguration.setAllowCredentials(true);
+//
+// final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+// source.registerCorsConfiguration("/**", corsConfiguration);
+// return source;
+// }
+//
+// public void updateCorsConfiguration() {
+// List origins = allowedDomainRepository.findAll()
+// .stream().map(AllowedDomain::getDomainName).toList();
+// configuration.setAllowedOrigins(origins);
+// }
+//}
diff --git a/src/main/java/com/openAi/security/controller/AuthController.java b/src/main/java/com/openAi/security/controller/AuthController.java
new file mode 100644
index 0000000..fe07fe9
--- /dev/null
+++ b/src/main/java/com/openAi/security/controller/AuthController.java
@@ -0,0 +1,242 @@
+package com.openAi.security.controller;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.openAi.security.exceptions.CustomRuntimeException;
+import com.openAi.security.model.JwtRequest;
+import com.openAi.security.model.UserRequest;
+import com.openAi.security.model.WebClientResponse;
+import com.openAi.security.repository.CustomerCredentialRepository;
+import com.openAi.security.entity.CustomerCredentials;
+import com.openAi.security.service.UserService;
+import com.openAi.security.utils.JwtUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseCookie;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+@Slf4j
+@RestController
+@RequiredArgsConstructor
+public class AuthController {
+
+ private static final String ERROR_DUE_TO_INVALID_EMAIL = "Bad/Unauthorised Request error due to Invalid email";
+ private static final String COOKIE = "Set-Cookie";
+ private static final String BEARER = "Bearer ";
+ private final JwtUtils jwtUtils;
+ private final HttpServletResponse httpServletResponse;
+ private final HttpServletRequest httpServletRequest;
+ private final UserService userService;
+ private final CustomerCredentialRepository customerCredentialRepository;
+
+ @Value("${security.jwtExpirationMs}")
+ private Long jwtExpirationMs;
+ private final PasswordEncoder passwordEncoder;
+
+ @PostMapping("/getTokenUserAuth")
+ public ResponseEntity authenticateCustomer(@RequestBody UserRequest userRequest){
+ String user = userRequest.getUser();
+ List credentialsList = customerCredentialRepository.findAllByUserNameOrUserEmail(user,user);
+ if(credentialsList.isEmpty()){
+ log.error(ERROR_DUE_TO_INVALID_EMAIL);
+ return ResponseEntity.status(HttpStatus.NON_AUTHORITATIVE_INFORMATION).body(WebClientResponse.builder()
+ .reason("Incorrect Username")
+ .build());
+ }
+ CustomerCredentials customerCredentials = credentialsList.get(0);
+ if(!passwordEncoder.matches(userRequest.getPassword(),customerCredentials.getPassword())){
+ return ResponseEntity.status(HttpStatus.NON_AUTHORITATIVE_INFORMATION).body(WebClientResponse.builder()
+ .reason("Incorrect Password")
+ .build());
+ }
+
+ else{
+ String jwt = jwtUtils.getJWTToken(customerCredentials.getUserEmail());
+ userService.saveUserLog(customerCredentials.getUserEmail());
+
+
+ var cookie = getAuthCookie(jwt);
+ httpServletResponse.addHeader(COOKIE, cookie.toString());
+
+ customerCredentials.setLoginCount(Optional.ofNullable(customerCredentials.getLoginCount()).orElse(0) + 1);
+ customerCredentialRepository.save(customerCredentials);
+
+ return ResponseEntity.ok(WebClientResponse.builder()
+ .givenName(customerCredentials.getUserName())
+ .displayName(customerCredentials.getUserName())
+ .mail(customerCredentials.getUserEmail())
+ .isResetRequired(!customerCredentials.getIsReset())
+ .token(BEARER + jwt).build());
+ }
+ }
+
+ @PostMapping("/resetPassword")
+ public ResponseEntity resetPassword(@RequestBody UserRequest userRequest){
+ String user = userRequest.getUser();
+ List credentialsList = customerCredentialRepository.findAllByUserNameOrUserEmail(user,user);
+ if(credentialsList.isEmpty()){
+ log.error(ERROR_DUE_TO_INVALID_EMAIL);
+ return ResponseEntity.status(HttpStatus.NON_AUTHORITATIVE_INFORMATION).body(WebClientResponse.builder()
+ .reason("Incorrect Username")
+ .build());
+ }
+ String actualPwd = credentialsList.get(0).getPassword();
+ String password = userRequest.getOldPassword();
+
+ if(!passwordEncoder.matches(password,actualPwd)){
+ return ResponseEntity.status(HttpStatus.NON_AUTHORITATIVE_INFORMATION).body(WebClientResponse.builder()
+ .reason("Incorrect Password")
+ .build());
+ }
+
+ if(userRequest.getPassword().isBlank()){
+ return ResponseEntity.status(HttpStatus.NON_AUTHORITATIVE_INFORMATION).body(WebClientResponse.builder()
+ .reason("Enter New Password")
+ .build());
+ }
+
+ credentialsList.get(0).setPassword(passwordEncoder.encode(userRequest.getPassword()));
+ credentialsList.get(0).setPwdGeneratedDate(new Date());
+ credentialsList.get(0).setIsReset(true);
+
+ customerCredentialRepository.save(credentialsList.get(0));
+
+ String jwt = jwtUtils.getJWTToken(credentialsList.get(0).getUserEmail());
+ userService.saveUserLog(credentialsList.get(0).getUserEmail());
+
+ if(Boolean.TRUE.equals(credentialsList.get(0).getIsReset())) {
+ var cookie = getAuthCookie(jwt);
+ httpServletResponse.addHeader(COOKIE, cookie.toString());
+ }
+
+ return ResponseEntity.ok(WebClientResponse.builder()
+ .givenName(credentialsList.get(0).getUserName())
+ .displayName(credentialsList.get(0).getUserName())
+ .mail(credentialsList.get(0).getUserEmail())
+ .isResetRequired(!credentialsList.get(0).getIsReset())
+ .token(BEARER + jwt).build());
+ }
+
+ @GetMapping("/initialLogin")
+ public ResponseEntity ifInitialLogin(@RequestParam String email) {
+ List credentialsList = customerCredentialRepository.findAllByUserEmail(email);
+ if(credentialsList.isEmpty()){
+ throw new IllegalArgumentException(ERROR_DUE_TO_INVALID_EMAIL);
+ }
+ return ResponseEntity.ok(credentialsList.get(0).getLoginCount() == 1);
+ }
+
+ @PostMapping("/getTokenGoogleAuth")
+ public ResponseEntity authenticateGoogleUser(@RequestBody JwtRequest jwtRequest) {
+ WebClient client = WebClient.create();
+ JsonNode response = client.get()
+ .uri("https://www.googleapis.com/oauth2/v3/userinfo")
+ .headers(headers -> {
+ headers.setBearerAuth(jwtRequest.getToken());
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ })
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
+
+ log.info(
+ "Profile successfully validated from google against user {}",
+ Objects.requireNonNull(response).get("email").asText());
+
+ String mail = response.get("email").asText();
+ if (mail == null) {
+ log.error(ERROR_DUE_TO_INVALID_EMAIL);
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
+ }
+
+ String jwt = jwtUtils.getJWTToken(mail);
+
+ log.info("JWT token fetched successfully for valid email: {}", mail);
+
+ userService.saveUserLog(mail);
+
+ var cookie = getAuthCookie(jwt);
+ httpServletResponse.addHeader(COOKIE, cookie.toString());
+
+ return ResponseEntity.ok(WebClientResponse.builder()
+ .id(response.get("sub").asText())
+ .givenName(response.get("given_name").asText())
+ .displayName(response.get("name").asText())
+ .mail(mail)
+ .token(BEARER + jwt).build());
+ }
+
+ @PostMapping("/getToken")
+ public ResponseEntity authenticateUser(@RequestBody JwtRequest jwtRequest) {
+ WebClient client = WebClient.create();
+ WebClientResponse response =
+ client
+ .get()
+ .uri("https://graph.microsoft.com/v1.0/me")
+ .headers(
+ headers -> {
+ headers.setBearerAuth(jwtRequest.getToken());
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ })
+ .retrieve()
+ .bodyToMono(WebClientResponse.class)
+ .block();
+ log.info(
+ "Me profile successfully validated from microsoft against user {}",
+ Objects.requireNonNull(response).getMail());
+
+ String mail = response.getMail();
+ if (StringUtils.isEmpty(response.getMail())) {
+ log.error(ERROR_DUE_TO_INVALID_EMAIL);
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
+ }
+
+ String jwt = jwtUtils.getJWTToken(mail);
+ response.setToken(BEARER + jwt);
+ log.info("JWT token fetched successfully for valid email: {}", response.getMail());
+
+ userService.saveUserLog(mail);
+
+
+ var cookie = getAuthCookie(jwt);
+ httpServletResponse.addHeader(COOKIE, cookie.toString());
+
+ return ResponseEntity.ok(response);
+ }
+
+ private ResponseCookie getAuthCookie(String authToken) {
+ URL url = null;
+ try {
+ url = new URL(httpServletRequest.getRequestURL().toString());
+ } catch (MalformedURLException e) {
+ throw new CustomRuntimeException(e.getMessage());
+ }
+ final String cookieName = "auth-token";
+ final int expiryTime = Math.toIntExact(jwtExpirationMs / 1000); // millis in seconds
+ return ResponseCookie
+ .from(cookieName,authToken)
+ .secure(true)
+ .httpOnly(false)
+ .path("/")
+ .maxAge(expiryTime)
+ .domain(url.getHost().equalsIgnoreCase("localhost")?"localhost":".talentica.com")
+ .sameSite("None")
+ .build();
+
+ }
+}
diff --git a/src/main/java/com/openAi/security/controller/UserController.java b/src/main/java/com/openAi/security/controller/UserController.java
new file mode 100644
index 0000000..913fcf0
--- /dev/null
+++ b/src/main/java/com/openAi/security/controller/UserController.java
@@ -0,0 +1,121 @@
+package com.openAi.security.controller;
+
+import com.openAi.security.entity.Roles;
+import com.openAi.security.entity.User;
+import com.openAi.security.enums.AppConstant;
+import com.openAi.security.enums.EntityStatus;
+import com.openAi.security.enums.UserRole;
+import com.openAi.security.mapper.UserMapper;
+import com.openAi.security.mapper.UserTeamRolesMapper;
+import com.openAi.security.model.UserListViewResponse;
+import com.openAi.security.model.UserModel;
+import com.openAi.security.service.UserService;
+import com.openAi.security.service.UserTeamRoleService;
+import com.openAi.security.utils.SessionUtils;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.mapstruct.factory.Mappers;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+@Slf4j
+@RestController
+@RequestMapping("/user")
+@RequiredArgsConstructor
+public class UserController {
+
+ UserMapper userMapper = Mappers.getMapper(UserMapper.class);
+ UserTeamRolesMapper userTeamRolesMapper = Mappers.getMapper(UserTeamRolesMapper.class);
+ private final UserService userService;
+ private final SessionUtils sessionUtils;
+ private final UserTeamRoleService userTeamRoleService;
+
+ @GetMapping("/loggedInUser")
+ public ResponseEntity getLoggedInUser() {
+ return ResponseEntity.status(HttpStatus.OK).body(sessionUtils.getLoggedInUser());
+ }
+
+ @GetMapping
+ public ResponseEntity getUser(@RequestParam String email) {
+ if (StringUtils.isEmpty(email)) {
+ log.error("Invalid email address.");
+ throw new IllegalArgumentException("Invalid email address");
+ }
+ UserModel userModel = userService.findUserByEmailOrAttendance(email);
+ return ResponseEntity.status(HttpStatus.OK).body(userModel);
+ }
+
+ @GetMapping("/roles")
+ public ResponseEntity> getRoles() {
+ List roles = userService.getRoles();
+ return ResponseEntity.status(HttpStatus.OK).body(roles);
+ }
+
+ @GetMapping("all")
+ public ResponseEntity getAllUser(
+ @RequestParam(value = "role", required = false) UserRole role,
+ @RequestParam(value = "status", required = false) EntityStatus status,
+ @RequestParam(value = "name", required = false) String name,
+ @RequestParam(value = "email", required = false) String email,
+ @RequestParam(value = "teamName", required = false) String teamName,
+ @RequestParam(value = "isTeg", required = false) Boolean isTeg,
+ @RequestParam(value = "orderBy", defaultValue = "id", required = false) String orderBy,
+ @RequestParam(value = "direction", defaultValue = "DESC", required = false)
+ Sort.Direction direction,
+ @RequestParam(value = "page", defaultValue = AppConstant.DEFAULT_PAGE, required = false)
+ int page,
+ @RequestParam(value = "size", defaultValue = AppConstant.DEFAULT_PAGE_SIZE, required = false)
+ int size,
+ @RequestParam(value = "searchField", required = false) String searchField) {
+ Sort sort =
+ orderBy.equalsIgnoreCase("id")
+ ? Sort.by(direction, orderBy)
+ : Sort.by(direction, orderBy).and(Sort.by(Sort.Direction.ASC, "id"));
+ Pageable paging = PageRequest.of(page, size, sort);
+ Specification userSpecification = Specification.where(null);
+
+ if (Arrays.asList(UserRole.values()).contains(role)) {
+ userSpecification = userSpecification.and(User.roleSpec(role));
+ }
+ if (Objects.nonNull(status)) {
+ userSpecification = userSpecification.and(User.statusSpec(status));
+ }
+ if (Objects.nonNull(name)) {
+ userSpecification = userSpecification.and(User.nameSpec(name));
+ }
+ if (Objects.nonNull(email)) {
+ userSpecification = userSpecification.and(User.emailSpec(email));
+ }
+ if (Objects.nonNull(teamName)) {
+ userSpecification = userSpecification.and(User.teamSpec(teamName));
+ }
+ if (Objects.nonNull(isTeg)) {
+ userSpecification = userSpecification.and(User.isTegSpec(isTeg));
+ }
+ if (StringUtils.isNotBlank(searchField)) {
+ userSpecification = userSpecification.and(User.userSearchFieldSpec(searchField));
+ }
+ userSpecification = userSpecification.and(User.distinct());
+ UserListViewResponse userListViewResponse = userService.findAllUsers(userSpecification, paging);
+ return ResponseEntity.status(HttpStatus.OK).body(userListViewResponse);
+ }
+
+ @GetMapping("/manager-list")
+ public ResponseEntity> getSeniorManagers(@RequestParam(required = true) String role) {
+ UserRole userRole = UserRole.valueOf(role);
+ return ResponseEntity.ok(userTeamRoleService.getUsersByRole(userRole));
+ }
+}
diff --git a/src/main/java/com/openAi/security/entity/AllowedDomain.java b/src/main/java/com/openAi/security/entity/AllowedDomain.java
new file mode 100644
index 0000000..1c8be4e
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/AllowedDomain.java
@@ -0,0 +1,41 @@
+package com.openAi.security.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import jakarta.persistence.*;
+import java.time.LocalDate;
+
+@Entity
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "allowed_domain")
+public class AllowedDomain {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ private Integer id;
+
+ @Column(name = "domain_name")
+ private String domainName;
+
+ @Column(name = "customer_id")
+ private Integer customerId;
+
+ @Column(name = "team_ids")
+ private String teamIds;
+
+ @Column(name = "is_on_boarded")
+ private Boolean isOnBoarded;
+
+ @Column(name = "on_boarded_date")
+ private LocalDate onBoardedDate;
+
+ @Column(name = "data_from")
+ private LocalDate dataFrom;
+}
diff --git a/src/main/java/com/openAi/security/entity/Attendance.java b/src/main/java/com/openAi/security/entity/Attendance.java
new file mode 100644
index 0000000..01bbe4c
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/Attendance.java
@@ -0,0 +1,79 @@
+package com.openAi.security.entity;
+
+import lombok.*;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import java.util.Date;
+
+@Entity
+@Data
+@Table(name = "attendance")
+public class Attendance {
+
+ @Id
+ @Column(name = "id")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Integer id;
+
+ private String employeeCode;
+
+ private String employeeName;
+
+ private String firstName;
+
+ private String lastName;
+
+ private String projectName;
+
+ private String employeeGrade;
+
+ private String reportingManager;
+
+ private String emailId;
+
+ private Integer presentDays;
+
+ private Integer year;
+
+ private Integer month;
+
+ private Date assignmentStartDate;
+
+ private Date assignmentEndDate;
+
+ private Date dateOfJoining;
+
+ private String employeeFunction;
+
+ private Integer billingPercentage;
+
+ private String businessUnit;
+
+ public Attendance(Attendance att) {
+ this.id = att.id;
+ this.employeeCode = att.employeeCode;
+ this.employeeName = att.employeeName;
+ this.firstName = att.firstName;
+ this.lastName = att.lastName;
+ this.projectName = att.projectName;
+ this.employeeGrade = att.employeeGrade;
+ this.reportingManager = att.reportingManager;
+ this.emailId = att.emailId;
+ this.presentDays = att.presentDays;
+ this.year = att.year;
+ this.month = att.month;
+ this.assignmentStartDate = att.assignmentStartDate;
+ this.assignmentEndDate = att.assignmentEndDate;
+ this.employeeFunction = att.employeeFunction;
+ this.billingPercentage = att.billingPercentage;
+ this.businessUnit = att.businessUnit;
+ this.dateOfJoining = att.dateOfJoining;
+
+ }
+
+}
diff --git a/src/main/java/com/openAi/security/entity/Customer.java b/src/main/java/com/openAi/security/entity/Customer.java
new file mode 100644
index 0000000..add4481
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/Customer.java
@@ -0,0 +1,54 @@
+package com.openAi.security.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.openAi.security.enums.EntityStatus;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import jakarta.persistence.*;
+import java.time.LocalDate;
+import java.util.List;
+
+@Entity
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+@Table(name = "customers")
+public class Customer {
+
+ @Id
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Integer id;
+
+ private String customerName;
+ private String projectName;
+
+ @Enumerated(EnumType.STRING)
+ private EntityStatus status = EntityStatus.ACTIVE;
+
+ private String currentStage;
+
+ private String engagementType;
+
+ @OneToMany(mappedBy = "customer", cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
+ @JsonIgnoreProperties("teamLeads")
+ private List teams;
+
+
+ @Column(columnDefinition = "DATE")
+ private LocalDate startDate;
+
+ @Column(columnDefinition = "DATE")
+ private LocalDate endDate;
+
+ private Boolean isCicero;
+
+ private Boolean isTeg;
+
+ private String link;
+
+}
diff --git a/src/main/java/com/openAi/security/entity/CustomerCredentials.java b/src/main/java/com/openAi/security/entity/CustomerCredentials.java
new file mode 100644
index 0000000..88e107f
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/CustomerCredentials.java
@@ -0,0 +1,28 @@
+package com.openAi.security.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import jakarta.persistence.*;
+import java.util.Date;
+
+@Entity
+@Getter
+@Setter
+@Accessors(chain = true)
+@Table(name = "customer_credentials")
+public class CustomerCredentials {
+ @Id
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+
+ private String userName;
+ private String userEmail;
+ private String password;
+ private Boolean isReset;
+ private Date pwdGeneratedDate;
+ private Integer loginCount;
+ private Boolean tourClosed;
+}
diff --git a/src/main/java/com/openAi/security/entity/Roles.java b/src/main/java/com/openAi/security/entity/Roles.java
new file mode 100644
index 0000000..e303a13
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/Roles.java
@@ -0,0 +1,24 @@
+package com.openAi.security.entity;
+
+import com.openAi.security.enums.UserRole;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import jakarta.persistence.*;
+
+@Entity
+@Getter
+@Setter
+@Accessors(chain = true)
+public class Roles {
+ @Id
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+
+ @Enumerated(EnumType.STRING)
+ private UserRole role = UserRole.LEAD;
+
+ private float priority;
+}
diff --git a/src/main/java/com/openAi/security/entity/Team.java b/src/main/java/com/openAi/security/entity/Team.java
new file mode 100644
index 0000000..85a0910
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/Team.java
@@ -0,0 +1,144 @@
+package com.openAi.security.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.openAi.security.enums.EntityStatus;
+import com.openAi.security.enums.TeamType;
+import lombok.*;
+import lombok.experimental.Accessors;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.jpa.domain.Specification;
+
+import jakarta.persistence.*;
+import jakarta.persistence.criteria.JoinType;
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * Team Entity.
+ */
+@Entity
+@Getter
+@Setter
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = true)
+public class Team {
+
+ @Id
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Integer id;
+
+ private String teamName;
+
+ private String teamShortName;
+
+ private String teamJiraName;
+
+ private String teamJiraLink;
+
+ @Enumerated(EnumType.STRING)
+ private TeamType teamType;
+
+ private Double noOfHoursPerSP;
+
+ @ManyToMany(fetch = FetchType.LAZY)
+ @JsonIgnoreProperties("teams")
+ @JoinTable(
+ name = "user_teams",
+ joinColumns = @JoinColumn(name = "teams_id", referencedColumnName = "id"),
+ inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"))
+ private List teamLeads;
+
+ @Column(columnDefinition = "DATE")
+ private LocalDate activeSince;
+
+ @Column(columnDefinition = "DATE")
+ private LocalDate endDate;
+
+ @Enumerated(EnumType.STRING)
+ private EntityStatus status = EntityStatus.ACTIVE;
+
+ private Boolean isTeg;
+ private Boolean excludeCompliance;
+
+ private Boolean complianceByStory;
+
+ @JsonIgnore
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "customer_id")
+ @JsonIgnoreProperties("teams")
+ private Customer customer;
+
+ private String doneStatuses;
+
+ private String onTimeIssueTypes;
+/*
+ public static Specification idSpec(int id) {
+ return (team, criteriaQuery, criteriaBuilder) -> criteriaBuilder.equal(team.get("id"), id);
+ }
+
+ public static Specification statusSpec(EntityStatus status) {
+ return (team, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.equal((team.get("status")), status);
+ }
+
+ public static Specification teamTypeSpec(TeamType teamType) {
+ return (team, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.equal((team.get("teamType")), teamType);
+ }
+
+ public static Specification teamNameSpec(String teamName) {
+ return (team, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.like(team.get("teamName"), "%" + teamName + "%");
+ }
+
+ public static Specification teamLeadNameSpec(String teamLeadName) {
+ return (team, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.like(
+ team.join("teamLeads", JoinType.LEFT).get("name"), "%" + teamLeadName + "%");
+ }
+
+ public static Specification teamLeadEmailSpec(String teamLeadEmail) {
+ return (team, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.like(
+ team.join("teamLeads", JoinType.LEFT).get("email"), "%" + teamLeadEmail + "%");
+ }
+
+ public static Specification isTegSpec(Boolean isTeg) {
+ return (team, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.equal((team.get("isTeg")), isTeg);
+ }
+
+ public static Specification distinct() {
+ return (root, query, cb) -> {
+ query.distinct(true);
+ return null;
+ };
+ }
+
+ public static Specification teamSearchFieldSpec(String searchField) {
+ Specification teamSpecification = Specification.where(null);
+ if (StringUtils.isNumeric(searchField)) {
+ int id = Integer.parseInt(searchField);
+ teamSpecification = teamSpecification.or(Team.idSpec(id));
+ }
+ try {
+ var entityStatus = EntityStatus.valueOf(searchField.toUpperCase());
+ teamSpecification = teamSpecification.or(Team.statusSpec(entityStatus));
+ } catch (IllegalArgumentException e) {
+ // Not Entity Status
+ }
+ try {
+ var teamType = TeamType.valueOf(searchField.toUpperCase());
+ teamSpecification = teamSpecification.or(Team.teamTypeSpec(teamType));
+ } catch (IllegalArgumentException e) {
+ // Not Team Type
+ }
+ teamSpecification =
+ teamSpecification.or(Team.teamLeadNameSpec(searchField)).or(Team.teamNameSpec(searchField));
+ return teamSpecification;
+ }*/
+}
diff --git a/src/main/java/com/openAi/security/entity/User.java b/src/main/java/com/openAi/security/entity/User.java
new file mode 100644
index 0000000..c3a1b3b
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/User.java
@@ -0,0 +1,121 @@
+package com.openAi.security.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.openAi.security.entity.Team;
+import com.openAi.security.entity.UserTeamRoles;
+import com.openAi.security.enums.EntityStatus;
+import com.openAi.security.enums.UserRole;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.jpa.domain.Specification;
+
+import jakarta.persistence.*;
+import jakarta.persistence.criteria.JoinType;
+import java.util.List;
+
+/**
+ * User Entity.
+ */
+@Entity
+@Getter
+@Setter
+@Accessors(chain = true)
+public class User {
+
+ @Id
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+
+ private String name;
+
+ @Enumerated(EnumType.STRING)
+ private UserRole role = UserRole.LEAD;
+
+ @JsonIgnoreProperties("user")
+ @OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
+ private List userTeamRoles;
+
+ private String email;
+ private Boolean isTeg;
+
+ @ManyToMany(fetch = FetchType.LAZY)
+ @JoinTable(
+ name = "user_teams",
+ joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
+ inverseJoinColumns = @JoinColumn(name = "teams_id", referencedColumnName = "id"))
+ @JsonIgnoreProperties("teamLeads")
+ private List teams;
+
+ @Enumerated(EnumType.STRING)
+ private EntityStatus status = EntityStatus.ACTIVE;
+
+
+ public static Specification idSpec(int id) {
+ return (user, criteriaQuery, criteriaBuilder) -> criteriaBuilder.equal(user.get("id"), id);
+ }
+
+ public static Specification nameSpec(String name) {
+ return (user, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.like(user.get("name"), "%" + name + "%");
+ }
+
+ public static Specification emailSpec(String email) {
+ return (user, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.like(user.get("email"), "%" + email + "%");
+ }
+
+ public static Specification roleSpec(UserRole role) {
+ return (user, criteriaQuery, criteriaBuilder) -> criteriaBuilder.equal(user.get("role"), role);
+ }
+
+ public static Specification teamSpec(String teamName) {
+ return (user, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.like(
+ user.join("teams", JoinType.LEFT).get("teamName"), "%" + teamName + "%");
+ }
+
+ public static Specification statusSpec(EntityStatus status) {
+ return (user, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.equal(user.get("status"), status);
+ }
+
+ public static Specification isTegSpec(Boolean isTeg) {
+ return (user, criteriaQuery, criteriaBuilder) ->
+ criteriaBuilder.equal((user.get("isTeg")), isTeg);
+ }
+
+ public static Specification distinct() {
+ return (root, query, cb) -> {
+ query.distinct(true);
+ return null;
+ };
+ }
+
+ public static Specification userSearchFieldSpec(String searchField) {
+ Specification userSpecification = Specification.where(null);
+ if (StringUtils.isNumeric(searchField)) {
+ int id = Integer.parseInt(searchField);
+ userSpecification = userSpecification.or(User.idSpec(id));
+ }
+ try {
+ var entityStatus = EntityStatus.valueOf(searchField.toUpperCase());
+ userSpecification = userSpecification.or(User.statusSpec(entityStatus));
+ } catch (IllegalArgumentException e) {
+ // Not Entity Status
+ }
+ try {
+ var userRole = UserRole.valueOf(searchField.toUpperCase());
+ userSpecification = userSpecification.or(User.roleSpec(userRole));
+ } catch (IllegalArgumentException e) {
+ // Not User Role
+ }
+ userSpecification =
+ userSpecification
+ .or(User.nameSpec(searchField).or(User.emailSpec(searchField)))
+ .or(User.teamSpec(searchField));
+ return userSpecification;
+ }
+}
diff --git a/src/main/java/com/openAi/security/entity/UserLog.java b/src/main/java/com/openAi/security/entity/UserLog.java
new file mode 100644
index 0000000..5ad917c
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/UserLog.java
@@ -0,0 +1,26 @@
+package com.openAi.security.entity;
+
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import jakarta.persistence.*;
+import java.util.Date;
+
+@Entity
+@Getter
+@Setter
+@Builder
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "user_log")
+public class UserLog {
+ @Id
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+
+ private Integer userId;
+
+ private Date logInDate;
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/security/entity/UserTeamRoles.java b/src/main/java/com/openAi/security/entity/UserTeamRoles.java
new file mode 100644
index 0000000..acbf950
--- /dev/null
+++ b/src/main/java/com/openAi/security/entity/UserTeamRoles.java
@@ -0,0 +1,36 @@
+package com.openAi.security.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import jakarta.persistence.*;
+
+@Entity
+@Getter
+@Setter
+@Accessors(chain = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "user_team_roles")
+public class UserTeamRoles{
+
+ @Id
+ @Column(columnDefinition = "INT(11) UNSIGNED")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "user_id", referencedColumnName = "id")
+ private User user;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "role_id")
+ private Roles userRole;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "team_id")
+ @JsonIgnoreProperties(value = {"teamLeads"}, allowSetters = true)
+ private Team team;
+}
diff --git a/src/main/java/com/openAi/security/enums/AppConstant.java b/src/main/java/com/openAi/security/enums/AppConstant.java
new file mode 100644
index 0000000..fc6193c
--- /dev/null
+++ b/src/main/java/com/openAi/security/enums/AppConstant.java
@@ -0,0 +1,8 @@
+package com.openAi.security.enums;
+
+public class AppConstant {
+ private AppConstant(){}
+ public static final String DEFAULT_PAGE = "0";
+ public static final String DEFAULT_PAGE_SIZE = "10";
+ public static final String DEFAULT_PAGE_SIZE_PRODUCT_ROADMAP = "50";
+}
diff --git a/src/main/java/com/openAi/security/enums/EntityStatus.java b/src/main/java/com/openAi/security/enums/EntityStatus.java
new file mode 100644
index 0000000..7d8ae22
--- /dev/null
+++ b/src/main/java/com/openAi/security/enums/EntityStatus.java
@@ -0,0 +1,14 @@
+package com.openAi.security.enums;
+
+import lombok.Getter;
+
+public enum EntityStatus {
+ INACTIVE(0),
+ ACTIVE(1);
+
+ @Getter private final int value;
+
+ EntityStatus(int value) {
+ this.value = value;
+ }
+}
diff --git a/src/main/java/com/openAi/security/enums/TeamType.java b/src/main/java/com/openAi/security/enums/TeamType.java
new file mode 100644
index 0000000..31acc17
--- /dev/null
+++ b/src/main/java/com/openAi/security/enums/TeamType.java
@@ -0,0 +1,27 @@
+package com.openAi.security.enums;
+
+import java.util.EnumMap;
+import java.util.List;
+
+/** TeamType consisting multiple team types. */
+public enum TeamType {
+ BIG_TECH,
+ EARLY,
+ GROWTH,
+ PROFITABLE;
+ private static final EnumMap> CORRESPONDING_TYPES =
+ new EnumMap<>(TeamType.class);
+
+ static {
+ CORRESPONDING_TYPES.put(BIG_TECH, List.of(BIG_TECH));
+ CORRESPONDING_TYPES.put(EARLY, List.of(EARLY));
+ CORRESPONDING_TYPES.put(GROWTH, List.of(GROWTH));
+ CORRESPONDING_TYPES.put(PROFITABLE, List.of(PROFITABLE));
+ }
+
+ public static List getCorrespondingTypeList(TeamType teamType) {
+ return CORRESPONDING_TYPES.get(teamType);
+ }
+
+
+}
diff --git a/src/main/java/com/openAi/security/enums/UserRole.java b/src/main/java/com/openAi/security/enums/UserRole.java
new file mode 100644
index 0000000..a24cb91
--- /dev/null
+++ b/src/main/java/com/openAi/security/enums/UserRole.java
@@ -0,0 +1,35 @@
+package com.openAi.security.enums;
+
+import lombok.Getter;
+
+public enum UserRole {
+ ADMIN(0),
+ MANAGER(1),
+ LEAD(2),
+ M4(3),
+ CSO(4),
+ RO(5),
+ TO(6),
+ I3(7),
+ I2(8),
+ I1(9),
+ WATCHER(10),
+ PEOPLE_GROUP(11),
+ M1(12),
+ M2(13),
+ I4(14),
+ A1(15),
+ A2(16),
+ A3(17),
+ M3(18),
+ CUSTOMER(19),
+ E1(20),
+ E2(21);
+
+ @Getter
+ private final int value;
+
+ UserRole(int value) {
+ this.value = value;
+ }
+}
diff --git a/src/main/java/com/openAi/security/exceptions/CustomRuntimeException.java b/src/main/java/com/openAi/security/exceptions/CustomRuntimeException.java
new file mode 100644
index 0000000..69221dc
--- /dev/null
+++ b/src/main/java/com/openAi/security/exceptions/CustomRuntimeException.java
@@ -0,0 +1,12 @@
+package com.openAi.security.exceptions;
+
+public class CustomRuntimeException extends RuntimeException {
+ public CustomRuntimeException(String message) {
+ super(message);
+ }
+
+ public CustomRuntimeException(String message,Exception e) {
+ super(message+ "::" +e.getMessage());
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/security/exceptions/EntityNotFoundException.java b/src/main/java/com/openAi/security/exceptions/EntityNotFoundException.java
new file mode 100644
index 0000000..105d56a
--- /dev/null
+++ b/src/main/java/com/openAi/security/exceptions/EntityNotFoundException.java
@@ -0,0 +1,51 @@
+package com.openAi.security.exceptions;
+
+
+import static com.openAi.security.exceptions.ErrorCode.*;
+
+/**
+ * EntityNotFoundException.
+ */
+public class EntityNotFoundException extends RAGException {
+
+ private EntityNotFoundException(String message, Integer code) {
+ super(message);
+ setCode(code);
+ }
+
+ public static EntityNotFoundException user(String message) {
+ return new EntityNotFoundException(message, USER_NOT_FOUND);
+ }
+
+ public static EntityNotFoundException team(String message) {
+ return new EntityNotFoundException(message, TEAM_NOT_FOUND);
+ }
+
+ public static EntityNotFoundException cycleConfig(String message) {
+ return new EntityNotFoundException(message, CYCLE_CONFIG_NOT_FOUND);
+ }
+
+ public static EntityNotFoundException survey(String message) {
+ return new EntityNotFoundException(message, SURVEY_NOT_FOUND);
+ }
+
+ public static EntityNotFoundException customer(String message) {
+ return new EntityNotFoundException(message, CUSTOMER_NOT_FOUND);
+ }
+
+ public static EntityNotFoundException section(String message) {
+ return new EntityNotFoundException(message, SECTION_NOT_FOUND);
+ }
+
+ public static EntityNotFoundException employee(String message) {
+ return new EntityNotFoundException(message, EMPLOYEE_NOT_FOUND);
+ }
+
+ public static EntityNotFoundException dataForEmployee(String message) {
+ return new EntityNotFoundException(message, NO_DATA_FOUND_FOR_EMPLOYEE);
+ }
+
+ public static RuntimeException techDigest(String s) {
+ return new EntityNotFoundException(s,TECH_DIGEST_NOT_FOUND);
+ }
+}
diff --git a/src/main/java/com/openAi/security/exceptions/ErrorCode.java b/src/main/java/com/openAi/security/exceptions/ErrorCode.java
new file mode 100644
index 0000000..96b852a
--- /dev/null
+++ b/src/main/java/com/openAi/security/exceptions/ErrorCode.java
@@ -0,0 +1,65 @@
+package com.openAi.security.exceptions;
+
+public class ErrorCode {
+
+ public static final Integer INTERNAL_SERVER_ERROR = 500;
+ public static final Integer NULL_POINTER_EXCEPTION = 500;
+ public static final Integer INVALID_ACCESS = 401;
+
+ // Authentication and Authorization
+ public static final Integer INVALID_TOKEN = 1;
+ public static final Integer UNAUTHORISED_USER = 2;
+
+ // User
+ public static final Integer USER_NOT_FOUND = 11;
+
+ // Team
+ public static final Integer TEAM_NOT_FOUND = 21;
+
+ // ConfigCycle
+ public static final Integer CYCLE_EXPIRED = 31;
+ public static final Integer CYCLE_CONFIG_NOT_FOUND = 32;
+
+ // Survey
+ public static final Integer SURVEY_NOT_FOUND = 41;
+ public static final Integer NOT_ENOUGH_SURVEY = 42;
+
+ // File
+ public static final Integer INVALID_FILE_EXTENSION = 51;
+ public static final Integer INVALID_FILE_FORMAT = 52;
+
+ // Csat
+ public static final Integer NOT_ENOUGH_SURVEYS = 61;
+ public static final Integer CATEGORY_NOT_FOUND = 62;
+ public static final Integer QUESTION_NOT_FOUND = 63;
+ public static final Integer SUB_QUESTION_NOT_FOUND = 64;
+ public static final Integer SURVEY_ALREADY_EXISTS = 65;
+ public static final Integer PLACEHOLDER_NOT_FOUND = 66;
+
+ // Customer
+ public static final Integer CUSTOMER_NOT_FOUND = 71;
+
+ // Product Roadmap
+ public static final Integer EMPTY_STORY_NAME = 81;
+ public static final Integer INVALID_END_DATE = 82;
+ public static final Integer EMPTY_START_DATE = 83;
+ public static final Integer INCORRECT_DATA = 84;
+ public static final Integer NO_DATA_FOUND = 85;
+
+ // Http Connection
+ public static final Integer HTTP_CONNECTION_FAILED = 91;
+
+ // Section
+ public static final Integer SECTION_NOT_FOUND = 101;
+
+ // TouchPoint
+ public static final Integer INVALID_FILE = 1101;
+
+ // Teams
+ public static final Integer EMPLOYEE_NOT_FOUND = 1201;
+ public static final Integer NO_DATA_FOUND_FOR_EMPLOYEE = 1202;
+
+ public static final Integer TECH_DIGEST_NOT_FOUND = 1301;
+ private ErrorCode() {
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/security/exceptions/InvalidAuthenticationException.java b/src/main/java/com/openAi/security/exceptions/InvalidAuthenticationException.java
new file mode 100644
index 0000000..b8ab3ef
--- /dev/null
+++ b/src/main/java/com/openAi/security/exceptions/InvalidAuthenticationException.java
@@ -0,0 +1,20 @@
+package com.openAi.security.exceptions;
+
+import static com.openAi.security.exceptions.ErrorCode.INVALID_TOKEN;
+import static com.openAi.security.exceptions.ErrorCode.UNAUTHORISED_USER;
+
+public class InvalidAuthenticationException extends RAGException {
+
+ private InvalidAuthenticationException(String message, Integer code) {
+ super(message);
+ setCode(code);
+ }
+
+ public static InvalidAuthenticationException invalidToken(String message) {
+ return new InvalidAuthenticationException(message, INVALID_TOKEN);
+ }
+
+ public static InvalidAuthenticationException unauthorisedUser(String message) {
+ return new InvalidAuthenticationException(message, UNAUTHORISED_USER);
+ }
+}
diff --git a/src/main/java/com/openAi/security/exceptions/RAGException.java b/src/main/java/com/openAi/security/exceptions/RAGException.java
new file mode 100644
index 0000000..744ddc6
--- /dev/null
+++ b/src/main/java/com/openAi/security/exceptions/RAGException.java
@@ -0,0 +1,28 @@
+package com.openAi.security.exceptions;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+
+
+
+@Setter
+@Getter
+public abstract class RAGException extends RuntimeException {
+
+ private Integer code = ErrorCode.INTERNAL_SERVER_ERROR;
+
+ protected RAGException(String message) {
+ super(message);
+ }
+
+ protected RAGException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected RAGException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/src/main/java/com/openAi/security/mapper/UserMapper.java b/src/main/java/com/openAi/security/mapper/UserMapper.java
new file mode 100644
index 0000000..d7289b6
--- /dev/null
+++ b/src/main/java/com/openAi/security/mapper/UserMapper.java
@@ -0,0 +1,16 @@
+package com.openAi.security.mapper;
+
+
+import com.openAi.security.entity.User;
+import com.openAi.security.model.UserModel;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+/** Entity-Model mapper for User. */
+@Mapper
+public interface UserMapper {
+ @Mapping(source = "userTeamRoles", target = "teamRoles")
+ UserModel entityToModel(User user);
+
+ User modelToEntity(UserModel user);
+}
diff --git a/src/main/java/com/openAi/security/mapper/UserTeamRolesMapper.java b/src/main/java/com/openAi/security/mapper/UserTeamRolesMapper.java
new file mode 100644
index 0000000..604f41b
--- /dev/null
+++ b/src/main/java/com/openAi/security/mapper/UserTeamRolesMapper.java
@@ -0,0 +1,12 @@
+package com.openAi.security.mapper;
+
+import com.openAi.security.entity.UserTeamRoles;
+import com.openAi.security.model.UserTeamRolesModel;
+import org.mapstruct.Mapper;
+
+@Mapper
+public interface UserTeamRolesMapper {
+ UserTeamRolesModel entityToModel(UserTeamRoles userTeamRoles);
+
+ UserTeamRoles modelToEntity(UserTeamRolesModel userTeamRolesModel);
+}
diff --git a/src/main/java/com/openAi/security/model/JwtRequest.java b/src/main/java/com/openAi/security/model/JwtRequest.java
new file mode 100644
index 0000000..3d277be
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/JwtRequest.java
@@ -0,0 +1,10 @@
+package com.openAi.security.model;
+
+import lombok.Data;
+
+@Data
+public class JwtRequest {
+
+ private String token;
+ private String email;
+}
\ No newline at end of file
diff --git a/src/main/java/com/openAi/security/model/MonthValue.java b/src/main/java/com/openAi/security/model/MonthValue.java
new file mode 100644
index 0000000..aae7072
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/MonthValue.java
@@ -0,0 +1,10 @@
+package com.openAi.security.model;
+
+import lombok.Getter;
+
+public interface MonthValue {
+ String getMonth();
+ String getYear();
+ String getValue();
+
+}
diff --git a/src/main/java/com/openAi/security/model/TeamModel.java b/src/main/java/com/openAi/security/model/TeamModel.java
new file mode 100644
index 0000000..e3c50da
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/TeamModel.java
@@ -0,0 +1,43 @@
+package com.openAi.security.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.openAi.security.entity.Customer;
+import com.openAi.security.entity.User;
+import com.openAi.security.enums.EntityStatus;
+import com.openAi.security.enums.TeamType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TeamModel {
+
+ private Integer id;
+ private String teamName;
+ private TeamType teamType;
+ private LocalDate activeSince;
+ private LocalDate endDate;
+ private String teamShortName;
+ private String teamJiraName;
+ private Boolean isTeg;
+ private Boolean excludeCompliance;
+ private Boolean complianceByStory;
+
+ @JsonIgnoreProperties("teams")
+ private List teamLeads;
+
+ @JsonIgnoreProperties("team")
+ private List userRoles;
+
+ private EntityStatus status;
+
+ @JsonIgnoreProperties(value = {"epics", "customerUserRoles"}, allowSetters = true)
+ private Customer customer;
+}
diff --git a/src/main/java/com/openAi/security/model/UserListViewResponse.java b/src/main/java/com/openAi/security/model/UserListViewResponse.java
new file mode 100644
index 0000000..e68c288
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/UserListViewResponse.java
@@ -0,0 +1,23 @@
+package com.openAi.security.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** UserListViewResponse. */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class UserListViewResponse {
+
+ private List userListViews = new ArrayList<>();
+ private Long totalRecords;
+ private Integer totalPages;
+ private boolean hasNext = false;
+ private boolean hasPrevious = false;
+ private Integer page;
+ private Integer size;
+}
diff --git a/src/main/java/com/openAi/security/model/UserModel.java b/src/main/java/com/openAi/security/model/UserModel.java
new file mode 100644
index 0000000..43542bb
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/UserModel.java
@@ -0,0 +1,32 @@
+package com.openAi.security.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.openAi.security.entity.Customer;
+import com.openAi.security.enums.EntityStatus;
+import com.openAi.security.enums.UserRole;
+import lombok.*;
+
+import java.util.List;
+
+/**
+ * User Model.
+ */
+@Getter
+@Setter
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class UserModel {
+
+ private Integer id;
+ private String name;
+ private UserRole role;
+ private String email;
+ @JsonIgnoreProperties(value = {"teamLeads", "userTeamRoles"}, allowSetters = true)
+ private List teams;
+ private List teamRoles;
+ private boolean isCustomerRole;
+ private EntityStatus status;
+ private List customers;
+ private boolean isTeg;
+}
diff --git a/src/main/java/com/openAi/security/model/UserRequest.java b/src/main/java/com/openAi/security/model/UserRequest.java
new file mode 100644
index 0000000..e1433ef
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/UserRequest.java
@@ -0,0 +1,10 @@
+package com.openAi.security.model;
+
+import lombok.Data;
+
+@Data
+public class UserRequest {
+ private String user;
+ private String password;
+ private String oldPassword;
+}
diff --git a/src/main/java/com/openAi/security/model/UserRole.java b/src/main/java/com/openAi/security/model/UserRole.java
new file mode 100644
index 0000000..38fac0b
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/UserRole.java
@@ -0,0 +1,35 @@
+package com.openAi.security.model;
+
+import lombok.Getter;
+
+public enum UserRole {
+ ADMIN(0),
+ MANAGER(1),
+ LEAD(2),
+ M4(3),
+ CSO(4),
+ RO(5),
+ TO(6),
+ I3(7),
+ I2(8),
+ I1(9),
+ WATCHER(10),
+ PEOPLE_GROUP(11),
+ M1(12),
+ M2(13),
+ I4(14),
+ A1(15),
+ A2(16),
+ A3(17),
+ M3(18),
+ CUSTOMER(19),
+ E1(20),
+ E2(21);
+
+ @Getter
+ private final int value;
+
+ UserRole(int value) {
+ this.value = value;
+ }
+}
diff --git a/src/main/java/com/openAi/security/model/UserTeamRolesModel.java b/src/main/java/com/openAi/security/model/UserTeamRolesModel.java
new file mode 100644
index 0000000..dcfea87
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/UserTeamRolesModel.java
@@ -0,0 +1,23 @@
+package com.openAi.security.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.openAi.security.entity.Roles;
+import com.openAi.security.entity.Team;
+import com.openAi.security.entity.User;
+import lombok.*;
+
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UserTeamRolesModel {
+ private int id;
+ private User user;
+ private Roles userRole;
+
+ @JsonIgnoreProperties(
+ value = {"teamLeads"},
+ allowSetters = true)
+ private Team team;
+}
diff --git a/src/main/java/com/openAi/security/model/WebClientResponse.java b/src/main/java/com/openAi/security/model/WebClientResponse.java
new file mode 100644
index 0000000..15e2316
--- /dev/null
+++ b/src/main/java/com/openAi/security/model/WebClientResponse.java
@@ -0,0 +1,23 @@
+package com.openAi.security.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class WebClientResponse {
+ private String displayName;
+ private String givenName;
+ private String mail;
+ private String mobilePhone;
+ private String id;
+ private String userPrincipalName;
+ private String type = "Bearer";
+ private String token;
+ private Boolean isResetRequired;
+ private String reason;
+}
diff --git a/src/main/java/com/openAi/security/repository/AllowedDomainRepository.java b/src/main/java/com/openAi/security/repository/AllowedDomainRepository.java
new file mode 100644
index 0000000..1c7b2e6
--- /dev/null
+++ b/src/main/java/com/openAi/security/repository/AllowedDomainRepository.java
@@ -0,0 +1,17 @@
+package com.openAi.security.repository;
+
+import com.drew.lang.annotations.NotNull;
+import com.openAi.security.entity.AllowedDomain;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface AllowedDomainRepository extends JpaRepository {
+
+ @NotNull
+ List findAll();
+ @NotNull List findAllByDomainName(String domainName);
+ List findByTeamIdsContains(String teamId);
+}
diff --git a/src/main/java/com/openAi/security/repository/AttendanceRepository.java b/src/main/java/com/openAi/security/repository/AttendanceRepository.java
new file mode 100644
index 0000000..5fc7d09
--- /dev/null
+++ b/src/main/java/com/openAi/security/repository/AttendanceRepository.java
@@ -0,0 +1,394 @@
+package com.openAi.security.repository;
+
+
+import com.openAi.security.entity.Attendance;
+import com.openAi.security.model.MonthValue;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+
+public interface AttendanceRepository extends JpaRepository {
+
+ @Query(value = """
+ select distinct concat(a.year,"-",a.month) from playbook.attendance a
+ order by a.year desc,a.month desc limit 1
+ """, nativeQuery = true)
+ String getLatestMonthAndYear();
+
+ @Query(value = """
+ SELECT * FROM attendance where
+ month in :month AND year=:year AND
+ (project_name like %:projectName% or project_name = :customerName)
+ AND employee_grade != 'Contract' """, nativeQuery = true)
+ List findAllByProjectName(Integer year, List month, String projectName, String customerName);
+
+ @Query(value = """
+ SELECT * FROM attendance a where
+ STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d') <=:endDate
+ and (a.project_name like %:projectName% or a.project_name = :customerName)
+ AND a.employee_grade != 'Contract' """, nativeQuery = true)
+ List findAllByProjectNameAndDate(LocalDate startDate,LocalDate endDate, String projectName, String customerName);
+
+
+ @Query(value = """
+ select distinct a.* FROM playbook.attendance a
+ where a.month = :month and a.year = :year
+ and a.employee_function not in ('IT','Administration','Account','Accounts','Account Management')
+ AND a.email_id NOT IN (SELECT user_email_id FROM playbook.kra_user_survey WHERE kra_cycle_id= :configId)
+ """, nativeQuery = true)
+ List findAllAttendanceSurvey(Integer year, Integer month,Integer configId);
+ @Query(value = """
+ SELECT * FROM attendance where
+ month in :month AND year=:year
+ AND employee_grade != 'Contract' """, nativeQuery = true)
+ List findAllByYearAndMonth(Integer year, List month);
+
+
+ @Query(value = """
+ SELECT * FROM attendance where
+ (project_name like %:projectName% or project_name = :customerName)
+ AND employee_grade != 'Contract' """, nativeQuery = true)
+ List findAllByProjectName(String projectName, String customerName);
+
+
+ @Query(value = """
+ SELECT * FROM attendance where
+ month in :month AND year=:year AND
+ (employee_function like %:function%)
+ AND employee_grade != 'Contract' """, nativeQuery = true)
+ List findAllByEmployeeFunction(Integer year, List month, String function);
+
+ @Query(value = """
+ select a2.* FROM attendance a1 join attendance a2
+ on a1.employee_name = a2.reporting_manager and a1.month = a2.month and a1.year = a2.year
+ join (select * from attendance where employee_grade = 'M2' and employee_function like %:function% and month in (:month) and year=:year) as a3
+ on a1.reporting_manager = a3.employee_name and a1.month = a3.month and a1.year = a3.year
+ where a1.month in (:month) AND a1.year=:year
+ union
+ select a1.* FROM attendance a1
+ join (select * from attendance where employee_grade = 'M2' and employee_function like %:function% and month in (:month) and year=:year) a2
+ on a1.reporting_manager = a2.employee_name and a1.month = a2.month and a1.year = a2.year
+ where a1.month in (:month) AND a1.year=:year
+ """, nativeQuery = true)
+ List findAllByReportingManager(Integer year, List month, String function);
+
+
+ @Query(value= """
+ select(
+ (select sum(story_points) from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and a.email_id= :email
+ and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d') <=:endDate and at.team_id in :teamId)
+ /
+ (select sum(story_points) from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d') <=:endDate and at.team_id in :teamId and a.employee_function
+ in (select a.employee_function from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and a.email_id=:email
+ and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d') <=:endDate )))*100 as Result
+ """,nativeQuery = true)
+ Double getOwnerShipByEffort(List teamId, String email, LocalDate startDate, LocalDate endDate);
+
+
+ @Query(value = """
+ select sum(present_days) from attendance a
+ where STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d') <=:endDate\s
+ and a.email_id =:email
+ """,nativeQuery = true)
+ Double getDevelopmentDays(String email, LocalDate startDate, LocalDate endDate);
+
+ @Query(value= """
+ select sum(logged_hours)/avg(working_hours)*100 from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and a.email_id= :email
+ and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')<=:endDate and at.team_id in (:teamId)
+ group by a.month,a.year
+ """,nativeQuery = true)
+ List getProductivity(List teamId,String email, LocalDate startDate,LocalDate endDate);
+
+
+ @Query(value= """
+ select sum(logged_hours)/(8) from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and a.email_id= :email
+ and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')<=:endDate and at.team_id in (:teamId)
+ group by a.month,a.year
+ """,nativeQuery = true)
+ List getProductivityInDays(List teamId,String email, LocalDate startDate,LocalDate endDate);
+
+ @Query(value= """
+ select sum(logged_hours)/avg(working_hours)*100 as value,a.month,a.year from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and a.email_id= :email
+ and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')<=:endDate and at.team_id in (:teamId)
+ group by a.month,a.year
+ """,nativeQuery = true)
+ List getProductivityValues(List teamId, String email, LocalDate startDate, LocalDate endDate);
+
+
+ @Query(value= """
+ select sum(story_points) * 22 /sum(a.present_days) from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and a.email_id= :email
+ and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')<=:endDate and at.team_id in (:teamId)
+ group by a.month,a.year
+ """,nativeQuery = true)
+ List getStoryPoints(List teamId,String email, LocalDate startDate,LocalDate endDate);
+
+
+ @Query(value= """
+ select sum(story_points) from playbook.attendance_team at join playbook.attendance a
+ on at.attendance_id = a.id and a.email_id= :email
+ and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')>=:startDate and STR_TO_DATE(CONCAT(a.year,'-',a.month,'-',1), '%Y-%m-%d')<=:endDate and at.team_id in (:teamId)
+ group by a.month,a.year
+ """,nativeQuery = true)
+ List getTotalStoryPoints(List teamId,String email, LocalDate startDate,LocalDate endDate);
+
+ @Query(value= """
+ select (sum(COALESCE(bug_fixes_story_points, 0) + COALESCE(enhancements_story_points, 0) + COALESCE(new_features_story_points, 0))/(sum(at.working_hours)/8))*22 sp
+ from playbook.attendance_team at
+ join playbook.attendance a on at.attendance_id = a.id
+ and a.month = :month and a.year = :year and at.team_id = :teamId
+ """,nativeQuery = true)
+ Double getVelocityByTeamAndMonthAndYear(Integer teamId, Integer month, Integer year);
+
+ @Query(value = """
+ SELECT * FROM attendance where
+ month in :month AND year=:year AND
+ (employee_grade like 'A%')
+ AND employee_grade != 'Contract' """, nativeQuery = true)
+ List findAllByEmployeeGrade(Integer year, List month);
+
+ @Query(value = "SELECT at FROM Attendance at where at.month=:month AND at.year=:year AND at.employeeName IN :employeeNames")
+ List getByMonthAndYearAndEmployeeNameIn(Integer month, Integer year, List employeeNames);
+
+ @Query(value = "select * from attendance where email_id= :emailId and ((month >= :startMonth and year= :startYear) or (month <= :endMonth and year= :endYear)) order by year,month desc", nativeQuery = true)
+ List findByEmployeeEmailAndYearMonth(String emailId, Integer startMonth, Integer startYear, Integer endMonth, Integer endYear);
+
+ @Query(value = "select * from attendance where email_id= :emailId and month >= :startMonth and month <= :endMonth and year= :year order by year,month desc", nativeQuery = true)
+ List findByEmployeeEmailAndYearMonth(String emailId, Integer startMonth, Integer endMonth, Integer year);
+
+ List findByMonthAndYearAndFirstNameAndLastName(Integer month, Integer year, String firstName, String lastName);
+
+ @Query(value = """
+ SELECT * FROM attendance where
+ (project_name like %:projectName% or project_name = :customerName)
+ AND first_name = :firstName
+ AND last_name = :lastName
+ AND employee_grade != 'Contract'
+ """, nativeQuery = true)
+ List findByProjectNameAndFirstNameAndLastName(String projectName, String customerName, String firstName, String lastName);
+
+ List findByMonthAndYearAndLastName(Integer month, Integer year, String lastName);
+
+ List findByMonthAndYearAndLastNameAndProjectName(Integer month, Integer year, String lastName,String projectName);
+
+ List findByMonthAndYearAndFirstNameAndProjectName(Integer month, Integer year, String firstName,String projectName);
+
+
+ List findByEmailIdOrderByYearDescMonthDesc(String email);
+
+ @Query(value = "select * from attendance where reporting_manager= :name and month = :month and year= :year", nativeQuery = true)
+ List findByReportingManagerOrderByYearDescMonthDesc(String name,Integer year,Integer month);
+
+ @Query(value = "select * from attendance where email_id= :email and month = :month and year= :year Limit 1", nativeQuery = true)
+ Attendance findByEmailAndYearAndMonth(String email, Integer year, Integer month);
+
+ @Query(value = "select * from attendance where month = :month and year= :year Limit 5", nativeQuery = true)
+ List findByYearAndMonth(Integer year, Integer month);
+
+ @Modifying
+ @Transactional
+ @Query(value = "delete FROM attendance where month = :month and year = :year", nativeQuery = true)
+ void deleteByMonthAndYear(Integer month, Integer year);
+
+ @Modifying
+ @Transactional
+ @Query(value = "delete FROM attendance_team where attendance_id in (select id from attendance where month = :month and year = :year)", nativeQuery = true)
+ void deleteByMonthAndYearAttendanceTeam(Integer month, Integer year);
+
+ @Query(value = "SELECT DISTINCT a.* FROM attendance AS a JOIN customers AS c ON a.project_name LIKE CONCAT('%', SUBSTRING(c.project_name, 1, LENGTH(a.project_name)), '%') WHERE c.id = :customerId AND ((a.year = :startYear AND a.month >= :startMonth) AND (a.year = :endYear AND a.month <= :endMonth));", nativeQuery = true)
+ List findByCustomerIdAndDateRanges(Long customerId, int startYear, int startMonth, int endYear,
+ int endMonth);
+
+ @Query(value = "SELECT DISTINCT a.* FROM attendance AS a WHERE a.id IN( SELECT attendance_id FROM attendance_team WHERE team_id in :teamId ) AND ((month >= :startMonth and year= :startYear) or (month <= :endMonth and year= :endYear));", nativeQuery = true)
+ List findByTeamIdAndDateRanges(List teamId, int startYear, int startMonth, int endYear, int endMonth);
+
+ @Query(value = "SELECT DISTINCT a.* FROM attendance AS a WHERE a.id IN( SELECT attendance_id FROM attendance_team WHERE team_id in :teamId ) AND (month >= :startMonth and year= :startYear and month <= :endMonth);", nativeQuery = true)
+ List findByTeamIdAndDateRanges(List teamId, int startYear, int startMonth, int endMonth);
+
+ @Query(value = "SELECT DISTINCT a.employee_code,a.employee_name, a.employee_grade, a.employee_function ,at.team_id FROM attendance a join attendance_team at on a.id = at.attendance_id join team t on at.team_id = t.id WHERE ((month >= :startMonth and year= :startYear) or (month <= :endMonth and year= :endYear));", nativeQuery = true)
+ List