Index: ReserveNGo-backend/pom.xml
===================================================================
--- ReserveNGo-backend/pom.xml	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/pom.xml	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -75,4 +75,9 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+            <version>3.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/ReserveNGoApplication.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/ReserveNGoApplication.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/ReserveNGoApplication.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -3,10 +3,9 @@
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
 import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 @EnableJpaAuditing
+@EnableScheduling
 @SpringBootApplication
 public class ReserveNGoApplication {
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/WebSecurityConfig.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/WebSecurityConfig.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/WebSecurityConfig.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -2,4 +2,5 @@
 
 import mk.ukim.finki.it.reservengo.config.filter.JWTAuthenticationFilter;
+import mk.ukim.finki.it.reservengo.config.filter.UserActivityFilter;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -26,8 +27,10 @@
     private final JWTAuthenticationFilter jwtAuthFilter;
     private final AuthenticationProvider authenticationProvider;
+    private final UserActivityFilter userActivityFilter;
 
-    public WebSecurityConfig(JWTAuthenticationFilter jwtAuthFilter, AuthenticationProvider authenticationProvider) {
+    public WebSecurityConfig(JWTAuthenticationFilter jwtAuthFilter, AuthenticationProvider authenticationProvider, UserActivityFilter userActivityFilter) {
         this.jwtAuthFilter = jwtAuthFilter;
         this.authenticationProvider = authenticationProvider;
+        this.userActivityFilter = userActivityFilter;
     }
 
@@ -59,5 +62,6 @@
                 )
                 .authenticationProvider(authenticationProvider)
-                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
+                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
+                .addFilterAfter(userActivityFilter, JWTAuthenticationFilter.class);
 
         return http.build();
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/JWTAuthenticationFilter.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/JWTAuthenticationFilter.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/JWTAuthenticationFilter.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -47,5 +47,5 @@
         if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
             UserDetails userDetails = userDetailsService.loadUserByUsername(userEmail);
-            if (jwtService.isTokenValid(jwt, userDetails)) {
+            if (jwtService.isTokenValid(jwt, userDetails) && userDetails.isEnabled()) {
                 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                 authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/UserActivityFilter.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/UserActivityFilter.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/UserActivityFilter.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -0,0 +1,38 @@
+package mk.ukim.finki.it.reservengo.config.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.NonNull;
+import mk.ukim.finki.it.reservengo.model.domain.User;
+import mk.ukim.finki.it.reservengo.service.intf.UserService;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+@Component
+public class UserActivityFilter extends OncePerRequestFilter {
+    private final UserService userService;
+
+    public UserActivityFilter(UserService userService) {
+        this.userService = userService;
+    }
+
+    @Override
+    protected void doFilterInternal(@NonNull HttpServletRequest request,
+                                    @NonNull HttpServletResponse response,
+                                    @NonNull FilterChain filterChain) throws ServletException, IOException {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+        if (authentication != null && authentication.getPrincipal() instanceof User user) {
+            userService.updateUserActivity(user.getId());
+        }
+
+        filterChain.doFilter(request, response);
+    }
+}
+
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/model/domain/User.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/model/domain/User.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/model/domain/User.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -13,4 +13,5 @@
 import org.springframework.security.core.userdetails.UserDetails;
 
+import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.List;
@@ -49,4 +50,6 @@
     private boolean enabled;
 
+    private LocalDateTime lastActivityDate;
+
     public User(String firstName, String lastName, String email, String password, String phoneNumber, Role userRole) {
         this.firstName = firstName;
@@ -56,5 +59,6 @@
         this.phoneNumber = phoneNumber;
         this.userRole = userRole;
-        this.setEnabled(true);
+        this.enabled = true;
+        this.lastActivityDate = LocalDateTime.now();
     }
 
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/repository/UserRepository.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/repository/UserRepository.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/repository/UserRepository.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -5,4 +5,6 @@
 import org.springframework.stereotype.Repository;
 
+import java.time.LocalDateTime;
+import java.util.List;
 import java.util.Optional;
 
@@ -10,3 +12,6 @@
 public interface UserRepository extends JpaRepository<User, Long> {
     Optional<User> findByEmail(String email);
+    List<User> findAllByEnabledFalseAndLastActivityDateBefore(LocalDateTime time);
+    List<User> findAllByEnabledTrueAndLastActivityDateBefore(LocalDateTime time);
 }
+
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/AuthServiceImpl.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/AuthServiceImpl.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/AuthServiceImpl.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -4,4 +4,5 @@
 import mk.ukim.finki.it.reservengo.dto.jwtDTO.JWTAuthenticationResponseDTO;
 import mk.ukim.finki.it.reservengo.dto.jwtDTO.JWTLoginDTO;
+import mk.ukim.finki.it.reservengo.dto.userDTO.EditUserEmailDTO;
 import mk.ukim.finki.it.reservengo.model.domain.Customer;
 import mk.ukim.finki.it.reservengo.model.domain.LocalManager;
@@ -25,6 +26,7 @@
     private final AuthenticationManager authenticationManager;
     private final UserRepository userRepository;
+    private final UserService userService;
 
-    public AuthServiceImpl(CustomerService customerService, LocalWorkerService localWorkerService, LocalManagerService localManagerService, JWTService jwtService, PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, UserRepository userRepository) {
+    public AuthServiceImpl(CustomerService customerService, LocalWorkerService localWorkerService, LocalManagerService localManagerService, JWTService jwtService, PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, UserRepository userRepository, UserService userService) {
         this.customerService = customerService;
         this.localWorkerService = localWorkerService;
@@ -34,4 +36,5 @@
         this.authenticationManager = authenticationManager;
         this.userRepository = userRepository;
+        this.userService = userService;
     }
 
@@ -73,5 +76,16 @@
         String jwt = jwtService.generateToken(user);
 
+        userService.updateUserActivity(user.getId());
+
         return JWTAuthenticationResponseDTO.fromUser(user, jwt);
     }
+
+    @Override
+    public void reactivateProfile(EditUserEmailDTO editUserEmailDTO) {
+        User user = userService.findUserByEmail(editUserEmailDTO.newEmail());
+
+        if (!user.isEnabled()) {
+            userService.enableProfile(user.getId());
+        }
+    }
 }
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/EmailServiceImpl.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/EmailServiceImpl.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/EmailServiceImpl.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -0,0 +1,62 @@
+package mk.ukim.finki.it.reservengo.service.impl;
+
+import mk.ukim.finki.it.reservengo.service.intf.EmailService;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+
+public class EmailServiceImpl implements EmailService {
+    private final JavaMailSender mailSender;
+
+    private final String frontEndUrl = "http://localhost:5173";
+
+    public EmailServiceImpl(JavaMailSender mailSender) {
+        this.mailSender = mailSender;
+    }
+
+    @Override
+    public void sendManagerInvitationEmail(String email, String token) {
+        String invitationUrl = frontEndUrl + "/register/manager?token=" + token;
+
+        SimpleMailMessage message = new SimpleMailMessage();
+        message.setTo(email);
+        message.setSubject("Manager Invitation");
+        message.setText(String.format(
+                """
+                        You have been invited to become a manager.
+                        
+                        Click the link below to complete your registration:
+                        %s
+                        
+                        This link will expire in 48 hours.""",
+                invitationUrl
+        ));
+
+        mailSender.send(message);
+    }
+
+    @Override
+    public void sendWorkerInvitationEmail(String email, String token, String managerEmail, String localName) {
+        String invitationUrl = frontEndUrl + "/register/worker?token=" + token;
+
+        SimpleMailMessage message = new SimpleMailMessage();
+        message.setTo(email);
+        message.setSubject("Worker Invitation");
+        message.setText(String.format(
+                """
+                        You have been invited to become a worker at "%s".
+                        
+                        Invited by manager: %s
+                        
+                        Click the link below to complete your registration:
+                        %s
+                        
+                        This link will expire in 48 hours.
+                        """,
+                localName,
+                managerEmail,
+                invitationUrl
+        ));
+
+        mailSender.send(message);
+    }
+}
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/UserServiceImpl.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/UserServiceImpl.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/impl/UserServiceImpl.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -15,4 +15,6 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
 
 @Service
@@ -81,5 +83,5 @@
         User user = userRepository.findById(userId).orElseThrow(() -> new UserIdNotFoundException(userId));
 
-        if (user.getProfilePhotoUrl() != null && !user.getProfilePhotoUrl().isEmpty() ) {
+        if (user.getProfilePhotoUrl() != null && !user.getProfilePhotoUrl().isEmpty()) {
             fileStorageService.deletePhotoFile(user.getProfilePhotoUrl());
         }
@@ -114,4 +116,19 @@
 
     @Override
+    public void enableProfile(Long id) {
+        User user = userRepository.findById(id).orElseThrow(() -> new UserIdNotFoundException(id));
+        user.setEnabled(true);
+        user.setLastActivityDate(LocalDateTime.now());
+        userRepository.save(user);
+    }
+
+    @Override
+    public void updateUserActivity(Long id) {
+        User user = userRepository.findById(id).orElseThrow(() -> new UserIdNotFoundException(id));
+        user.setLastActivityDate(LocalDateTime.now());
+        userRepository.save(user);
+    }
+
+    @Override
     public User editUser(Long userId, EditUserProfileDTO editUserProfileDTO) {
         User user = userRepository.findById(userId).orElseThrow(() -> new UserIdNotFoundException(userId));
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/AuthService.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/AuthService.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/AuthService.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -4,4 +4,5 @@
 import mk.ukim.finki.it.reservengo.dto.jwtDTO.JWTAuthenticationResponseDTO;
 import mk.ukim.finki.it.reservengo.dto.jwtDTO.JWTLoginDTO;
+import mk.ukim.finki.it.reservengo.dto.userDTO.EditUserEmailDTO;
 
 public interface AuthService {
@@ -13,3 +14,5 @@
 
     JWTAuthenticationResponseDTO login(JWTLoginDTO jwtLoginDTO);
+
+    void reactivateProfile(EditUserEmailDTO editUserEmailDTO);
 }
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/EmailService.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/EmailService.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/EmailService.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -0,0 +1,7 @@
+package mk.ukim.finki.it.reservengo.service.intf;
+
+public interface EmailService {
+    void sendManagerInvitationEmail(String email, String token);
+
+    void sendWorkerInvitationEmail(String email, String token, String managerEmail, String localName);
+}
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/UserService.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/UserService.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/intf/UserService.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -23,3 +23,7 @@
 
     void disableProfile(Long id);
+
+    void enableProfile(Long id);
+
+    void updateUserActivity(Long id);
 }
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/jobs/ScheduledTasks.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/jobs/ScheduledTasks.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/service/jobs/ScheduledTasks.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -0,0 +1,45 @@
+package mk.ukim.finki.it.reservengo.service.jobs;
+
+import mk.ukim.finki.it.reservengo.model.domain.User;
+import mk.ukim.finki.it.reservengo.model.enumerations.Role;
+import mk.ukim.finki.it.reservengo.repository.UserRepository;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Component
+public class ScheduledTasks {
+
+    private final UserRepository userRepository;
+
+    public ScheduledTasks(UserRepository userRepository) {
+        this.userRepository = userRepository;
+    }
+
+    @Transactional
+    @Scheduled(cron = "0 0 3 * * ?")
+    public void deleteInactiveDisabledUsers() {
+        LocalDateTime threshold = LocalDateTime.now().minusDays(30);
+        List<User> usersToDelete = userRepository.findAllByEnabledFalseAndLastActivityDateBefore(threshold);
+        userRepository.deleteAll(usersToDelete);
+    }
+
+    @Transactional
+    @Scheduled(cron = "0 0 4 * * ?")
+    public void disableInactiveWorkersAndManagers() {
+        LocalDateTime threshold = LocalDateTime.now().minusDays(30);
+        List<User> usersToDisable = userRepository.findAllByEnabledTrueAndLastActivityDateBefore(threshold)
+                .stream()
+                .filter(user -> user.getUserRole() == Role.ROLE_LOCAL_MANAGER || user.getUserRole() == Role.ROLE_LOCAL_WORKER)
+                .toList();
+
+        usersToDisable.forEach(user -> {
+            user.setEnabled(false);
+            user.setLastActivityDate(LocalDateTime.now());
+        });
+        userRepository.saveAll(usersToDisable);
+    }
+}
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/web/controller/AuthController.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/web/controller/AuthController.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/web/controller/AuthController.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -4,11 +4,9 @@
 import mk.ukim.finki.it.reservengo.dto.jwtDTO.JWTAuthenticationResponseDTO;
 import mk.ukim.finki.it.reservengo.dto.jwtDTO.JWTLoginDTO;
+import mk.ukim.finki.it.reservengo.dto.userDTO.EditUserEmailDTO;
 import mk.ukim.finki.it.reservengo.service.intf.AuthService;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 @RestController
@@ -40,3 +38,9 @@
         return new ResponseEntity<>(authenticationService.login(jwtLoginDTO), HttpStatus.OK);
     }
+
+    @PatchMapping("/enable")
+    public ResponseEntity<Void> reactivateAccount(@RequestBody EditUserEmailDTO editUserEmailDTO) {
+        authenticationService.reactivateProfile(editUserEmailDTO);
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
 }
Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/web/controller/UserController.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/web/controller/UserController.java	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/web/controller/UserController.java	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -58,5 +58,5 @@
     }
 
-    @DeleteMapping("/disable")
+    @PatchMapping("/disable")
     public ResponseEntity<Void> disableUser(@AuthenticationPrincipal User user) {
         userService.disableProfile(user.getId());
Index: ReserveNGo-backend/src/main/resources/application.properties
===================================================================
--- ReserveNGo-backend/src/main/resources/application.properties	(revision 90774c33ff590c05af7ae3ca76aeb6f2905c1ea3)
+++ ReserveNGo-backend/src/main/resources/application.properties	(revision 867c6efe60c2e5a6c61ac9a1a0a1792bfed259f6)
@@ -1,7 +1,14 @@
 spring.application.name=ReserveNGo
 server.port=8080
-spring.profiles.active=h2
+spring.profiles.active=dev
 # use prod for postgre
 
 spring.servlet.multipart.max-file-size=10MB
 spring.servlet.multipart.max-request-size=20MB
+
+spring.mail.host=${MAIL_HOST:smtp.gmail.com}
+spring.mail.port=587
+spring.mail.username=${MAIL_USERNAME:}
+spring.mail.password=${MAIL_PASSWORD:}
+spring.mail.properties.mail.smtp.auth=true
+spring.mail.properties.mail.smtp.starttls.enable=true
