Index: springapp/src/main/java/mk/profesori/springapp/Controller/MainController.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Controller/MainController.java	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/java/mk/profesori/springapp/Controller/MainController.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -14,4 +14,5 @@
 import mk.profesori.springapp.Model.Faculty;
 import mk.profesori.springapp.Model.Professor;
+import mk.profesori.springapp.Model.StudyProgramme;
 import mk.profesori.springapp.Model.University;
 import mk.profesori.springapp.Service.MainService;
@@ -32,5 +33,17 @@
     @RequestMapping(value = "/professor/{professorId}", method = RequestMethod.GET)
     public Professor getProfessorById(@PathVariable Long professorId) {
-        return mainService.getProfessorById(professorId);
+        return mainService.getProfessorById(professorId);   //vrakja profesor spored id
+    }
+
+    @RequestMapping(value = "/study_programmes", method = RequestMethod.GET)
+    public List<StudyProgramme> getStudyProgrammesByFaculty(@RequestParam Optional<Long> facultyId) {
+
+        if(!facultyId.isPresent()) return mainService.getAllStudyProgrammes(); //ako nema parametar facultyId gi vrakja site studiski programi
+        return mainService.getStudyProgrammesByFacultyId(facultyId.get());
+    }
+
+    @RequestMapping(value = "/study_programme/{studyProgrammeId}", method = RequestMethod.GET)
+    public StudyProgramme getStudyProgrammeById(@PathVariable Long studyProgrammeId) {
+        return mainService.getStudyProgrammeById(studyProgrammeId);   //vrakja studiska programa spored id
     }
 
@@ -44,5 +57,5 @@
     @RequestMapping(value = "/faculty/{facultyId}", method = RequestMethod.GET)
     public Faculty getFacultyById(@PathVariable Long facultyId) {
-        return mainService.getFacultyById(facultyId);
+        return mainService.getFacultyById(facultyId); //vrakja fakultet spored id
     }
 
@@ -56,5 +69,5 @@
     @RequestMapping(value = "/university/{universityId}", method = RequestMethod.GET)
     public University getUniversityById(@PathVariable Long universityId) {
-        return mainService.getUniversityById(universityId);
+        return mainService.getUniversityById(universityId); //vrakja univerzitet spored id
     }
 
@@ -66,7 +79,6 @@
     @RequestMapping(value = "/city/{cityId}", method = RequestMethod.GET)
     public City getCityById(@PathVariable Long cityId) {
-        return mainService.getCityById(cityId);
+        return mainService.getCityById(cityId); //vrakja grad spored id
     }
 
-    
 }
Index: springapp/src/main/java/mk/profesori/springapp/Controller/RegistrationController.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Controller/RegistrationController.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Controller/RegistrationController.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,30 @@
+package mk.profesori.springapp.Controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+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.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import lombok.AllArgsConstructor;
+import mk.profesori.springapp.Model.RegistrationRequest;
+import mk.profesori.springapp.Service.RegistrationService;
+
+@RestController
+@RequestMapping(path = "/registration")
+@AllArgsConstructor
+public class RegistrationController {
+
+    private RegistrationService registrationService;
+    
+    @PostMapping
+    public String register(@RequestBody RegistrationRequest request) {
+        return registrationService.register(request);
+    }
+
+    @GetMapping(path = "confirm")
+    public String confirm(@RequestParam("token") String token) {
+        return registrationService.confirmToken(token);
+    }
+}
Index: springapp/src/main/java/mk/profesori/springapp/Model/ConfirmationToken.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/ConfirmationToken.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Model/ConfirmationToken.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,52 @@
+package mk.profesori.springapp.Model;
+
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.SequenceGenerator;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@Entity
+public class ConfirmationToken {
+    
+    @Id
+    @SequenceGenerator(name = "confirmation_token_sequence", sequenceName = "confirmation_token_sequence", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "confirmation_token_sequence")
+    private Long id;
+
+    @Column(nullable = false)
+    private String token;
+
+    @Column(nullable = false)
+    private LocalDateTime createdAt;
+
+    @Column(nullable = false)
+    private LocalDateTime expiresAt;
+
+    private LocalDateTime confirmedAt;
+
+    @ManyToOne
+    @JoinColumn(nullable = false, name = "custom_user_details_id")
+    private CustomUserDetails customUserDetails;
+
+    public ConfirmationToken(String token, LocalDateTime createdAt, LocalDateTime expiredAt, 
+    CustomUserDetails customUserDetails) {
+        
+        this.token = token;
+        this.createdAt = createdAt;
+        this.expiresAt = expiredAt;
+        this.customUserDetails = customUserDetails;
+    }
+}
Index: springapp/src/main/java/mk/profesori/springapp/Model/CustomUserDetails.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/CustomUserDetails.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Model/CustomUserDetails.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,87 @@
+package mk.profesori.springapp.Model;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@EqualsAndHashCode
+@NoArgsConstructor
+@Entity
+public class CustomUserDetails implements UserDetails {
+
+    @Id
+    @SequenceGenerator(name = "user_sequence", sequenceName = "user_sequence", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_sequence")
+    private Long id;
+    private String fullName; //opcionalno, smee da e prazno
+    private String username;
+    private String email;
+    private String password;
+    @Enumerated(EnumType.STRING)
+    private UserRole userRole;
+    private Boolean locked = false;
+    private Boolean enabled = false;
+
+    public CustomUserDetails(String fullName, String username, String email, String password, UserRole userRole) {
+        this.fullName = fullName;
+        this.username = username;
+        this.email = email;
+        this.password = password;
+        this.userRole = userRole;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(userRole.name());
+        return Collections.singletonList(authority);
+    }
+
+    @Override
+    public String getPassword() {
+        return password;
+    }
+
+    @Override
+    public String getUsername() {
+        return username;
+    }
+
+    @Override
+    public boolean isAccountNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isAccountNonLocked() {
+        return !locked;
+    }
+
+    @Override
+    public boolean isCredentialsNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+    
+}
Index: springapp/src/main/java/mk/profesori/springapp/Model/RegistrationRequest.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/RegistrationRequest.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Model/RegistrationRequest.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,17 @@
+package mk.profesori.springapp.Model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+
+@Getter
+@AllArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class RegistrationRequest {
+    private final String fullName; //formata treba da dozvoli ova da prazno
+    private final String username;
+    private final String email;
+    private final String password;
+}
Index: springapp/src/main/java/mk/profesori/springapp/Model/StudyProgramme.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/StudyProgramme.java	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/java/mk/profesori/springapp/Model/StudyProgramme.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -29,4 +29,7 @@
     private String studyProgrammeName;
 
+    @Column(name = "cycle")
+    private int cycle;
+
     @ManyToOne
     @JoinColumn(name = "faculty_id")
@@ -45,4 +48,8 @@
     }
 
+    public int getCycle() {
+        return cycle;
+    }
+
     @JsonBackReference
     public Faculty getFaculty() {
Index: springapp/src/main/java/mk/profesori/springapp/Model/UserRole.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/UserRole.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Model/UserRole.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,6 @@
+package mk.profesori.springapp.Model;
+
+public enum UserRole {
+    REGULAR,
+    MODERATOR
+}
Index: springapp/src/main/java/mk/profesori/springapp/Repository/CityRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/CityRepository.java	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/CityRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -4,7 +4,9 @@
 
 import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
 
 import mk.profesori.springapp.Model.City;
 
+@Repository
 public interface CityRepository extends CrudRepository<City, Long>{
 
Index: springapp/src/main/java/mk/profesori/springapp/Repository/ConfirmationTokenRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/ConfirmationTokenRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/ConfirmationTokenRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,24 @@
+package mk.profesori.springapp.Repository;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import mk.profesori.springapp.Model.ConfirmationToken;
+
+@Repository
+@Transactional(readOnly = true)
+public interface ConfirmationTokenRepository extends JpaRepository<ConfirmationToken,Long>{
+    
+    Optional<ConfirmationToken> findByToken(String token);
+
+    @Transactional
+    @Modifying
+    @Query("UPDATE ConfirmationToken c " + "SET c.confirmedAt = ?2 " + "WHERE c.token = ?1")
+    int updateConfirmedAt(String token, LocalDateTime confirmedAt);
+}
Index: springapp/src/main/java/mk/profesori/springapp/Repository/FacultyRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/FacultyRepository.java	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/FacultyRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -4,8 +4,10 @@
 
 import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
 
 import mk.profesori.springapp.Model.Faculty;
 import mk.profesori.springapp.Model.University;
 
+@Repository
 public interface FacultyRepository extends CrudRepository<Faculty, Long>{
 
Index: springapp/src/main/java/mk/profesori/springapp/Repository/ProfessorRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/ProfessorRepository.java	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/ProfessorRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -4,8 +4,10 @@
 
 import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
 
 import mk.profesori.springapp.Model.Faculty;
 import mk.profesori.springapp.Model.Professor;
 
+@Repository
 public interface ProfessorRepository extends CrudRepository<Professor, Long>{
     
Index: springapp/src/main/java/mk/profesori/springapp/Repository/StudyProgrammeRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/StudyProgrammeRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/StudyProgrammeRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,18 @@
+package mk.profesori.springapp.Repository;
+
+import java.util.List;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import mk.profesori.springapp.Model.Faculty;
+import mk.profesori.springapp.Model.StudyProgramme;
+
+
+@Repository
+public interface StudyProgrammeRepository extends CrudRepository<StudyProgramme, Long>{
+    
+    public List<StudyProgramme> findAll();
+    public StudyProgramme findByStudyProgrammeId(Long id);
+    public List<StudyProgramme> findByFaculty(Faculty faculty);
+}
Index: springapp/src/main/java/mk/profesori/springapp/Repository/UniversityRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/UniversityRepository.java	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/UniversityRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -4,4 +4,5 @@
 
 import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
 
 import mk.profesori.springapp.Model.City;
@@ -9,4 +10,5 @@
 import mk.profesori.springapp.Model.University;
 
+@Repository
 public interface UniversityRepository extends CrudRepository<University, Long>{
 
Index: springapp/src/main/java/mk/profesori/springapp/Repository/UserRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/UserRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/UserRepository.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,23 @@
+package mk.profesori.springapp.Repository;
+
+import java.util.Optional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import mk.profesori.springapp.Model.CustomUserDetails;
+
+@Repository
+@Transactional(readOnly = true)
+public interface UserRepository extends JpaRepository<CustomUserDetails,Long> {
+    Optional<CustomUserDetails> findByEmail(String email);
+    Optional<CustomUserDetails> findByUsername(String username);
+
+    @Transactional
+    @Modifying
+    @Query("UPDATE CustomUserDetails a " + "SET a.enabled = TRUE WHERE a.email = ?1")
+    int enableUser(String email);
+}
Index: springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,47 @@
+package mk.profesori.springapp.Security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+
+import lombok.RequiredArgsConstructor;
+import mk.profesori.springapp.Service.CustomUserDetailsService;
+
+@Configuration
+@RequiredArgsConstructor
+@EnableWebSecurity
+public class SecurityConfiguration {
+
+    private final CustomUserDetailsService customUserDetailsService;
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
+        return authenticationConfiguration.getAuthenticationManager();
+    }
+    
+    @Bean
+    protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+        http
+            .csrf().disable() //PRIVREMENO
+            .authorizeRequests()
+                .antMatchers("/registration/**")
+                .permitAll()
+            .anyRequest()
+            .authenticated().and()
+            .formLogin();
+        
+        return http.build();
+    }
+}
Index: springapp/src/main/java/mk/profesori/springapp/Service/ConfirmationTokenService.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/ConfirmationTokenService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/ConfirmationTokenService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,31 @@
+package mk.profesori.springapp.Service;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+import org.springframework.stereotype.Service;
+
+import lombok.AllArgsConstructor;
+import mk.profesori.springapp.Model.ConfirmationToken;
+import mk.profesori.springapp.Repository.ConfirmationTokenRepository;
+
+@Service
+@AllArgsConstructor
+public class ConfirmationTokenService {
+    
+    private final ConfirmationTokenRepository confirmationTokenRepository;
+
+    public void saveConfirmationToken(ConfirmationToken token) {
+        confirmationTokenRepository.save(token);
+    }
+
+    public Optional<ConfirmationToken> getToken(String token) {
+        return confirmationTokenRepository.findByToken(token);
+    }
+
+    public int setConfirmedAt(String token) {
+        return confirmationTokenRepository.updateConfirmedAt(
+                token, LocalDateTime.now());
+    }
+
+}
Index: springapp/src/main/java/mk/profesori/springapp/Service/CustomUserDetailsService.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/CustomUserDetailsService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/CustomUserDetailsService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,72 @@
+package mk.profesori.springapp.Service;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import lombok.AllArgsConstructor;
+import mk.profesori.springapp.Model.ConfirmationToken;
+import mk.profesori.springapp.Model.CustomUserDetails;
+import mk.profesori.springapp.Repository.UserRepository;
+
+@Service
+@AllArgsConstructor
+public class CustomUserDetailsService implements UserDetailsService {
+
+    private final UserRepository userRepository;
+    @Autowired
+    public PasswordEncoder passwordEncoder()
+    {
+        return new BCryptPasswordEncoder();
+    }
+    private final static String USER_NOT_FOUND_MSG = "User with email %s not found";
+    private final ConfirmationTokenService confirmationTokenService;
+
+    @Override
+    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
+        return userRepository.findByEmail(email).orElseThrow(
+            () -> new UsernameNotFoundException(String.format(USER_NOT_FOUND_MSG,email))
+            );
+    }
+
+    public String signUp(CustomUserDetails customUserDetails) {
+
+        boolean emailExists = userRepository.findByEmail(customUserDetails.getEmail()).isPresent();
+        if(emailExists) {
+            throw new IllegalStateException("Email is taken");
+        }
+
+        boolean usernameExists = userRepository.findByUsername(customUserDetails.getUsername()).isPresent();
+        if(usernameExists) {
+            throw new IllegalStateException("Username is taken");
+        }
+
+        String encodedPassword = passwordEncoder().encode(customUserDetails.getPassword());
+        customUserDetails.setPassword(encodedPassword);
+
+        userRepository.save(customUserDetails);
+
+        String token = UUID.randomUUID().toString();
+        ConfirmationToken confirmationToken = new ConfirmationToken(
+            token,
+            LocalDateTime.now(),
+            LocalDateTime.now().plusMinutes(10),
+            customUserDetails
+        );
+        
+        confirmationTokenService.saveConfirmationToken(confirmationToken);
+        return token;
+    }
+
+    public int enableUser(String email) {
+        return userRepository.enableUser(email);
+    }
+    
+}
Index: springapp/src/main/java/mk/profesori/springapp/Service/EmailSender.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/EmailSender.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/EmailSender.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,5 @@
+package mk.profesori.springapp.Service;
+
+public interface EmailSender {
+    void send(String to, String email);
+}
Index: springapp/src/main/java/mk/profesori/springapp/Service/EmailService.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/EmailService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/EmailService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,39 @@
+package mk.profesori.springapp.Service;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import lombok.AllArgsConstructor;
+
+@Service
+@AllArgsConstructor
+public class EmailService implements EmailSender{
+    
+    private final static Logger LOGGER = LoggerFactory.getLogger(EmailService.class);
+    private final JavaMailSender mailSender;
+
+    @Override
+    @Async
+    public void send(String to, String email) {
+        try {
+            MimeMessage mimeMessage = mailSender.createMimeMessage();
+            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, "utf-8");
+            helper.setText(email, true);
+            helper.setTo(to);
+            helper.setSubject("Активирај ја својата корисничка сметка");
+            helper.setFrom("admin@profesori.mk");
+            mailSender.send(mimeMessage);
+        } catch (MessagingException e) {
+            LOGGER.error("Failed to send email", e);
+            throw new IllegalStateException("Failed to send email");
+        }
+    }
+
+}
Index: springapp/src/main/java/mk/profesori/springapp/Service/EmailValidator.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/EmailValidator.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/EmailValidator.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,27 @@
+package mk.profesori.springapp.Service;
+
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class EmailValidator implements Predicate<String> {
+    
+    @Override
+    public boolean test(String email) {
+        
+        String regex = "^(.+)@(.+)$";
+
+        Pattern pattern = Pattern.compile(regex);
+
+        if (email == null) {
+            return false;
+        }
+
+        Matcher matcher = pattern.matcher(email);
+
+        return matcher.matches();   
+    }
+}
Index: springapp/src/main/java/mk/profesori/springapp/Service/MainService.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/MainService.java	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/java/mk/profesori/springapp/Service/MainService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -10,8 +10,10 @@
 import mk.profesori.springapp.Repository.FacultyRepository;
 import mk.profesori.springapp.Repository.ProfessorRepository;
+import mk.profesori.springapp.Repository.StudyProgrammeRepository;
 import mk.profesori.springapp.Repository.UniversityRepository;
 import mk.profesori.springapp.Model.City;
 import mk.profesori.springapp.Model.Faculty;
 import mk.profesori.springapp.Model.Professor;
+import mk.profesori.springapp.Model.StudyProgramme;
 import mk.profesori.springapp.Model.University;
 
@@ -21,4 +23,6 @@
     @Autowired
     private ProfessorRepository professorRepository;
+    @Autowired
+    private StudyProgrammeRepository studyProgrammeRepository;
     @Autowired
     private FacultyRepository facultyRepository;
@@ -46,4 +50,25 @@
         List<Professor> list = new ArrayList<>();
         professorRepository.findByFaculty(faculty).forEach(list::add);
+        return list;
+    }
+
+    public List<StudyProgramme> getAllStudyProgrammes() {
+
+        List<StudyProgramme> list = new ArrayList<>();
+        studyProgrammeRepository.findAll().forEach(list::add);
+        return list;
+    }
+
+    public StudyProgramme getStudyProgrammeById(Long id) {
+
+        return studyProgrammeRepository.findByStudyProgrammeId(id);
+    }
+
+    public List<StudyProgramme> getStudyProgrammesByFacultyId(Long facultyId) {
+        
+        Faculty faculty = facultyRepository.findByFacultyId(facultyId);
+
+        List<StudyProgramme> list = new ArrayList<>();
+        studyProgrammeRepository.findByFaculty(faculty).forEach(list::add);
         return list;
     }
Index: springapp/src/main/java/mk/profesori/springapp/Service/PasswordValidator.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/PasswordValidator.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/PasswordValidator.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,39 @@
+package mk.profesori.springapp.Service;
+
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class PasswordValidator implements Predicate<String> {
+    
+    @Override
+    public boolean test(String password) {
+        
+        String regex = "^(?=.*[0-9])"
+                       + "(?=.*[a-z])(?=.*[A-Z])"
+                       + "(?=.*[@#$%^&+=])"
+                       + "(?=\\S+$).{8,20}$";
+
+        Pattern pattern = Pattern.compile(regex);
+
+        if (password == null) {
+            return false;
+        }
+
+        Matcher matcher = pattern.matcher(password);
+
+        return matcher.matches();   
+    }
+}
+
+/*
+    It contains at least 8 characters and at most 20 characters.
+    It contains at least one digit.
+    It contains at least one upper case alphabet.
+    It contains at least one lower case alphabet.
+    It contains at least one special character which includes !@#$%&*()-+=^.
+    It doesn’t contain any white space.
+ */
Index: springapp/src/main/java/mk/profesori/springapp/Service/RegistrationService.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/RegistrationService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/RegistrationService.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,145 @@
+package mk.profesori.springapp.Service;
+
+import java.time.LocalDateTime;
+
+import javax.transaction.Transactional;
+
+import org.springframework.stereotype.Service;
+
+import lombok.AllArgsConstructor;
+import mk.profesori.springapp.Model.ConfirmationToken;
+import mk.profesori.springapp.Model.CustomUserDetails;
+import mk.profesori.springapp.Model.RegistrationRequest;
+import mk.profesori.springapp.Model.UserRole;
+
+@Service
+@AllArgsConstructor
+public class RegistrationService {
+
+    private final CustomUserDetailsService customUserDetailsService;
+    private final ConfirmationTokenService confirmationTokenService;
+    private final EmailValidator emailValidator;
+    private final PasswordValidator passwordValidator;
+    private final UsernameValidator usernameValidator;
+    private final EmailSender emailSender;
+    
+    public String register(RegistrationRequest request) {
+
+        boolean isValidEmail = emailValidator.test(request.getEmail());
+        if(!isValidEmail) throw new IllegalStateException("Invalid email");
+
+        boolean isValidPassword = passwordValidator.test(request.getPassword());
+        if(!isValidPassword) throw new IllegalStateException("Invalid password");
+
+        boolean isValidUsername = usernameValidator.test(request.getUsername());
+        if(!isValidUsername) throw new IllegalStateException("Invalid username");
+
+        String token = customUserDetailsService.signUp(
+            new CustomUserDetails(
+                request.getFullName(),
+                request.getUsername(),
+                request.getEmail(),
+                request.getPassword(),
+                UserRole.REGULAR
+            )
+            );
+        
+        String link = "http://192.168.0.17:8080/registration/confirm?token=" + token;
+        
+        emailSender.send(request.getEmail(), buildEmail(request.getUsername(), link));
+        
+        return token;
+    }
+
+    @Transactional
+    public String confirmToken(String token) {
+        ConfirmationToken confirmationToken = confirmationTokenService
+                .getToken(token)
+                .orElseThrow(() ->
+                        new IllegalStateException("Token not found"));
+
+        if (confirmationToken.getConfirmedAt() != null) {
+            throw new IllegalStateException("Email already confirmed");
+        }
+
+        LocalDateTime expiredAt = confirmationToken.getExpiresAt();
+
+        if (expiredAt.isBefore(LocalDateTime.now())) {
+            throw new IllegalStateException("Token expired");
+        }
+
+        confirmationTokenService.setConfirmedAt(token);
+        customUserDetailsService.enableUser(
+                confirmationToken.getCustomUserDetails().getEmail());
+        return "Confirmed";
+    }
+
+    private String buildEmail(String username, String link) {
+        return "<div style=\"font-family:Helvetica,Arial,sans-serif;font-size:16px;margin:0;color:#0b0c0c\">\n" +
+                "\n" +
+                "<span style=\"display:none;font-size:1px;color:#fff;max-height:0\"></span>\n" +
+                "\n" +
+                "  <table role=\"presentation\" width=\"100%\" style=\"border-collapse:collapse;min-width:100%;width:100%!important\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n" +
+                "    <tbody><tr>\n" +
+                "      <td width=\"100%\" height=\"53\" bgcolor=\"#0b0c0c\">\n" +
+                "        \n" +
+                "        <table role=\"presentation\" width=\"100%\" style=\"border-collapse:collapse;max-width:580px\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\">\n" +
+                "          <tbody><tr>\n" +
+                "            <td width=\"70\" bgcolor=\"#0b0c0c\" valign=\"middle\">\n" +
+                "                <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border-collapse:collapse\">\n" +
+                "                  <tbody><tr>\n" +
+                "                    <td style=\"padding-left:10px\">\n" +
+                "                  \n" +
+                "                    </td>\n" +
+                "                    <td style=\"font-size:28px;line-height:1.315789474;Margin-top:4px;padding-left:10px\">\n" +
+                "                      <span style=\"font-family:Helvetica,Arial,sans-serif;font-weight:700;color:#ffffff;text-decoration:none;vertical-align:top;display:inline-block\">Активирај ја својата корисничка сметка</span>\n" +
+                "                    </td>\n" +
+                "                  </tr>\n" +
+                "                </tbody></table>\n" +
+                "              </a>\n" +
+                "            </td>\n" +
+                "          </tr>\n" +
+                "        </tbody></table>\n" +
+                "        \n" +
+                "      </td>\n" +
+                "    </tr>\n" +
+                "  </tbody></table>\n" +
+                "  <table role=\"presentation\" class=\"m_-6186904992287805515content\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border-collapse:collapse;max-width:580px;width:100%!important\" width=\"100%\">\n" +
+                "    <tbody><tr>\n" +
+                "      <td width=\"10\" height=\"10\" valign=\"middle\"></td>\n" +
+                "      <td>\n" +
+                "        \n" +
+                "                <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border-collapse:collapse\">\n" +
+                "                  <tbody><tr>\n" +
+                "                    <td bgcolor=\"#1D70B8\" width=\"100%\" height=\"10\"></td>\n" +
+                "                  </tr>\n" +
+                "                </tbody></table>\n" +
+                "        \n" +
+                "      </td>\n" +
+                "      <td width=\"10\" valign=\"middle\" height=\"10\"></td>\n" +
+                "    </tr>\n" +
+                "  </tbody></table>\n" +
+                "\n" +
+                "\n" +
+                "\n" +
+                "  <table role=\"presentation\" class=\"m_-6186904992287805515content\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border-collapse:collapse;max-width:580px;width:100%!important\" width=\"100%\">\n" +
+                "    <tbody><tr>\n" +
+                "      <td height=\"30\"><br></td>\n" +
+                "    </tr>\n" +
+                "    <tr>\n" +
+                "      <td width=\"10\" valign=\"middle\"><br></td>\n" +
+                "      <td style=\"font-family:Helvetica,Arial,sans-serif;font-size:19px;line-height:1.315789474;max-width:560px\">\n" +
+                "        \n" +
+                "            <p style=\"Margin:0 0 20px 0;font-size:19px;line-height:25px;color:#0b0c0c\">Здраво " + username + ",</p><p style=\"Margin:0 0 20px 0;font-size:19px;line-height:25px;color:#0b0c0c\"> Добредојде на profesori.mk!. Да ја активираш својата корисничка сметка, кликни на линкот долу: </p><blockquote style=\"Margin:0 0 20px 0;border-left:10px solid #b1b4b6;padding:15px 0 0.1px 15px;font-size:19px;line-height:25px\"><p style=\"Margin:0 0 20px 0;font-size:19px;line-height:25px;color:#0b0c0c\"> <a href=\"" + link + "\">Активирај</a> </p></blockquote>\n Линкот истекува за 10 минути. <p>Убав престој!</p>" +
+                "        \n" +
+                "      </td>\n" +
+                "      <td width=\"10\" valign=\"middle\"><br></td>\n" +
+                "    </tr>\n" +
+                "    <tr>\n" +
+                "      <td height=\"30\"><br></td>\n" +
+                "    </tr>\n" +
+                "  </tbody></table><div class=\"yj6qo\"></div><div class=\"adL\">\n" +
+                "\n" +
+                "</div></div>";
+    }
+}
Index: springapp/src/main/java/mk/profesori/springapp/Service/UsernameValidator.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/UsernameValidator.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
+++ springapp/src/main/java/mk/profesori/springapp/Service/UsernameValidator.java	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -0,0 +1,36 @@
+package mk.profesori.springapp.Service;
+
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class UsernameValidator implements Predicate<String> {
+    
+    @Override
+    public boolean test(String username) {
+        
+        String regex = "^[A-Za-z]\\w{5,29}$";
+        
+        Pattern pattern = Pattern.compile(regex);
+
+        if (username == null) {
+            return false;
+        }
+
+        Matcher matcher = pattern.matcher(username);
+
+        return matcher.matches();   
+    }
+}
+
+/*
+  - The username consists of 6 to 30 characters inclusive. If the username
+    consists of less than 6 or greater than 30 characters, then it is an invalid username.
+  - The username can only contain alphanumeric characters and underscores (_). 
+    Alphanumeric characters describe the character set consisting of lowercase characters [a – z], uppercase characters [A – Z], and digits [0 – 9].
+  - The first character of the username must be an alphabetic character, i.e., either lowercase character
+    [a – z] or uppercase character [A – Z].
+ */
Index: springapp/src/main/resources/application.properties
===================================================================
--- springapp/src/main/resources/application.properties	(revision 9506ca8f1d1d14c1a16be0d016d016240b436344)
+++ springapp/src/main/resources/application.properties	(revision 6c1d611d2c6065f94a6ce7aba685af562d15971f)
@@ -2,6 +2,11 @@
 spring.datasource.username=postgres
 spring.datasource.password=1win7337
-spring.jpa.hibernate.ddl-auto=none
+spring.jpa.hibernate.ddl-auto=update
 spring.jpa.show-sql=false
 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
 spring.jpa.properties.hibernate.format_sql=true
+server.address=192.168.0.17
+spring.mail.host=192.168.0.24
+spring.mail.username=mailuser
+spring.mail.password=mailpass
+spring.mail.port=1025
