added uptime monitoring
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package zw.qantra.tm.domain.controllers;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import zw.qantra.tm.domain.models.Uptime;
|
||||
import zw.qantra.tm.domain.services.UptimeService;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/public/uptimes")
|
||||
@RequiredArgsConstructor
|
||||
public class UptimeController {
|
||||
|
||||
private final UptimeService uptimeService;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity getAllUptimes(Pageable pageable) {
|
||||
return ResponseEntity.ok(uptimeService.getAllUptimes(pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity getUptime(@PathVariable UUID id) {
|
||||
return uptimeService.getUptime(id)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package zw.qantra.tm.domain.controllers;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.kaczmarzyk.spring.data.jpa.domain.Equal;
|
||||
import net.kaczmarzyk.spring.data.jpa.domain.EqualIgnoreCase;
|
||||
import net.kaczmarzyk.spring.data.jpa.domain.LikeIgnoreCase;
|
||||
import net.kaczmarzyk.spring.data.jpa.web.annotation.And;
|
||||
import net.kaczmarzyk.spring.data.jpa.web.annotation.Join;
|
||||
import net.kaczmarzyk.spring.data.jpa.web.annotation.Spec;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import zw.qantra.tm.domain.models.User;
|
||||
import zw.qantra.tm.domain.services.UserService;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/users")
|
||||
@RequiredArgsConstructor
|
||||
public class UserController {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity findAllUsers(
|
||||
@Join(path = "workspaces", alias = "w")
|
||||
@And({
|
||||
@Spec(path = "username", defaultVal = "null", spec = LikeIgnoreCase.class),
|
||||
@Spec(path = "email", spec = EqualIgnoreCase.class),
|
||||
@Spec(path = "firstName", spec = LikeIgnoreCase.class),
|
||||
@Spec(path = "lastName", spec = LikeIgnoreCase.class),
|
||||
@Spec(path = "phone", spec = EqualIgnoreCase.class),
|
||||
@Spec(path = "w.id", params = "workspaceId", spec = Equal.class)
|
||||
}) Specification<User> spec, Pageable pageable) {
|
||||
return ResponseEntity.ok(userService.findAllUsers(spec, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/workspace")
|
||||
public ResponseEntity searchAllUsers(
|
||||
@Join(path = "workspaces", alias = "w")
|
||||
@And({
|
||||
@Spec(path = "username", spec = LikeIgnoreCase.class),
|
||||
@Spec(path = "email", spec = EqualIgnoreCase.class),
|
||||
@Spec(path = "firstName", spec = LikeIgnoreCase.class),
|
||||
@Spec(path = "lastName", spec = LikeIgnoreCase.class),
|
||||
@Spec(path = "phone", spec = EqualIgnoreCase.class),
|
||||
@Spec(path = "w.id", params = "workspaceId", defaultVal = "null", spec = Equal.class)
|
||||
}) Specification<User> spec, Pageable pageable) {
|
||||
return ResponseEntity.ok(userService.findAllUsers(spec, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity getUser(@PathVariable UUID id) {
|
||||
return userService.getUser(id)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity updateUser(@PathVariable UUID id, @RequestBody User user) {
|
||||
try {
|
||||
User updated = userService.updateUser(id, user);
|
||||
return ResponseEntity.ok(updated);
|
||||
} catch (RuntimeException e) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity deleteUser(@PathVariable UUID id) {
|
||||
if (userService.deleteUser(id)) {
|
||||
return ResponseEntity.ok(Map.of("message", "User deleted successfully"));
|
||||
}
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
@@ -59,14 +59,6 @@ public class WorkspaceController {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity deleteWorkspace(@PathVariable UUID id) {
|
||||
if (workspaceService.deleteWorkspace(id)) {
|
||||
return ResponseEntity.ok(Map.of("message", "Workspace deleted successfully"));
|
||||
}
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/users/{userId}")
|
||||
public ResponseEntity associateUser(@PathVariable UUID workspaceId, @PathVariable UUID userId) {
|
||||
return workspaceService.associateUser(workspaceId, userId)
|
||||
|
||||
24
src/main/java/zw/qantra/tm/domain/models/Uptime.java
Normal file
24
src/main/java/zw/qantra/tm/domain/models/Uptime.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package zw.qantra.tm.domain.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.hibernate.annotations.SQLRestriction;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@SQLRestriction("deleted = false")
|
||||
public class Uptime extends BaseEntity {
|
||||
private String name;
|
||||
private boolean status;
|
||||
}
|
||||
@@ -25,7 +25,8 @@ public class User extends BaseEntity implements UserDetails {
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String username;
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@Column(nullable = false)
|
||||
private String password;
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package zw.qantra.tm.domain.repositories;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import zw.qantra.tm.domain.models.Uptime;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface UptimeRepository extends JpaRepository<Uptime, UUID>, JpaSpecificationExecutor<Uptime> {
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package zw.qantra.tm.domain.repositories;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import zw.qantra.tm.domain.models.User;
|
||||
|
||||
@@ -8,7 +9,7 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
|
||||
Optional<User> findById(UUID uid);
|
||||
Optional<User> findByUsername(String username);
|
||||
Optional<User> findByEmail(String email);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package zw.qantra.tm.domain.services;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zw.qantra.tm.domain.models.Uptime;
|
||||
import zw.qantra.tm.domain.repositories.UptimeRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UptimeService {
|
||||
private final UptimeRepository uptimeRepository;
|
||||
|
||||
public Page<Uptime> getAllUptimes(Pageable pageable) {
|
||||
return uptimeRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
public Optional<Uptime> getUptime(UUID id) {
|
||||
return uptimeRepository.findById(id);
|
||||
}
|
||||
|
||||
public Uptime createUptime(Uptime uptime) {
|
||||
return uptimeRepository.save(uptime);
|
||||
}
|
||||
|
||||
public Uptime updateUptime(UUID id, Uptime uptime) {
|
||||
if (uptimeRepository.existsById(id)) {
|
||||
uptime.setId(id);
|
||||
return uptimeRepository.save(uptime);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean deleteUptime(UUID id) {
|
||||
if (uptimeRepository.existsById(id)) {
|
||||
uptimeRepository.deleteById(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,27 @@ package zw.qantra.tm.domain.services;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
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.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import zw.qantra.tm.domain.dtos.AuthResponse;
|
||||
import zw.qantra.tm.domain.dtos.LoginRequest;
|
||||
import zw.qantra.tm.domain.dtos.RegisterRequest;
|
||||
import zw.qantra.tm.domain.models.User;
|
||||
import zw.qantra.tm.domain.models.Workspace;
|
||||
import zw.qantra.tm.domain.repositories.UserRepository;
|
||||
import zw.qantra.tm.utils.JwtUtils;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserService implements UserDetailsService {
|
||||
@@ -23,6 +32,7 @@ public class UserService implements UserDetailsService {
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final JwtUtils jwtUtils;
|
||||
private final TransactionService transactionService;
|
||||
private final WorkspaceService workspaceService;
|
||||
|
||||
public User fetchUserByUsername(String username) {
|
||||
return userRepository.findByUsername(username)
|
||||
@@ -83,4 +93,52 @@ public class UserService implements UserDetailsService {
|
||||
return new AuthResponse(token, "Bearer", user.getUsername(),
|
||||
user.getEmail(), user.getPhone(), user.getFirstName(), user.getLastName(), user.getId());
|
||||
}
|
||||
|
||||
public Page<User> findAllUsers(Specification<User> spec, Pageable pageable) {
|
||||
return userRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
public Optional<User> getUser(UUID id) {
|
||||
return userRepository.findById(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User createUser(User user) {
|
||||
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||
user.setDeleted(false);
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User updateUser(UUID id, User userDetails) {
|
||||
return userRepository.findById(id)
|
||||
.map(existingUser -> {
|
||||
existingUser.setFirstName(userDetails.getFirstName());
|
||||
existingUser.setLastName(userDetails.getLastName());
|
||||
existingUser.setEmail(userDetails.getEmail());
|
||||
existingUser.setPhone(userDetails.getPhone());
|
||||
existingUser.setPhotoUrl(userDetails.getPhotoUrl());
|
||||
existingUser.setWorkflowId(userDetails.getWorkflowId());
|
||||
existingUser.setEnabled(userDetails.isEnabled());
|
||||
existingUser.setAccountNonExpired(userDetails.isAccountNonExpired());
|
||||
existingUser.setAccountNonLocked(userDetails.isAccountNonLocked());
|
||||
existingUser.setCredentialsNonExpired(userDetails.isCredentialsNonExpired());
|
||||
if (userDetails.getPassword() != null && !userDetails.getPassword().isEmpty()) {
|
||||
existingUser.setPassword(passwordEncoder.encode(userDetails.getPassword()));
|
||||
}
|
||||
return userRepository.save(existingUser);
|
||||
})
|
||||
.orElseThrow(() -> new RuntimeException("User not found with id: " + id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean deleteUser(UUID id) {
|
||||
return userRepository.findById(id)
|
||||
.map(user -> {
|
||||
user.setDeleted(true);
|
||||
userRepository.save(user);
|
||||
return true;
|
||||
})
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import zw.qantra.tm.domain.models.User;
|
||||
import zw.qantra.tm.domain.models.Workspace;
|
||||
import zw.qantra.tm.domain.repositories.UserRepository;
|
||||
import zw.qantra.tm.domain.repositories.WorkspaceRepository;
|
||||
import zw.qantra.tm.exceptions.ApiException;
|
||||
import zw.qantra.tm.utils.SecurityUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -69,6 +71,15 @@ public class WorkspaceService {
|
||||
|
||||
@Transactional
|
||||
public Optional<Workspace> disassociateUser(UUID workspaceId, UUID userId) {
|
||||
// Prevent a user from disassociating themselves from their own workspace
|
||||
String currentUsername = SecurityUtils.getCurrentUsername();
|
||||
if (currentUsername != null) {
|
||||
User currentUser = userRepository.findByUsername(currentUsername).orElse(null);
|
||||
if (currentUser != null && currentUser.getId().equals(userId)) {
|
||||
throw new ApiException("You cannot remove yourself from the workspace");
|
||||
}
|
||||
}
|
||||
|
||||
Workspace workspace = workspaceRepository.findById(workspaceId).orElse(null);
|
||||
User user = userRepository.findById(userId).orElse(null);
|
||||
if (workspace == null || user == null) {
|
||||
|
||||
Reference in New Issue
Block a user