diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml
new file mode 100644
index 0000000..a37bc83
--- /dev/null
+++ b/.idea/dataSources.local.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..eff9a4d
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "lastFilter": {
+ "state": "OPEN",
+ "assignee": "doaa-shafi"
+ }
+}
+ {
+ "selectedUrlAndAccountId": {
+ "url": "https://github.com/HubStaff-MSA/UserAppMicroService.git",
+ "accountId": "1e500e95-6352-4538-8934-ef6d2e5c5d11"
+ }
+}
+
+
+ {
+ "associatedIndex": 8
+}
+
+
+
+
+
+ {
+ "keyToString": {
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "git-widget-placeholder": "roba",
+ "kotlin-language-version-configured": "true",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "nodejs_package_manager_path": "npm",
+ "run.configurations.included.in.services": "true",
+ "vue.rearranger.settings.migration": "true"
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1715981610166
+
+
+ 1715981610166
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config-server/target/classes/application.properties b/config-server/target/classes/application.properties
new file mode 100644
index 0000000..d2c7449
--- /dev/null
+++ b/config-server/target/classes/application.properties
@@ -0,0 +1 @@
+spring.application.name=config-server
diff --git a/config-server/target/classes/com/roba/configserver/ConfigServerApplication.class b/config-server/target/classes/com/roba/configserver/ConfigServerApplication.class
new file mode 100644
index 0000000..c63e942
Binary files /dev/null and b/config-server/target/classes/com/roba/configserver/ConfigServerApplication.class differ
diff --git a/security/security/pom.xml b/security/security/pom.xml
index 883c7c5..e6c9c35 100644
--- a/security/security/pom.xml
+++ b/security/security/pom.xml
@@ -50,6 +50,12 @@
jjwt-impl
0.11.5
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.11.5
+
+
org.springframework.boot
spring-boot-starter-test
@@ -60,6 +66,8 @@
spring-security-test
test
+
+
diff --git a/security/security/src/main/java/com/roba/security/Client/Client.java b/security/security/src/main/java/com/roba/security/Client/Client.java
new file mode 100644
index 0000000..25eca0a
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Client/Client.java
@@ -0,0 +1,54 @@
+package com.roba.security.Client;
+
+import com.roba.security.Project.BudgetBasedOn;
+import com.roba.security.Project.BudgetType;
+import com.roba.security.Project.Project;
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.antlr.v4.runtime.misc.NotNull;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "Client")
+public class Client {
+ @Id
+ @SequenceGenerator(
+ name = "client_id_sequence",
+ sequenceName = "client_id_sequence"
+ )
+ @GeneratedValue(
+ strategy = GenerationType.SEQUENCE,
+ generator = "client_id_sequence"
+ )
+ private Integer id;
+
+ @Column(nullable = false)
+ private String name;
+
+ @Column(nullable = false)
+ private String email;
+
+ @NotNull
+ @OneToMany(mappedBy = "client", cascade = CascadeType.ALL)
+ private List projects;
+ private String phoneNumber;
+ private String emailAddress;
+ //private Budget budget;
+ private boolean billable;
+ private BudgetType budgetType;
+ private BudgetBasedOn budgetBasedOn;
+ private Double budgetCost;
+ private Double budgetNotifyAt;
+ private Date budgetStartDate;
+ private boolean budgetIncludeNonBillabeTime;
+ private Integer organizationId;
+}
\ No newline at end of file
diff --git a/security/security/src/main/java/com/roba/security/JwtService.java b/security/security/src/main/java/com/roba/security/JwtService.java
deleted file mode 100644
index 4ea89c9..0000000
--- a/security/security/src/main/java/com/roba/security/JwtService.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.roba.security;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class JwtService {
-
-
- public String extractEmail(String token) {
- return null;
- }
-}
diff --git a/security/security/src/main/java/com/roba/security/Project/BudgetBasedOn.java b/security/security/src/main/java/com/roba/security/Project/BudgetBasedOn.java
new file mode 100644
index 0000000..4e018e6
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/BudgetBasedOn.java
@@ -0,0 +1,4 @@
+package com.roba.security.Project;
+
+public enum BudgetBasedOn {
+}
diff --git a/security/security/src/main/java/com/roba/security/Project/BudgetType.java b/security/security/src/main/java/com/roba/security/Project/BudgetType.java
new file mode 100644
index 0000000..cdd2421
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/BudgetType.java
@@ -0,0 +1,4 @@
+package com.roba.security.Project;
+
+public enum BudgetType {
+}
diff --git a/security/security/src/main/java/com/roba/security/Project/Project.java b/security/security/src/main/java/com/roba/security/Project/Project.java
new file mode 100644
index 0000000..1f58074
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/Project.java
@@ -0,0 +1,57 @@
+package com.roba.security.Project;
+
+
+
+import com.roba.security.Client.Client;
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.antlr.v4.runtime.misc.NotNull;
+
+import java.util.Date;
+//import javax.*;
+
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "Project")
+public class Project {
+ @Id
+ @SequenceGenerator(
+ name = "project_id_sequence",
+ sequenceName = "project_id_sequence"
+ )
+ @GeneratedValue(
+ strategy = GenerationType.SEQUENCE,
+ generator = "project_id_sequence"
+ )
+ private Integer id;
+ // @NotNull
+ private String projectName;
+ private boolean disableActivity;
+ private boolean disableIdleTime;
+ //private Integer clientId;
+ @ManyToOne
+ @JoinColumn(name = "client_id", nullable = false)
+ private Client client;
+ // @NotNull
+ //private Budget budget;
+ private boolean billable;
+ private BudgetType budgetType;
+ private BudgetBasedOn budgetBasedOn;
+ private Double budgetCost;
+ private Double budgetNotifyAt;
+ private Date budgetStartDate;
+ private boolean budgetIncludeNonBillabeTime;
+ // @NotNull
+ private Integer organizationId;
+ //members
+ //users
+ //managers
+ //CONSTRAINTS
+}
\ No newline at end of file
diff --git a/security/security/src/main/java/com/roba/security/Project/ProjectController.java b/security/security/src/main/java/com/roba/security/Project/ProjectController.java
new file mode 100644
index 0000000..8c8a43e
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/ProjectController.java
@@ -0,0 +1,42 @@
+package com.roba.security.Project;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Optional;
+
+@Slf4j
+@RestController
+@RequestMapping("api/v1/project")
+public record ProjectController(ProjectService projectService) {
+
+ @PostMapping
+ public void createProject(@RequestBody ProjectCreationRequest projectRequest){
+ System.out.printf("new project added {}", projectRequest);
+ projectService.createProject(projectRequest);
+ }
+ @PutMapping
+ public void editProject(@RequestBody ProjectEditRequest projectRequest){
+ //log.info("project edited {}", projectRequest);
+ projectService.editProject(projectRequest);
+ }
+ @GetMapping
+ public Optional findById(@RequestParam Integer id){
+ //log.info("find project {}", id);
+ return projectService.findById(id);
+ }
+
+
+// @GetMapping("/{managerId}")
+// public List findByManagerId(@PathVariable Integer managerId){
+// //log.info("find project {}", id);
+// return projectService.findAllByManager(managerId);
+// }
+ @DeleteMapping
+ public void deleteProject(@RequestParam Integer id){
+ //log.info("project deleted {}", id);
+ projectService.deleteProject(id);
+ }
+
+}
\ No newline at end of file
diff --git a/security/security/src/main/java/com/roba/security/Project/ProjectCreationRequest.java b/security/security/src/main/java/com/roba/security/Project/ProjectCreationRequest.java
new file mode 100644
index 0000000..5b613f3
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/ProjectCreationRequest.java
@@ -0,0 +1,25 @@
+package com.roba.security.Project;
+
+
+
+import com.roba.security.Client.Client;
+
+import java.util.Date;
+
+public record ProjectCreationRequest(
+ String projectName,
+ boolean disableActivity,
+ boolean disableIdleTime,
+ //Integer clientId,
+ Client client,
+ boolean billable,
+ BudgetType budgetType,
+ BudgetBasedOn budgetBasedOn,
+ Double budgetCost,
+ Double budgetNotifyAt,
+ Date budgetStartDate,
+ boolean budgetIncludeNonBillabeTime,
+ //Budget budget,
+ Integer organizationId
+) {
+}
\ No newline at end of file
diff --git a/security/security/src/main/java/com/roba/security/Project/ProjectEditRequest.java b/security/security/src/main/java/com/roba/security/Project/ProjectEditRequest.java
new file mode 100644
index 0000000..959cdf6
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/ProjectEditRequest.java
@@ -0,0 +1,25 @@
+package com.roba.security.Project;
+
+
+import com.roba.security.Client.Client;
+
+import java.util.Date;
+
+public record ProjectEditRequest(
+ Integer id,
+ String projectName,
+ //Budget budget,
+ boolean disableActivity,
+ boolean disableIdleTime,
+ //Integer clientId,
+ Client client,
+ boolean billable,
+ BudgetType budgetType,
+ BudgetBasedOn budgetBasedOn,
+ Double budgetCost,
+ Double budgetNotifyAt,
+ Date budgetStartDate,
+ boolean budgetIncludeNonBillabeTime,
+ Integer organizationId
+) {
+}
\ No newline at end of file
diff --git a/security/security/src/main/java/com/roba/security/Project/ProjectRepository.java b/security/security/src/main/java/com/roba/security/Project/ProjectRepository.java
new file mode 100644
index 0000000..f415ac4
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/ProjectRepository.java
@@ -0,0 +1,9 @@
+package com.roba.security.Project;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface ProjectRepository extends JpaRepository {
+ // List findAllByManagerId(Integer managerId);
+}
\ No newline at end of file
diff --git a/security/security/src/main/java/com/roba/security/Project/ProjectService.java b/security/security/src/main/java/com/roba/security/Project/ProjectService.java
new file mode 100644
index 0000000..4d4acd3
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/Project/ProjectService.java
@@ -0,0 +1,72 @@
+package com.roba.security.Project;
+
+
+
+import org.springframework.stereotype.Service;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public record ProjectService(ProjectRepository projectRepository) {
+ public void createProject(ProjectCreationRequest projectRequest) {
+ if (projectRequest.projectName() == null || projectRequest.projectName().isEmpty()) {
+ throw new IllegalArgumentException("Project name cannot be empty");
+ }
+ Project project = Project.builder()
+ .projectName(projectRequest.projectName())
+ .billable(projectRequest.billable())
+ .budgetBasedOn(projectRequest.budgetBasedOn())
+ .budgetCost(projectRequest.budgetCost())
+ .budgetNotifyAt(projectRequest.budgetNotifyAt())
+ .budgetStartDate(projectRequest.budgetStartDate())
+ .budgetType(projectRequest.budgetType())
+ .client(projectRequest.client())
+ //.clientId(projectRequest.clientId())
+ .budgetIncludeNonBillabeTime(projectRequest.budgetIncludeNonBillabeTime())
+ .disableActivity(projectRequest.disableActivity())
+ .disableIdleTime(projectRequest.disableIdleTime())
+ .organizationId(projectRequest.organizationId())
+ //.budget(projectRequest.budget())
+ .build();
+ //todo: check constraints
+ //todo: fix pgadmin bug
+ projectRepository.save(project);
+ }
+ public void editProject(ProjectEditRequest projectRequest) {
+ //Project project = projectRepository.getById(projectRequest.id());
+ Project project = Project.builder()
+ .id(projectRequest.id())
+ .projectName(projectRequest.projectName())
+ .billable(projectRequest.billable())
+ .budgetBasedOn(projectRequest.budgetBasedOn())
+ .budgetCost(projectRequest.budgetCost())
+ .budgetNotifyAt(projectRequest.budgetNotifyAt())
+ .budgetStartDate(projectRequest.budgetStartDate())
+ .budgetType(projectRequest.budgetType())
+ //.clientId(projectRequest.clientId())
+ .client(projectRequest.client())
+ .budgetIncludeNonBillabeTime(projectRequest.budgetIncludeNonBillabeTime())
+ .disableActivity(projectRequest.disableActivity())
+ .disableIdleTime(projectRequest.disableIdleTime())
+ .organizationId(projectRequest.organizationId())
+// .budget(projectRequest.budget())
+ .build();
+ //todo: check constraints
+ //todo: fix pgadmin bug
+ projectRepository.save(project);
+ }
+ public void deleteProject(Integer id){
+ try {
+ projectRepository.deleteById(id);
+ } catch (Exception e) {
+ // Handle exception
+ throw new RuntimeException("Failed to delete project with id: " + id, e);
+ }
+ }
+ public Optional findById(Integer id){
+ return projectRepository.findById(id);
+ }
+// public List findAllByManager(Integer managerId){
+// return projectRepository.findAllByManagerId(managerId);
+// }
+}
\ No newline at end of file
diff --git a/security/security/src/main/java/com/roba/security/SecurityApplication.java b/security/security/src/main/java/com/roba/security/SecurityApplication.java
index 4fac3e2..245fa5a 100644
--- a/security/security/src/main/java/com/roba/security/SecurityApplication.java
+++ b/security/security/src/main/java/com/roba/security/SecurityApplication.java
@@ -2,7 +2,9 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+@EnableCaching
@SpringBootApplication
public class SecurityApplication {
diff --git a/security/security/src/main/java/com/roba/security/UserRespository.java b/security/security/src/main/java/com/roba/security/UserRespository.java
deleted file mode 100644
index cdbbee5..0000000
--- a/security/security/src/main/java/com/roba/security/UserRespository.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.roba.security;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.Optional;
-
-public interface UserRespository extends JpaRepository {
- Optional findByEmail(String workEmail);
-}
diff --git a/security/security/src/main/java/com/roba/security/auth/AuthenticationController.java b/security/security/src/main/java/com/roba/security/auth/AuthenticationController.java
new file mode 100644
index 0000000..e95bc9e
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/auth/AuthenticationController.java
@@ -0,0 +1,54 @@
+package com.roba.security.auth;
+
+import com.roba.security.user.Command;
+import com.roba.security.user.CommandFactory;
+import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api/v1/auth")
+@RequiredArgsConstructor
+public class AuthenticationController {
+ private final AuthenticationService service;
+ private final CommandFactory commandFactory;
+
+// @PostMapping("/register")
+// public ResponseEntity register(@RequestBody RegisterRequest request) {
+// Command command = commandFactory.createRegisterCommand(request);
+// command.execute();
+// //return ResponseEntity.ok().build();
+// return ResponseEntity.ok(service.register(request));
+// }
+//
+//
+// @PostMapping("/authenticate")
+// public ResponseEntity authenticate(@RequestBody AuthenticationRequest request) {
+// Command command = commandFactory.createAuthenticateCommand(request);
+// command.execute();
+// //return ResponseEntity.ok().build();
+// return ResponseEntity.ok(service.authenticate(request));
+// }
+
+
+ @PostMapping("/register")
+ public ResponseEntity register(@RequestBody RegisterRequest request) {
+ Command command = commandFactory.createRegisterCommand(request);
+ command.execute();
+ AuthenticationResponse response = command.getResult();
+ return ResponseEntity.ok(response);
+ }
+
+ @PostMapping("/authenticate")
+ public ResponseEntity authenticate(@RequestBody AuthenticationRequest request) {
+ Command command = commandFactory.createAuthenticateCommand(request);
+ command.execute();
+ AuthenticationResponse response = command.getResult();
+ return ResponseEntity.ok(response);
+ }
+
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/auth/AuthenticationRequest.java b/security/security/src/main/java/com/roba/security/auth/AuthenticationRequest.java
new file mode 100644
index 0000000..824e757
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/auth/AuthenticationRequest.java
@@ -0,0 +1,16 @@
+package com.roba.security.auth;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class AuthenticationRequest {
+ private String workEmail;
+ private String password;
+
+}
diff --git a/security/security/src/main/java/com/roba/security/auth/AuthenticationResponse.java b/security/security/src/main/java/com/roba/security/auth/AuthenticationResponse.java
new file mode 100644
index 0000000..022f994
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/auth/AuthenticationResponse.java
@@ -0,0 +1,14 @@
+package com.roba.security.auth;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class AuthenticationResponse {
+ private String token;
+}
diff --git a/security/security/src/main/java/com/roba/security/auth/AuthenticationService.java b/security/security/src/main/java/com/roba/security/auth/AuthenticationService.java
new file mode 100644
index 0000000..c69616a
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/auth/AuthenticationService.java
@@ -0,0 +1,232 @@
+package com.roba.security.auth;
+
+import com.roba.security.Project.Project;
+import com.roba.security.config.JwtService;
+
+import java.util.Optional;
+import com.roba.security.organization.Organization;
+import com.roba.security.organization.OrganizationRepository;
+import com.roba.security.token.Token;
+import com.roba.security.token.TokenRepository;
+import com.roba.security.token.TokenService;
+import com.roba.security.token.TokenType;
+import com.roba.security.user.*;
+import lombok.RequiredArgsConstructor;
+
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+@RequiredArgsConstructor
+
+public class AuthenticationService {
+ private final UserRepository repository;
+ private final PasswordEncoder passwordEncoder;
+ private final JwtService jwtService;
+ private final AuthenticationManager authenticationManager;
+ private final TokenRepository tokenRepository;
+ private final TokenService tokenService;
+ private final Emailvalidator emailvalidator;
+ private final OrganizationRepository organizationRepository;
+
+ // @Cacheable(key="#id",value="User")
+ public AuthenticationResponse register(RegisterRequest request) {
+ //boolean isValidEmail =emailvalidator.test(request.getWorkEmail());
+ //if(!isValidEmail) {throw new IllegalStateException("Invalid email");}
+ Optional existingUser = repository.findByworkEmail(request.getWorkEmail());
+ if (existingUser.isPresent()) {
+ throw new IllegalStateException("Email is already in use");
+ }
+ Role role;
+ if (request.getRole().equals("team_member")) {
+ role = Role.USER;
+ } else {
+ role = request.getRole();
+ }
+ if (role == Role.OWNER) {
+ // Create organization
+ Organization organization = Organization.builder()
+ .name(request.getOrganizationName())
+ .teamSize(request.getTeamSize())
+ .websiteURL(request.getWebsite())// Assuming organization name is provided in the request
+ .build();
+ Organization savedOrganization = organizationRepository.save(organization);
+
+ var user = User.builder()
+ .fullName(request.getFullName())
+ .workEmail(request.getWorkEmail())
+ .password(passwordEncoder.encode(request.getPassword()))
+ .role(request.getRole())
+ .organization(savedOrganization)
+ .build();
+ var savedUser = repository.save(user);
+ var jwtToken = jwtService.generateToken(user);
+
+ saveUserToken(savedUser, jwtToken);
+ return AuthenticationResponse.builder().token(jwtToken).build();
+ } else if (role == Role.USER) {
+ // Fetch organization by name
+ Optional organizationOptional = organizationRepository.findByName(request.getOrganizationName());
+ if (organizationOptional.isEmpty()) {
+ throw new IllegalStateException("Organization not found");
+ }
+ Organization organization = organizationOptional.get();
+
+ var user = User.builder()
+ .fullName(request.getFullName())
+ .workEmail(request.getWorkEmail())
+ .password(passwordEncoder.encode(request.getPassword()))
+ .role(Role.USER)
+ .organization(organization)
+ .build();
+ var savedUser = repository.save(user);
+ var jwtToken = jwtService.generateToken(user);
+
+ saveUserToken(savedUser, jwtToken);
+
+ return AuthenticationResponse.builder().token(jwtToken).build();
+ } else {
+ throw new IllegalStateException("Role not supported");
+
+ }
+
+ }
+
+ private void revokeAllUserTokens(User user) {
+ var validUserTokens = tokenRepository.findAllValidTokenByUser(user.getId());
+ if (validUserTokens.isEmpty())
+ return;
+ validUserTokens.forEach(token -> {
+ token.setExpired(true);
+ token.setRevoked(true);
+ });
+ tokenRepository.saveAll(validUserTokens);
+ }
+
+
+ public AuthenticationResponse authenticate(AuthenticationRequest request) {
+ authenticationManager.authenticate(
+ new UsernamePasswordAuthenticationToken(
+ request.getWorkEmail(),
+ request.getPassword()
+ )
+ );
+ var user = repository.findByworkEmail(request.getWorkEmail())
+ .orElseThrow();
+ var jwtToken = jwtService.generateToken(user);
+ revokeAllUserTokens(user);
+ saveUserToken(user, jwtToken);
+
+ return AuthenticationResponse.builder().token(jwtToken).build();
+
+ }
+
+ private void saveUserToken(User user, String jwtToken) {
+ var token = Token.builder().user(user).token(jwtToken).tokenType(TokenType.BEARER).revoked(false).expired(false).build();
+ tokenRepository.save(token);
+ tokenService.saveToken(token);
+ }
+
+
+/////////profile edits
+
+// public String updateUserProfile(Integer userId, UserProfileUpdateRequest request) {
+// User user = repository.findById(userId)
+// .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId));
+// if (request.getFullName() != null) {
+// user.setFullName(request.getFullName());
+// }
+// if (request.getWorkEmail() != null) {
+// user.setWorkEmail(request.getWorkEmail());
+// }
+//
+// repository.save(user);
+// return "";
+//
+
+
+ public String updateUserProfile(Integer userId, UserProfileUpdateRequest request) {
+ User user = repository.findById(userId)
+ .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId));
+
+ // Update user profile fields if provided in the request
+ if (request.getFullName() != null) {
+ user.setFullName(request.getFullName());
+ }
+ if (request.getWorkEmail() != null) {
+ user.setWorkEmail(request.getWorkEmail());
+ }
+
+ // Save the updated user record
+ User savedUser = repository.save(user);
+
+ // Refresh the associated token(s) to prevent expiration
+ refreshUserTokens(savedUser);
+
+ return "Profile updated successfully";
+ }
+
+ private void refreshUserTokens(User user) {
+ List userTokens = tokenRepository.findByUser(user);
+ userTokens.forEach(token -> {
+ token.setExpired(false); // Set the token as not expired
+ tokenRepository.save(token); // Save the refreshed token
+ tokenService.saveToken(token);
+ });
+
+
+
+
+
+
+
+
+}
+
+ public void changeUserPassword(Integer userId, ChangePasswordRequest request) {
+ User user = repository.findById(userId)
+ .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId));
+
+
+
+
+ // Check if the current password matches
+ if (!passwordEncoder.matches(request.getCurrentPassword(), user.getPassword())) {
+ throw new UnauthorizedException("Current password is incorrect");
+ }
+ // Update password
+ user.setPassword(passwordEncoder.encode(request.getNewPassword()));
+
+ repository.save(user);
+ }
+
+
+
+
+
+
+
+
+
+ //get all users
+ public List getAllUsers() {
+ return repository.findAll();
+ }
+
+ public OptionalgetUserById(Integer userId) {
+ return repository.findById(userId);
+ // .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId));
+ }
+ public List getUsersByRole(Role role) {
+ return repository.findByRole(role);
+ }
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/auth/Emailvalidator.java b/security/security/src/main/java/com/roba/security/auth/Emailvalidator.java
new file mode 100644
index 0000000..aaa8bfc
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/auth/Emailvalidator.java
@@ -0,0 +1,13 @@
+package com.roba.security.auth;
+
+import org.springframework.stereotype.Service;
+
+import java.util.function.Predicate;
+@Service
+public class Emailvalidator implements Predicate {
+
+ @Override
+ public boolean test(String s) {
+ return false;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/auth/RegisterRequest.java b/security/security/src/main/java/com/roba/security/auth/RegisterRequest.java
new file mode 100644
index 0000000..fd4eb33
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/auth/RegisterRequest.java
@@ -0,0 +1,24 @@
+package com.roba.security.auth;
+
+import com.roba.security.organization.Organization;
+import com.roba.security.user.Role;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class RegisterRequest {
+ private String fullName;
+ private String password;
+ private String workEmail;
+ private Role role;
+ private String organizationName;
+ private Integer teamSize;
+ private String website;
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/config/ApplicationConfig.java b/security/security/src/main/java/com/roba/security/config/ApplicationConfig.java
new file mode 100644
index 0000000..86ce4ad
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/config/ApplicationConfig.java
@@ -0,0 +1,49 @@
+package com.roba.security.config;
+
+import com.roba.security.user.UserRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UserDetails;
+@Configuration
+@RequiredArgsConstructor
+public class ApplicationConfig {
+ private final UserRepository repository;
+ @Bean
+ public UserDetailsService userDetailsService() {
+ return username -> repository.findByworkEmail(username)
+ .orElseThrow(() -> new UsernameNotFoundException("User not found"));
+
+ }
+ @Bean
+ public AuthenticationProvider authenticationProvider(){
+ DaoAuthenticationProvider authprovider = new DaoAuthenticationProvider();
+ authprovider.setUserDetailsService(userDetailsService());
+ authprovider.setPasswordEncoder(passwordEncoder());
+ return authprovider;
+
+ }
+
+
+ @Bean
+ public PasswordEncoder passwordEncoder(){
+ return new BCryptPasswordEncoder();
+
+ }
+
+ @Bean
+ public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
+ return config.getAuthenticationManager();
+
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/config/JwtAuthenticationFilter.java b/security/security/src/main/java/com/roba/security/config/JwtAuthenticationFilter.java
new file mode 100644
index 0000000..e8eae2c
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/config/JwtAuthenticationFilter.java
@@ -0,0 +1,69 @@
+package com.roba.security.config;
+
+import com.roba.security.token.TokenRepository;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+@Component
+@RequiredArgsConstructor
+public class JwtAuthenticationFilter extends OncePerRequestFilter {
+
+ private final JwtService jwtService;
+ private final UserDetailsService userDetailsService;
+ private final TokenRepository tokenRepository;
+
+
+
+
+
+
+
+ @Override
+ protected void doFilterInternal(
+ @NonNull HttpServletRequest request,
+ @NonNull HttpServletResponse response,
+ @NonNull FilterChain filterChain) throws ServletException, IOException {
+ final String authHeader = request.getHeader("Authorization");
+ final String jwt;
+ final String workEmail;
+ if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+ filterChain.doFilter(request, response);
+ return;
+
+ }
+ jwt = authHeader.substring(7);
+ workEmail = jwtService.extractUsername(jwt);
+ if (workEmail != null && SecurityContextHolder.getContext().getAuthentication()==null) {
+ UserDetails userDetails = this.userDetailsService.loadUserByUsername(workEmail);
+ var isTokenValid =tokenRepository.findByToken(jwt)
+ .map(t -> !t.isExpired() && !t.isRevoked())
+ .orElse(false);
+ if (jwtService.isTokenValid( jwt, userDetails) && isTokenValid ) {
+ UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
+ userDetails,
+ null,
+ userDetails.getAuthorities()
+ );
+ authToken.setDetails(
+ new WebAuthenticationDetailsSource().buildDetails(request)
+ );
+ SecurityContextHolder.getContext().setAuthentication(authToken);
+ }
+
+ }
+ filterChain.doFilter(request, response);
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/config/JwtService.java b/security/security/src/main/java/com/roba/security/config/JwtService.java
new file mode 100644
index 0000000..2aa0217
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/config/JwtService.java
@@ -0,0 +1,69 @@
+package com.roba.security.config;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.io.Decoders;
+import io.jsonwebtoken.security.Keys;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+
+import java.security.Key;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+@Service
+public class JwtService {
+public static final String SECRET_KEY="Hqj4ZSrMAhMvjEpAQMQb2FiHqeMNmJi7mvT5xArPVzdhVfYHvqL2ZnwWzjJ+mbb2";
+
+ public String extractUsername(String token) {///the email
+ return extractClaim(token,Claims::getSubject);
+ }
+ private Claims extractClaims(String token) {
+ return Jwts.parserBuilder().
+ setSigningKey(getSigningKey()).
+ build().
+ parseClaimsJws(token).getBody();
+ }
+
+ public T extractClaim(String token, FunctionclaimsResolver) {
+ final Claims claims = extractClaims(token);
+ return claimsResolver.apply(claims);
+ }
+ public String generateToken(UserDetails userDetails) {
+ return generateToken(new HashMap<>(),userDetails);
+ }
+ public String generateToken(Map extraClaims,
+
+ UserDetails userDetails) {
+ return Jwts
+ .builder()
+ .setClaims(extraClaims)
+ .setSubject(userDetails.getUsername())
+ .setIssuedAt(new Date(System.currentTimeMillis()))
+ .setExpiration(new Date(System.currentTimeMillis()+1000*60*24))
+ .signWith(getSigningKey(), SignatureAlgorithm.HS256).compact();
+ }
+public boolean isTokenValid(String token,UserDetails userDetails){
+ final String email = extractUsername(token);
+ return (email.equals(userDetails.getUsername())) && !isTokenExpired(token);
+}
+
+
+public boolean isTokenExpired(String token) {
+
+ return extractExpiration(token).before(new Date());
+}
+
+ private Date extractExpiration(String token) {
+ return extractClaim(token,Claims::getExpiration);
+
+ }
+
+ private Key getSigningKey() {
+ byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
+ return Keys.hmacShaKeyFor(keyBytes);
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/config/LogoutService.java b/security/security/src/main/java/com/roba/security/config/LogoutService.java
new file mode 100644
index 0000000..7f18258
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/config/LogoutService.java
@@ -0,0 +1,39 @@
+package com.roba.security.config;
+
+import com.roba.security.token.TokenRepository;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutHandler;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class LogoutService implements LogoutHandler {
+ private final TokenRepository tokenRepository;
+
+
+ @Override
+ public void logout(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ Authentication authentication) {
+ final String authHeader = request.getHeader("Authorization");
+ final String jwt;
+ if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+ return;
+ }
+ jwt = authHeader.substring(7);
+ var storedToken =tokenRepository.findByToken(jwt)
+ .orElse(null);
+ if (storedToken != null) {
+ storedToken.setRevoked(true);
+ storedToken.setExpired(true);
+ tokenRepository.save(storedToken);
+ }
+
+ }
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/config/SecurityConfiguration.java b/security/security/src/main/java/com/roba/security/config/SecurityConfiguration.java
new file mode 100644
index 0000000..16a752a
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/config/SecurityConfiguration.java
@@ -0,0 +1,79 @@
+package com.roba.security.config;
+
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationProvider;
+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.core.context.SecurityContextHolder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.logout.LogoutHandler;
+
+
+import static com.roba.security.user.Permission.*;
+import static com.roba.security.user.Role.ORGANIZATION_MANAGER;
+import static com.roba.security.user.Role.OWNER;
+
+@Configuration
+@EnableWebSecurity
+@RequiredArgsConstructor
+
+public class SecurityConfiguration {
+ private final JwtAuthenticationFilter jwtAuthFilter;
+ private final AuthenticationProvider authenticationProvider;
+ private final LogoutHandler logoutHandler;
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http
+
+ .csrf(csrf -> csrf.disable()) // Disable CSRF protection
+ .authorizeHttpRequests(authorizeRequests ->
+ authorizeRequests
+ .requestMatchers("/api/v1/auth/**").permitAll()// Allow access to public endpoints
+ .requestMatchers("api/users/**").permitAll()
+ .requestMatchers("/api/v1/project/**").hasAnyRole(OWNER.name(),ORGANIZATION_MANAGER.name())//allow access by biz owner to admin endpoint
+ .requestMatchers(HttpMethod.GET,"/api/v1/project/**").hasAnyAuthority(PROJECT_READ.name())
+ .requestMatchers(HttpMethod.PUT,"/api/v1/project/**").hasAnyAuthority(PROJECT_UPDATE.name())
+ .requestMatchers(HttpMethod.POST,"/api/v1/project/**").hasAnyAuthority(PROJECT_CREATE.name())
+ .requestMatchers(HttpMethod.DELETE,"/api/v1/project/**").hasAnyAuthority(PROJECT_DELETE.name())
+
+ .requestMatchers("/api/v1/payment/**").hasAnyRole(OWNER.name())
+ .requestMatchers("/payroll/**").hasAnyRole(OWNER.name())
+ .anyRequest().authenticated() // Require authentication for other requests
+ )
+ .sessionManagement(sessionManagement ->
+ sessionManagement
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ )
+ .authenticationProvider(authenticationProvider)
+ .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
+ .logout(logout -> // Customizing logout configuration
+ logout
+ .logoutUrl("/api/v1/auth/logout")
+ .addLogoutHandler(logoutHandler)
+ .logoutSuccessHandler( (request, response, authentication) -> SecurityContextHolder.clearContext()));
+
+
+
+// .logout()
+// .logoutUrl("/api/v1/auth/logout")
+// .addLogoutHandler(logoutHandler)
+// .logoutSuccessHandler(
+// (request, response, authentication) -> SecurityContextHolder.clearContext()
+// );
+ return http.build();
+ }
+
+
+
+
+
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/config_JwtAuthenticationFilter.java b/security/security/src/main/java/com/roba/security/config_JwtAuthenticationFilter.java
deleted file mode 100644
index fade8e9..0000000
--- a/security/security/src/main/java/com/roba/security/config_JwtAuthenticationFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.roba.security;
-
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import java.io.IOException;
-
-@Component
-@RequiredArgsConstructor
-public class config_JwtAuthenticationFilter extends OncePerRequestFilter {
-
- private final JwtService jwtService;
-
-
-
-
-
-
- @Override
- protected void doFilterInternal(
- @NonNull HttpServletRequest request,
- @NonNull HttpServletResponse response,
- @NonNull FilterChain filterChain) throws ServletException, IOException {
- final String authHeader = request.getHeader("Authorization");
- final String jwt;
- final String workEmail;
- if (authHeader == null || !authHeader.startsWith("Bearer ")) {
- filterChain.doFilter(request, response);
- return;
-
- }
- jwt = authHeader.substring(7);
- workEmail = jwtService.extractEmail(jwt);
- }
-}
diff --git a/security/security/src/main/java/com/roba/security/demo/DemoController.java b/security/security/src/main/java/com/roba/security/demo/DemoController.java
new file mode 100644
index 0000000..9b15770
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/demo/DemoController.java
@@ -0,0 +1,15 @@
+package com.roba.security.demo;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/v1/demo-controller")
+public class DemoController {
+ @GetMapping
+ public ResponseEntity sayHello() {
+ return ResponseEntity.ok("Hello from secured endpoint");
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/demo/ProjectController1.java b/security/security/src/main/java/com/roba/security/demo/ProjectController1.java
new file mode 100644
index 0000000..a528f11
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/demo/ProjectController1.java
@@ -0,0 +1,24 @@
+package com.roba.security.demo;
+
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/v1/projects")
+
+public class ProjectController1 {
+
+
+ @GetMapping
+ public String get() {
+ return "get controller";
+ }
+
+ @PostMapping
+ public String post() {
+ return "post controller";
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/organization/Organization.java b/security/security/src/main/java/com/roba/security/organization/Organization.java
new file mode 100644
index 0000000..7dd5e36
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/organization/Organization.java
@@ -0,0 +1,40 @@
+package com.roba.security.organization;
+
+import com.roba.security.user.User;
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Data
+public class Organization {
+ @Id
+ @SequenceGenerator(
+ name="organization_id_sequence",
+ sequenceName="organization_id_sequence"
+ )
+ @GeneratedValue(
+ strategy = GenerationType.SEQUENCE,
+ generator = "organization_id_seqeunce"
+ )
+ private Integer id;
+ private String name;
+ private String websiteURL;
+ private Integer teamSize;
+ private String industry;
+ @OneToMany(mappedBy = "organization") // mappedBy refers to the field in User entity that owns the relationship
+ private List users ;
+
+
+// @OneToOne(mappedBy = "organization", cascade = CascadeType.ALL)
+// private User manager;
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/organization/OrganizationRepository.java b/security/security/src/main/java/com/roba/security/organization/OrganizationRepository.java
new file mode 100644
index 0000000..73d45ec
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/organization/OrganizationRepository.java
@@ -0,0 +1,11 @@
+package com.roba.security.organization;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface OrganizationRepository extends JpaRepository {
+ Optional findByName(String organizationName);
+}
diff --git a/security/security/src/main/java/com/roba/security/organization/OrganizationService.java b/security/security/src/main/java/com/roba/security/organization/OrganizationService.java
new file mode 100644
index 0000000..60301ef
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/organization/OrganizationService.java
@@ -0,0 +1,20 @@
+package com.roba.security.organization;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class OrganizationService {
+
+ private final OrganizationRepository organizationRepository;
+ @Autowired
+ public OrganizationService(OrganizationRepository organizationRepository) {
+ this.organizationRepository = organizationRepository;
+ }
+
+ public List getAllOrganizations() {
+ return organizationRepository.findAll();
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/token/RedisConfig.java b/security/security/src/main/java/com/roba/security/token/RedisConfig.java
new file mode 100644
index 0000000..c319724
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/token/RedisConfig.java
@@ -0,0 +1,30 @@
+package com.roba.security.token;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+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 JedisConnectionFactory jedisConnectionFactory() {
+ JedisConnectionFactory factory = new JedisConnectionFactory();
+ factory.setHostName("redis-12006.c62.us-east-1-4.ec2.redns.redis-cloud.com");
+ factory.setPort(12006);
+ factory.setPassword("oSrE2KvyJdxFJ8vmpDlIBDtQ9ZriadjR");
+ return factory;
+ }
+
+ @Bean
+ public RedisTemplate redisTemplate() {
+ RedisTemplate template = new RedisTemplate<>();
+ template.setConnectionFactory(jedisConnectionFactory());
+ template.setKeySerializer(new StringRedisSerializer());
+ template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
+ return template;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/token/Token.java b/security/security/src/main/java/com/roba/security/token/Token.java
new file mode 100644
index 0000000..98d44d4
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/token/Token.java
@@ -0,0 +1,34 @@
+package com.roba.security.token;
+
+import com.roba.security.user.User;
+import jakarta.persistence.*;
+import lombok.*;
+import java.io.Serializable;
+
+@Entity
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class Token implements Serializable {
+
+ private static final long serialVersionUID = 6529685098267757690L; // Add a serial version UID for serialization
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY) // Make sure to specify the strategy explicitly if not default
+ private Integer id;
+
+ private String token;
+
+ @Enumerated(EnumType.STRING)
+ private TokenType tokenType;
+
+ private boolean expired;
+
+ private boolean revoked;
+
+ @ManyToOne
+ @JoinColumn(name = "user_id")
+ private User user; // Ensure that the User class is also Serializable if it's being cached or stored
+
+}
diff --git a/security/security/src/main/java/com/roba/security/token/TokenRepository.java b/security/security/src/main/java/com/roba/security/token/TokenRepository.java
new file mode 100644
index 0000000..e3b294e
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/token/TokenRepository.java
@@ -0,0 +1,21 @@
+package com.roba.security.token;
+
+
+import com.roba.security.user.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import java.util.Optional;
+import java.util.List;
+
+public interface TokenRepository extends JpaRepository {
+
+ @Query("""
+ select t from Token t inner join User u on t.user.id=u.id
+ where u.id=:userId and(t.expired=false or t.revoked=false)
+ """)
+ List findAllValidTokenByUser(Integer userId);
+
+ Optional findByToken(String token);
+
+ List findByUser(User user);
+}
diff --git a/security/security/src/main/java/com/roba/security/token/TokenService.java b/security/security/src/main/java/com/roba/security/token/TokenService.java
new file mode 100644
index 0000000..1cae9f5
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/token/TokenService.java
@@ -0,0 +1,41 @@
+package com.roba.security.token;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.TimeUnit;
+
+@Service
+public class TokenService {
+
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ // Save or update token in Redis and cache
+ @CachePut(value = "tokens", key = "#token.id")
+ public Token saveToken(Token token) {
+ redisTemplate.opsForValue().set(buildRedisKey(token.getId()), token, 30, TimeUnit.MINUTES);
+ return token;
+ }
+
+ // Retrieve token from cache or Redis
+ @Cacheable(value = "tokens", key = "#id")
+ public Token getToken(Integer id) {
+ // This will only execute if the token is not found in the cache
+ return redisTemplate.opsForValue().get(buildRedisKey(id));
+ }
+
+ // Remove token from Redis and cache
+ @CacheEvict(value = "tokens", key = "#id")
+ public void deleteToken(Integer id) {
+ redisTemplate.delete(buildRedisKey(id));
+ }
+
+ private String buildRedisKey(Integer id) {
+ return "TOKEN_" + id;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/token/TokenType.java b/security/security/src/main/java/com/roba/security/token/TokenType.java
new file mode 100644
index 0000000..59f32a6
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/token/TokenType.java
@@ -0,0 +1,5 @@
+package com.roba.security.token;
+
+public enum TokenType {
+ BEARER
+}
diff --git a/security/security/src/main/java/com/roba/security/user/AuthenticateCommand.java b/security/security/src/main/java/com/roba/security/user/AuthenticateCommand.java
new file mode 100644
index 0000000..0d388e9
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/AuthenticateCommand.java
@@ -0,0 +1,30 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationRequest;
+import com.roba.security.auth.AuthenticationResponse;
+import com.roba.security.auth.AuthenticationService;
+
+public class AuthenticateCommand implements Command {
+ private final AuthenticationService service;
+ private final AuthenticationRequest request;
+ private AuthenticationResponse result;
+ public AuthenticateCommand(AuthenticationService service, AuthenticationRequest request) {
+ this.service = service;
+ this.request = request;
+ }
+
+ @Override
+ public void execute() {
+ result = service.authenticate(request);
+ }
+ @Override
+ public AuthenticationResponse getResult() {
+ return result;
+ }
+}
+
+
+
+
+
+
diff --git a/security/security/src/main/java/com/roba/security/user/ChangePasswordCommand.java b/security/security/src/main/java/com/roba/security/user/ChangePasswordCommand.java
new file mode 100644
index 0000000..0774998
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/ChangePasswordCommand.java
@@ -0,0 +1,28 @@
+package com.roba.security.user;
+
+
+import com.roba.security.auth.AuthenticationResponse;
+import com.roba.security.auth.AuthenticationService;
+
+public class ChangePasswordCommand implements Command {
+ private final AuthenticationService userService;
+ private final Integer userId;
+ private final ChangePasswordRequest request;
+
+ public ChangePasswordCommand(AuthenticationService userService, Integer userId, ChangePasswordRequest request) {
+ this.userService = userService;
+ this.userId = userId;
+ this.request = request;
+ }
+
+ @Override
+ public void execute() {
+ userService.changeUserPassword(userId, request);
+ }
+
+ @Override
+ public AuthenticationResponse getResult() {
+ return null;
+ }
+}
+
diff --git a/security/security/src/main/java/com/roba/security/user/ChangePasswordRequest.java b/security/security/src/main/java/com/roba/security/user/ChangePasswordRequest.java
new file mode 100644
index 0000000..ae9b85e
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/ChangePasswordRequest.java
@@ -0,0 +1,11 @@
+package com.roba.security.user;
+
+
+import lombok.Data;
+
+@Data
+public class ChangePasswordRequest {
+ private String currentPassword;
+ private String newPassword;
+ // private String workEmail;
+}
diff --git a/security/security/src/main/java/com/roba/security/user/Command.java b/security/security/src/main/java/com/roba/security/user/Command.java
new file mode 100644
index 0000000..6362e4d
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/Command.java
@@ -0,0 +1,8 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationResponse;
+
+public interface Command {
+ void execute();
+ AuthenticationResponse getResult();
+}
diff --git a/security/security/src/main/java/com/roba/security/user/CommandFactory.java b/security/security/src/main/java/com/roba/security/user/CommandFactory.java
new file mode 100644
index 0000000..38d5d9d
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/CommandFactory.java
@@ -0,0 +1,47 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationRequest;
+import com.roba.security.auth.AuthenticationService;
+import com.roba.security.auth.RegisterRequest;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Optional;
+
+@Component
+public class CommandFactory {
+ private final AuthenticationService userService;
+
+ public CommandFactory(AuthenticationService userService) {
+ this.userService = userService;
+ }
+
+ public Command createUpdateProfileCommand(Integer userId, UserProfileUpdateRequest request) {
+ return new UpdateProfileCommand(userService, userId, request);
+ }
+
+ public Command createChangePasswordCommand(Integer userId, ChangePasswordRequest request) {
+ return new ChangePasswordCommand(userService, userId, request);
+ }
+ public Command createGetAllUsersCommand() {
+ return new GetAllUsersCommand(userService);
+ }
+ public Command createGetUserByIdCommand(Integer userId) {
+ return new GetUserByIdCommand(userId, userService);}
+
+ public Command createGetUsersByRoleCommand(Role role) {
+ return new GetUsersByRoleCommand(role, userService);
+ }
+ public Command createRegisterCommand(RegisterRequest request) {
+ return new RegisterCommand(userService, request);
+ }
+
+ public Command createAuthenticateCommand(AuthenticationRequest request) {
+ return new AuthenticateCommand(userService, request);
+ }
+
+
+
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/user/GetAllUsersCommand.java b/security/security/src/main/java/com/roba/security/user/GetAllUsersCommand.java
new file mode 100644
index 0000000..5f7ea63
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/GetAllUsersCommand.java
@@ -0,0 +1,24 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationResponse;
+import com.roba.security.auth.AuthenticationService;
+
+import java.util.List;
+
+public class GetAllUsersCommand implements Command {
+ private final AuthenticationService userService;
+
+ public GetAllUsersCommand(AuthenticationService userService) {
+ this.userService = userService;
+ }
+
+ @Override
+ public void execute() {
+ userService.getAllUsers();
+ }
+
+ @Override
+ public AuthenticationResponse getResult() {
+ return null;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/user/GetUserByIdCommand.java b/security/security/src/main/java/com/roba/security/user/GetUserByIdCommand.java
new file mode 100644
index 0000000..6f601ad
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/GetUserByIdCommand.java
@@ -0,0 +1,26 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationResponse;
+import com.roba.security.auth.AuthenticationService;
+
+import java.util.Optional;
+
+public class GetUserByIdCommand implements Command {
+ private final Integer userId;
+ private final AuthenticationService userService;
+
+ public GetUserByIdCommand(Integer userId, AuthenticationService userService) {
+ this.userId = userId;
+ this.userService = userService;
+ }
+
+ @Override
+ public void execute() {
+ userService.getUserById(userId);
+ }
+
+ @Override
+ public AuthenticationResponse getResult() {
+ return null;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/user/GetUsersByRoleCommand.java b/security/security/src/main/java/com/roba/security/user/GetUsersByRoleCommand.java
new file mode 100644
index 0000000..5aef022
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/GetUsersByRoleCommand.java
@@ -0,0 +1,28 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationResponse;
+import com.roba.security.auth.AuthenticationService;
+
+import java.util.List;
+
+public class GetUsersByRoleCommand implements Command {
+
+
+ private final Role role;
+ private final AuthenticationService userService;
+
+ public GetUsersByRoleCommand(Role role, AuthenticationService userService) {
+ this.role = role;
+ this.userService = userService;
+ }
+
+ @Override
+ public void execute() {
+ userService.getUsersByRole(role);
+ }
+
+ @Override
+ public AuthenticationResponse getResult() {
+ return null;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/user/Permission.java b/security/security/src/main/java/com/roba/security/user/Permission.java
new file mode 100644
index 0000000..be24339
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/Permission.java
@@ -0,0 +1,60 @@
+package com.roba.security.user;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public enum Permission {
+
+ PROJECT_READ("project:read"),
+ PROJECT_UPDATE("project:update"),
+ PROJECT_CREATE("project:create"),
+ PROJECT_DELETE("project:delete"),
+ ORGANIZATION_CREATE("organization:create"),
+ ORGANIZATION_DELETE("organization:delete"),
+ ORGANIZATION_UPDATE("organization:update"),//INVITE USERS=ADD MEMBERS
+ ORGANIZATION_READ("organization:read"),//VIEW MEMBERS
+
+ PAYMENT_CREATE("payment:create"),
+ PAYMEMT_DELETE("payment:delete"),
+ PAYMENT_UPDATE("payment:update"),
+ PAYMENT_READ("payment:read"),
+
+ PAYROLL_CREATE("payment:create"),
+ PAYROLL_DELETE("payment:delete"),
+ PAYROLL_UPDATE("payment:update"),
+ PAYROLL_READ("payment:read"),
+
+ TEAMINVOICE_CREATE("invoice:create"),
+ TEAMINVOICE_DELETE("invoice:delete"),
+ TEAMINVOICE_UPDATE("invoice:update"),
+ TEAMINVOICE_READ("invoice:read"),
+
+
+ CLIENTINVOICE_CREATE("invoice:create"),
+ CLIENTINVOICE_DELETE("invoice:delete"),
+ CLIENTINVOICE_UPDATE("invoice:update"),
+ CLIENTINVOICE_READ("invoice:read"),
+
+
+ TIMESHEET_CREATE("timesheets:create"),
+ TIMESHEET_DELETE("timesheets:delete"),
+ TIMESHEET_UPDATE("timesheets:update"),
+ TIMESHEET_READ("timesheets:read"),
+ REPORTS_CREATE("reports:create"),
+ REPORTS_DELETE("reports:delete"),
+ REPORTS_UPDATE("reports:update"),
+ REPORTS_READ("reports:read"),
+
+
+
+
+
+
+ ;
+
+
+
+ @Getter
+ private final String permission;
+}
diff --git a/security/security/src/main/java/com/roba/security/user/RegisterCommand.java b/security/security/src/main/java/com/roba/security/user/RegisterCommand.java
new file mode 100644
index 0000000..b4c7e4c
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/RegisterCommand.java
@@ -0,0 +1,27 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationResponse;
+import com.roba.security.auth.AuthenticationService;
+import com.roba.security.auth.RegisterRequest;
+
+public class RegisterCommand implements Command {
+ private final AuthenticationService service;
+ private final RegisterRequest request;
+ private AuthenticationResponse result;
+
+ public RegisterCommand(AuthenticationService service, RegisterRequest request) {
+ this.service = service;
+ this.request = request;
+ }
+
+ @Override
+ public void execute() {
+ result = service.register(request);
+ }
+ @Override
+ public AuthenticationResponse getResult() {
+ return result;
+ }
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/user/ResourceNotFoundException.java b/security/security/src/main/java/com/roba/security/user/ResourceNotFoundException.java
new file mode 100644
index 0000000..2f669eb
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/ResourceNotFoundException.java
@@ -0,0 +1,12 @@
+package com.roba.security.user;
+
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(HttpStatus.NOT_FOUND)
+public class ResourceNotFoundException extends RuntimeException {
+ public ResourceNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/user/Role.java b/security/security/src/main/java/com/roba/security/user/Role.java
new file mode 100644
index 0000000..e5ee41d
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/Role.java
@@ -0,0 +1,47 @@
+package com.roba.security.user;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.roba.security.user.Permission.*;
+
+
+@RequiredArgsConstructor
+
+public enum Role {
+ USER(Collections.emptySet()),
+
+ OWNER(Set.of(PROJECT_READ,
+ PROJECT_UPDATE,
+ PROJECT_DELETE,
+ PROJECT_CREATE,
+ PAYMENT_READ,
+ PAYMENT_UPDATE,
+ PAYMENT_CREATE
+
+
+ )),
+
+ ORGANIZATION_MANAGER(Set.of(PROJECT_READ,
+ PROJECT_UPDATE,
+ PROJECT_DELETE,
+ PROJECT_CREATE)),
+ PROJECT_MANAGER(Collections.emptySet());
+
+@Getter
+private final Set permissions;
+public List getAuthorities(){
+ var authorities=getPermissions()
+ .stream()
+ .map(permission -> new SimpleGrantedAuthority(permission.getPermission()))
+ .collect(Collectors.toList());
+ authorities.add(new SimpleGrantedAuthority("ROLE_"+this.name()));
+ return authorities;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/user/UnauthorizedException.java b/security/security/src/main/java/com/roba/security/user/UnauthorizedException.java
new file mode 100644
index 0000000..0dfa3d2
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/UnauthorizedException.java
@@ -0,0 +1,11 @@
+package com.roba.security.user;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(HttpStatus.UNAUTHORIZED)
+public class UnauthorizedException extends RuntimeException {
+ public UnauthorizedException(String message) {
+ super(message);
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/user/UpdateProfileCommand.java b/security/security/src/main/java/com/roba/security/user/UpdateProfileCommand.java
new file mode 100644
index 0000000..10a83e1
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/UpdateProfileCommand.java
@@ -0,0 +1,27 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationResponse;
+import com.roba.security.auth.AuthenticationService;
+
+public class UpdateProfileCommand implements Command{
+ private final AuthenticationService userService;
+ private final Integer userId;
+ private final UserProfileUpdateRequest request;
+
+
+ public UpdateProfileCommand(AuthenticationService userService, Integer userId, UserProfileUpdateRequest request) {
+ this.userService = userService;
+ this.userId = userId;
+ this.request = request;
+ }
+
+ @Override
+ public void execute() {
+ userService.updateUserProfile(userId, request);
+ }
+
+ @Override
+ public AuthenticationResponse getResult() {
+ return null;
+ }
+}
diff --git a/security/security/src/main/java/com/roba/security/User.java b/security/security/src/main/java/com/roba/security/user/User.java
similarity index 50%
rename from security/security/src/main/java/com/roba/security/User.java
rename to security/security/src/main/java/com/roba/security/user/User.java
index 42a8933..b749f62 100644
--- a/security/security/src/main/java/com/roba/security/User.java
+++ b/security/security/src/main/java/com/roba/security/user/User.java
@@ -1,13 +1,18 @@
-package com.roba.security;
+package com.roba.security.user;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.roba.security.Project.Project;
+import com.roba.security.organization.Organization;
+import com.roba.security.token.Token;
import jakarta.persistence.*;
import lombok.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
-import javax.management.relation.Role;
+
+import java.io.Serializable;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
@@ -20,7 +25,8 @@
@Builder
@Data
@Table(name="_user")
-public class User implements UserDetails {
+@EqualsAndHashCode
+public class User implements UserDetails, Serializable {
@Id
@SequenceGenerator(
name="user_id_sequence",
@@ -36,13 +42,54 @@ public class User implements UserDetails {
private String password;
@Enumerated(EnumType.STRING)
private Role role;
- private LocalDate joinDate;
- //foreign key to organization table
- private Integer organizationId;
+ @OneToMany(mappedBy = "user")
+ @JsonIgnore
+ private List tokens;
+
+
+
+ private String Department;
+ private String Position;//Title
+
+
+ @ManyToOne
+ @JoinColumn(name="organization_id")
+ // This specifies the foreign key column name in the User table
+
+ @JsonIgnore
+ private Organization organization; // Reference to organization)
+
+
+ @OneToMany
+ private List projects;
+ private String TimeZone;
+ private LocalDate hireDate;
+ private double hourlyRate;
+ private double salary;
+ private String taxInfo;
+ private Integer usedTimeOff;
+ private Integer pendingTimeOff;
+ private Integer balanceTimeOff;
+ private double totalHoursWorked;
+ private double WeeklyLimit;
+
+
+ private LocalDate DateRemoved;
+ private String PayType;//hourly/fixed
+ private Integer BillRate;
+
+ private Integer DailyLimit;
+ private boolean TrackingEnabled;
+ private boolean TimesheetsEnabled;
+ private String Status;
+ // private List teams;
+
+
+
@Override
public Collection extends GrantedAuthority> getAuthorities() {
- return List.of(new SimpleGrantedAuthority(role.getRoleName()));
+ return role.getAuthorities();
}
@Override
diff --git a/security/security/src/main/java/com/roba/security/user/UserController.java b/security/security/src/main/java/com/roba/security/user/UserController.java
new file mode 100644
index 0000000..f1dd4cd
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/UserController.java
@@ -0,0 +1,83 @@
+package com.roba.security.user;
+
+import com.roba.security.auth.AuthenticationService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import java.util.Optional;
+import java.util.List;
+ import com.roba.security.user.CommandFactory;
+@RestController
+@RequestMapping("/api/users")
+@RequiredArgsConstructor
+public class UserController {
+
+ private final CommandFactory commandFactory;
+ // @Autowired
+ private final AuthenticationService userService;
+
+ @PutMapping("/{userId}/profile")
+// public ResponseEntity> updateProfile(@PathVariable("userId") Integer userId, @RequestBody UserProfileUpdateRequest request) {
+// System.out.println("gg");
+// userService.updateUserProfile(userId, request);
+// return ResponseEntity.ok().build();
+// }
+
+ public ResponseEntity> updateProfile(@PathVariable("userId") Integer userId, @RequestBody UserProfileUpdateRequest request) {
+ Command command = commandFactory.createUpdateProfileCommand(userId, request);
+ command.execute();
+ return ResponseEntity.ok().build();
+ }
+
+
+ @PutMapping("/{userId}/password")
+// public ResponseEntity> changePassword(@PathVariable("userId") Integer userId, @RequestBody ChangePasswordRequest request) {
+// userService.changeUserPassword(userId, request);
+// return ResponseEntity.ok().build();
+// }
+ public ResponseEntity> changePassword(@PathVariable("userId") Integer userId, @RequestBody ChangePasswordRequest request) {
+ Command command = commandFactory.createChangePasswordCommand(userId, request);
+ command.execute();
+ return ResponseEntity.ok().build();
+ }
+
+
+ @GetMapping("/all")
+ public List getAllUsers() {
+ Command command = commandFactory.createGetAllUsersCommand();
+ command.execute();
+ return userService.getAllUsers();
+ }
+
+
+ @GetMapping("/{userId}")
+ @Cacheable(key="#id",value="User")
+ public Optional getUserById(@PathVariable Integer userId) {
+ Command command = commandFactory.createGetUserByIdCommand(userId);
+ command.execute();
+ return userService.getUserById(userId);
+ }
+
+ @GetMapping("/role/{role}")
+ public List getUsersByRole(@PathVariable Role role) {
+ Command command = commandFactory.createGetUsersByRoleCommand(role);
+ command.execute();
+ return userService.getUsersByRole(role);
+ }
+
+//
+// @DeleteMapping("/{userId}")
+// public ResponseEntity> deleteUserById(@PathVariable("userId") Integer userId) {
+// Command command = commandFactory.createDeleteUserCommand(userId);
+// command.execute();
+// userService.deleteUserById(userId);
+// return ResponseEntity.ok().build();
+// }
+
+
+
+
+
+}
diff --git a/security/security/src/main/java/com/roba/security/user/UserProfileUpdateRequest.java b/security/security/src/main/java/com/roba/security/user/UserProfileUpdateRequest.java
new file mode 100644
index 0000000..955376e
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/UserProfileUpdateRequest.java
@@ -0,0 +1,12 @@
+package com.roba.security.user;
+
+import lombok.Data;
+
+@Data
+public class UserProfileUpdateRequest {
+ private String fullName;
+ private String WorkEmail;
+
+
+ // Add other fields as needed for profile update
+}
diff --git a/security/security/src/main/java/com/roba/security/user/UserRepository.java b/security/security/src/main/java/com/roba/security/user/UserRepository.java
new file mode 100644
index 0000000..ce88755
--- /dev/null
+++ b/security/security/src/main/java/com/roba/security/user/UserRepository.java
@@ -0,0 +1,14 @@
+package com.roba.security.user;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface UserRepository extends JpaRepository {
+ Optional findByworkEmail(String workEmail);
+
+ List findByRole(Role role);
+
+ // Optional findByWorkEmail(String workEmail);
+}
diff --git a/security/security/src/main/resources/application.yml b/security/security/src/main/resources/application.yml
index aa957fb..e6d1afc 100644
--- a/security/security/src/main/resources/application.yml
+++ b/security/security/src/main/resources/application.yml
@@ -22,6 +22,19 @@ spring:
show_sql: true
database: postgresql
database-platform: org.hibernate.dialect.PostgreSQLDialect
-
+ cache:
+ type: redis
+ redis:
+ host: redis-12006.c62.us-east-1-4.ec2.redns.redis-cloud.com
+ port: 12006
+ password: oSrE2KvyJdxFJ8vmpDlIBDtQ9ZriadjR
+ database: 0
+ timeout: 60000 # Optional: Timeout in milliseconds for connection (60 seconds)
+ jedis:
+ pool:
+ max-active: 8
+ max-wait: -1ms
+ max-idle: 8
+ min-idle: 0
diff --git a/user/src/main/java/com/roba/user/User.java b/user/src/main/java/com/roba/user/User.java
index 2006641..946f6b2 100644
--- a/user/src/main/java/com/roba/user/User.java
+++ b/user/src/main/java/com/roba/user/User.java
@@ -1,34 +1,34 @@
-package com.roba.user;
-
-import jakarta.persistence.*;
-import lombok.*;
-
-import java.time.LocalDate;
-
-@Entity
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-@Builder
-@Data
-@Table(name="_user")
-public class User {
- @Id
- @SequenceGenerator(
- name="user_id_sequence",
- sequenceName="user_id_sequence"
- )
- @GeneratedValue(
- strategy = GenerationType.SEQUENCE,
- generator = "user_id_seqeunce"
- )
- private Integer id;
- private String fullName;
- private String workEmail;
- private String password;
- private String role;
- private LocalDate joinDate;
- private Integer organizationId;
-
-}
+//package com.roba.user;
+//
+//import jakarta.persistence.*;
+//import lombok.*;
+//
+//import java.time.LocalDate;
+//
+//@Entity
+//@Getter
+//@Setter
+//@AllArgsConstructor
+//@NoArgsConstructor
+//@Builder
+//@Data
+//@Table(name="_user")
+//public class User {
+// @Id
+// @SequenceGenerator(
+// name="user_id_sequence",
+// sequenceName="user_id_sequence"
+// )
+// @GeneratedValue(
+// strategy = GenerationType.SEQUENCE,
+// generator = "user_id_seqeunce"
+// )
+// private Integer id;
+// private String fullName;
+// private String workEmail;
+// private String password;
+// private String role;
+// private LocalDate joinDate;
+// private Integer organizationId;
+//
+//}
diff --git a/user/src/main/java/com/roba/user/UserController.java b/user/src/main/java/com/roba/user/UserController.java
index eb2e723..f4cfac6 100644
--- a/user/src/main/java/com/roba/user/UserController.java
+++ b/user/src/main/java/com/roba/user/UserController.java
@@ -1,36 +1,36 @@
-package com.roba.user;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-
-@RestController
-@RequestMapping("api/v1/users")
-@RequiredArgsConstructor
-public class UserController {
-private final UserService service;
- private final UserService userService;
-
- @PostMapping
- @ResponseStatus(HttpStatus.CREATED)
-// public void save(@RequestBody User user){
-// service.saveUser(user);
+//package com.roba.user;
//
+//import lombok.RequiredArgsConstructor;
+//import lombok.extern.slf4j.Slf4j;
+//
+//import org.springframework.http.HttpStatus;
+//import org.springframework.http.ResponseEntity;
+//import org.springframework.web.bind.annotation.*;
+//
+//import java.util.List;
+//
+//
+//@RestController
+//@RequestMapping("api/v1/users")
+//@RequiredArgsConstructor
+//public class UserController {
+//private final UserService service;
+// private final UserService userService;
+//
+// @PostMapping
+// @ResponseStatus(HttpStatus.CREATED)
+//// public void save(@RequestBody User user){
+//// service.saveUser(user);
+////
+//// }
+// public void createUser(@RequestBody UserRequest userRequest){
+// userService.createUser(userRequest);
+//
+// }
+//
+// @GetMapping
+// @ResponseStatus(HttpStatus.OK)
+// public List getAllUsers(){
+// return userService.getAllUsers();
// }
- public void createUser(@RequestBody UserRequest userRequest){
- userService.createUser(userRequest);
-
- }
-
- @GetMapping
- @ResponseStatus(HttpStatus.OK)
- public List getAllUsers(){
- return userService.getAllUsers();
- }
-}
+//}
diff --git a/user/src/main/java/com/roba/user/UserRepository.java b/user/src/main/java/com/roba/user/UserRepository.java
index f18c563..e6fc952 100644
--- a/user/src/main/java/com/roba/user/UserRepository.java
+++ b/user/src/main/java/com/roba/user/UserRepository.java
@@ -1,6 +1,6 @@
-package com.roba.user;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface UserRepository extends JpaRepository {
-}
+//package com.roba.user;
+//
+//import org.springframework.data.jpa.repository.JpaRepository;
+//
+//public interface UserRepository extends JpaRepository {
+//}
diff --git a/user/src/main/java/com/roba/user/UserService.java b/user/src/main/java/com/roba/user/UserService.java
index ae3ad91..ecbac7a 100644
--- a/user/src/main/java/com/roba/user/UserService.java
+++ b/user/src/main/java/com/roba/user/UserService.java
@@ -1,39 +1,39 @@
-package com.roba.user;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@RequiredArgsConstructor
-@Slf4j
-public class UserService {
-
-
- private final UserRepository userRepository;
-// public void saveUser(User user) {
+//package com.roba.user;
//
+//import lombok.RequiredArgsConstructor;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Service;
//
+//import java.util.List;
+//
+//@Service
+//@RequiredArgsConstructor
+//@Slf4j
+//public class UserService {
+//
+//
+// private final UserRepository userRepository;
+//// public void saveUser(User user) {
+////
+////
+//// userRepository.save(user);
+//// }
+//
+// public void createUser(UserRequest userRequest) {
+// User user = User.builder().fullName(userRequest.getFullName())
+// .workEmail(userRequest.getWorkEmail()).password(userRequest.getPassword()).role(userRequest.getRole()).build();
// userRepository.save(user);
+// log.info("is saved user: {}", user);
// }
-
- public void createUser(UserRequest userRequest) {
- User user = User.builder().fullName(userRequest.getFullName())
- .workEmail(userRequest.getWorkEmail()).password(userRequest.getPassword()).role(userRequest.getRole()).build();
- userRepository.save(user);
- log.info("is saved user: {}", user);
- }
-
- public List getAllUsers(){
- List users= userRepository.findAll();
- return users.stream().map(this::mapToUserResponse).toList();
- }
- private UserResponse mapToUserResponse (User user ){
- return UserResponse.builder().
- id(user.getId())
- .fullName(user.getFullName()).workEmail(user.getWorkEmail()).password(user.getPassword()).role(user.getRole()).build();
- }
-
-}
+//
+// public List getAllUsers(){
+// List users= userRepository.findAll();
+// return users.stream().map(this::mapToUserResponse).toList();
+// }
+// private UserResponse mapToUserResponse (User user ){
+// return UserResponse.builder().
+// id(user.getId())
+// .fullName(user.getFullName()).workEmail(user.getWorkEmail()).password(user.getPassword()).role(user.getRole()).build();
+// }
+//
+//}