Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/PhoneController.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/PhoneController.java	(revision b68ae8d3cc34d054d169fb34943b9fcd77bff7c2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/PhoneController.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -19,4 +19,6 @@
     }
 
+
+    // handle request parameters for filtering phones
     @GetMapping
     public List<Phone> getPhones(){
@@ -24,8 +26,3 @@
     }
 
-    @PostMapping(path = "{phoneId}")
-    public List<PhoneOffer> getOffersForPhone(@PathVariable("phoneId") Long phoneId){
-        return phoneService.getOffersForPhone(phoneId);
-    }
-
 }
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/PhoneOfferController.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/PhoneOfferController.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/PhoneOfferController.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,27 @@
+package finki.it.phoneluxbackend.controllers;
+
+import finki.it.phoneluxbackend.entities.PhoneOffer;
+import finki.it.phoneluxbackend.services.PhoneOfferService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@RequestMapping(path = "/phone/{phoneId}")
+public class PhoneOfferController {
+    private final PhoneOfferService phoneOfferService;
+
+    @Autowired
+    public PhoneOfferController(PhoneOfferService phoneOfferService) {
+        this.phoneOfferService = phoneOfferService;
+    }
+
+    @GetMapping
+    public List<PhoneOffer> getOffersForPhone(@PathVariable("phoneId") Long phoneId){
+        return phoneOfferService.getPhoneOffersForPhone(phoneId);
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/RegistrationController.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/RegistrationController.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/RegistrationController.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,26 @@
+package finki.it.phoneluxbackend.controllers;
+
+import finki.it.phoneluxbackend.data.RegistrationRequest;
+import finki.it.phoneluxbackend.services.RegistrationService;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping(path = "/registration")
+@AllArgsConstructor
+public class RegistrationController {
+    private final RegistrationService registrationService;
+
+    @PostMapping
+    public String RegisterRequest(@RequestBody RegistrationRequest request)
+    {
+        return registrationService.register(request);
+    }
+
+    @GetMapping(path = "confirm")
+    public String confirm(@RequestParam("token") String token){
+        return registrationService.confirmToken(token);
+    }
+
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/data/RegistrationRequest.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/data/RegistrationRequest.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/data/RegistrationRequest.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,18 @@
+package finki.it.phoneluxbackend.data;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+
+@Getter
+@AllArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class RegistrationRequest {
+    private final String firstName;
+    private final String lastName;
+    private final String password;
+    private final String email;
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/data/UserRole.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/data/UserRole.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/data/UserRole.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,7 @@
+package finki.it.phoneluxbackend.data;
+
+public enum UserRole {
+    USER,
+    ADMIN,
+    SUPERADMIN
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/ConfirmationToken.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/ConfirmationToken.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/ConfirmationToken.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,53 @@
+package finki.it.phoneluxbackend.entities;
+
+import finki.it.phoneluxbackend.entities.User;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@Entity(name = "confirmation_tokens")
+public class ConfirmationToken {
+
+    @SequenceGenerator(
+            name = "confirmation_token_sequence",
+            sequenceName = "confirmation_token_sequence",
+            allocationSize = 1
+    )
+    @Id
+    @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(cascade = CascadeType.ALL)
+    @JoinColumn(
+            nullable = false,
+            name = "user_id"
+    )
+    private User user;
+
+    public ConfirmationToken(String token,
+                             LocalDateTime createdAt,
+                             LocalDateTime expiresAt,
+                             User user) {
+        this.token = token;
+        this.createdAt = createdAt;
+        this.expiresAt = expiresAt;
+        this.user = user;
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/Phone.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/Phone.java	(revision b68ae8d3cc34d054d169fb34943b9fcd77bff7c2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/Phone.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -25,4 +25,7 @@
     private String model;
 
+    @Column(name = "image_url")
+    private String image_url;
+
     @OneToMany(fetch = FetchType.LAZY, mappedBy = "phone")
     @JsonIgnore
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/PhoneOffer.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/PhoneOffer.java	(revision b68ae8d3cc34d054d169fb34943b9fcd77bff7c2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/PhoneOffer.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -77,3 +77,33 @@
     @JsonIgnore
     private Phone phone;
+
+    public PhoneOffer(String offer_shop, String offer_name,
+                      Integer price, String ram_memory,
+                      String rom_memory, String color,
+                      String front_camera, String back_camera,
+                      String chipset, String battery,
+                      String operating_system, String cpu,
+                      String image_url, String offer_url,
+                      Date last_updated, Boolean is_validated,
+                      String offer_description, String offer_shop_code, Phone phone) {
+        this.offer_shop = offer_shop;
+        this.offer_name = offer_name;
+        this.price = price;
+        this.ram_memory = ram_memory;
+        this.rom_memory = rom_memory;
+        this.color = color;
+        this.front_camera = front_camera;
+        this.back_camera = back_camera;
+        this.chipset = chipset;
+        this.battery = battery;
+        this.operating_system = operating_system;
+        this.cpu = cpu;
+        this.image_url = image_url;
+        this.offer_url = offer_url;
+        this.last_updated = last_updated;
+        this.is_validated = is_validated;
+        this.offer_description = offer_description;
+        this.offer_shop_code = offer_shop_code;
+        this.phone = phone;
+    }
 }
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/User.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/User.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/User.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,84 @@
+package finki.it.phoneluxbackend.entities;
+
+import finki.it.phoneluxbackend.data.UserRole;
+import lombok.*;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import javax.persistence.*;
+import java.util.Collection;
+import java.util.Collections;
+
+@Getter
+@Setter
+@EqualsAndHashCode
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity(name = "users")
+public class User implements UserDetails {
+
+    @SequenceGenerator(
+            name = "user_sequence",
+            sequenceName = "user_sequence",
+            allocationSize = 1
+    )
+    @Id
+    @GeneratedValue(
+            strategy = GenerationType.SEQUENCE,
+            generator = "user_sequence"
+    )
+    private Long id;
+    private String firstName;
+    private String lastName;
+    private String email;
+    private String password;
+    @Enumerated(EnumType.STRING)
+    private UserRole userRole;
+    private Boolean locked = false;
+    private Boolean enabled = false;
+
+    public User(String firstName, String lastName, String email, String password, UserRole userRole) {
+        this.firstName = firstName;
+        this.lastName = lastName;
+        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 email;
+    }
+
+    @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: phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/ConfirmationTokenRepository.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/ConfirmationTokenRepository.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/ConfirmationTokenRepository.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,23 @@
+package finki.it.phoneluxbackend.repositories;
+
+import finki.it.phoneluxbackend.entities.ConfirmationToken;
+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 java.time.LocalDateTime;
+import java.util.Optional;
+
+@Repository
+public interface ConfirmationTokenRepository extends JpaRepository<ConfirmationToken,Long> {
+    Optional<ConfirmationToken> findByToken(String token);
+
+    @Transactional
+    @Modifying
+    @Query("UPDATE confirmation_tokens c " +
+            "SET c.confirmedAt = ?2 " +
+            "WHERE c.token = ?1")
+    int updateConfirmedAt(String token, LocalDateTime confirmedAt);
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/PhoneOfferRepository.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/PhoneOfferRepository.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/PhoneOfferRepository.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,9 @@
+package finki.it.phoneluxbackend.repositories;
+import finki.it.phoneluxbackend.entities.PhoneOffer;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PhoneOfferRepository extends JpaRepository<PhoneOffer,Long> {
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/UserRepository.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/UserRepository.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/UserRepository.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,23 @@
+package finki.it.phoneluxbackend.repositories;
+
+import finki.it.phoneluxbackend.entities.User;
+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 java.util.Optional;
+
+@Repository
+@Transactional(readOnly = true)
+public interface UserRepository extends JpaRepository<User,Long> {
+    Optional<User> findByEmail(String email);
+
+    @Transactional
+    @Modifying
+    @Query("UPDATE users a " +
+            "SET a.enabled = TRUE WHERE a.email = ?1")
+    int enableUser(String email);
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/PasswordEncoder.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/PasswordEncoder.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/PasswordEncoder.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,14 @@
+package finki.it.phoneluxbackend.security;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+@Configuration
+public class PasswordEncoder {
+
+    @Bean
+    public BCryptPasswordEncoder bCryptPasswordEncoder(){
+        return new BCryptPasswordEncoder();
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/configs/WebSecurityConfig.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/configs/WebSecurityConfig.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/configs/WebSecurityConfig.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,52 @@
+package finki.it.phoneluxbackend.security.configs;
+
+import finki.it.phoneluxbackend.services.UserService;
+import lombok.AllArgsConstructor;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.config.annotation.SecurityBuilder;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+@AllArgsConstructor
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    private final UserService userService;
+    private final BCryptPasswordEncoder bCryptPasswordEncoder;
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+                .csrf().disable()
+                .authorizeRequests()
+                .antMatchers("/registration/**")
+                .permitAll()
+                .anyRequest()
+                .authenticated().and()
+                .formLogin();
+
+    }
+
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+        auth.authenticationProvider(daoAuthenticationProvider());
+    }
+
+
+    public DaoAuthenticationProvider daoAuthenticationProvider(){
+        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+        provider.setPasswordEncoder(bCryptPasswordEncoder);
+        provider.setUserDetailsService(userService);
+        return provider;
+    }
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/email/EmailSender.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/email/EmailSender.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/email/EmailSender.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,5 @@
+package finki.it.phoneluxbackend.security.email;
+
+public interface EmailSender {
+    void send(String to, String email);
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/email/EmailValidator.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/email/EmailValidator.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/email/EmailValidator.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,16 @@
+package finki.it.phoneluxbackend.security.email;
+
+import org.springframework.stereotype.Service;
+
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+@Service
+public class EmailValidator implements Predicate<String> {
+
+    @Override
+    public boolean test(String s) {
+        // regex to validate email
+        return Pattern.compile("^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$").matcher(s).matches();
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/ConfirmationTokenService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/ConfirmationTokenService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/ConfirmationTokenService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,28 @@
+package finki.it.phoneluxbackend.services;
+
+import finki.it.phoneluxbackend.repositories.ConfirmationTokenRepository;
+import finki.it.phoneluxbackend.entities.ConfirmationToken;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+@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: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/EmailService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/EmailService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/EmailService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,40 @@
+package finki.it.phoneluxbackend.services;
+
+import finki.it.phoneluxbackend.security.email.EmailSender;
+import lombok.AllArgsConstructor;
+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 javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+@Service
+@AllArgsConstructor
+public class EmailService implements EmailSender {
+
+    private final JavaMailSender mailSender;
+    private final static Logger LOGGER = LoggerFactory.getLogger(EmailService.class);
+
+
+
+    @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("Confirm your email - Phonelux");
+            helper.setFrom("phonelux_official@gmail.com");
+            mailSender.send(mimeMessage);
+        } catch (MessagingException e){
+            LOGGER.error("Failed to send email ", e);
+            throw new IllegalStateException("Failed to send email");
+        }
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/PhoneOfferService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/PhoneOfferService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/PhoneOfferService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,28 @@
+package finki.it.phoneluxbackend.services;
+
+import finki.it.phoneluxbackend.entities.PhoneOffer;
+import finki.it.phoneluxbackend.repositories.PhoneOfferRepository;
+import finki.it.phoneluxbackend.repositories.PhoneRepository;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class PhoneOfferService {
+    private final PhoneOfferRepository phoneOfferRepository;
+    private final PhoneRepository phoneRepository;
+
+    public PhoneOfferService(PhoneOfferRepository phoneOfferRepository, PhoneRepository phoneRepository) {
+        this.phoneOfferRepository = phoneOfferRepository;
+        this.phoneRepository = phoneRepository;
+    }
+
+    public List<PhoneOffer> getPhoneOffersForPhone(Long phoneId) {
+        boolean exists = phoneRepository.existsById(phoneId);
+        if(!exists)
+            throw new IllegalStateException("Phone with id "+phoneId+" does not exist");
+
+        return phoneRepository.findById(phoneId).get().getPhoneOffers();
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/PhoneService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/PhoneService.java	(revision b68ae8d3cc34d054d169fb34943b9fcd77bff7c2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/PhoneService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -21,10 +21,3 @@
     }
 
-    public List<PhoneOffer> getOffersForPhone(Long phoneId) {
-        boolean exists = phoneRepository.existsById(phoneId);
-        if(!exists)
-            throw new IllegalStateException("Phone with id "+phoneId+" does not exist");
-
-        return phoneRepository.findById(phoneId).get().getPhoneOffers();
-    }
 }
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/RegistrationService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/RegistrationService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/RegistrationService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,134 @@
+package finki.it.phoneluxbackend.services;
+
+import finki.it.phoneluxbackend.data.RegistrationRequest;
+import finki.it.phoneluxbackend.data.UserRole;
+import finki.it.phoneluxbackend.entities.ConfirmationToken;
+import finki.it.phoneluxbackend.entities.User;
+import finki.it.phoneluxbackend.security.email.EmailSender;
+import finki.it.phoneluxbackend.security.email.EmailValidator;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+
+@Service
+@AllArgsConstructor
+public class RegistrationService {
+    private final UserService userService;
+    private final EmailValidator emailValidator;
+    private final ConfirmationTokenService confirmationTokenService;
+    private final EmailSender emailSender;
+
+
+    public String register(RegistrationRequest request) {
+        boolean isValidEmail = emailValidator.test(request.getEmail());
+
+        // validacija za mejl na frontend ?
+        if (!isValidEmail)
+            throw new IllegalStateException("Email"+request.getEmail()+" not valid!");
+
+        String token = userService.signUpUser(
+                new User(request.getFirstName(),
+                        request.getLastName(),
+                        request.getEmail(),
+                        request.getPassword(),
+                        UserRole.USER));
+
+        String link = "http://localhost:8080/registration/confirm?token="+token;
+        emailSender.send(request.getEmail(), buildEmail(request.getFirstName(),link));
+        return token;
+    }
+
+    private String buildEmail(String name, 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\">Confirm your email</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\">Hi " + name + ",</p><p style=\"Margin:0 0 20px 0;font-size:19px;line-height:25px;color:#0b0c0c\"> Thank you for registering. Please click on the below link to activate your account: </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 + "\">Activate Now</a> </p></blockquote>\n Link will expire in 15 minutes. <p>See you soon</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>";
+    }
+
+
+    @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 expiresAt = confirmationToken.getExpiresAt();
+
+        if (expiresAt.isBefore(LocalDateTime.now())){
+            throw new IllegalStateException("Token expired");
+        }
+
+        confirmationTokenService.setConfirmedAt(token);
+        userService.enableUser(confirmationToken.getUser().getEmail());
+
+        return "Email confirmed";
+    }
+
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/UserService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/UserService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/UserService.java	(revision dbd483418f962e3b40992a977eef4ece28007aa2)
@@ -0,0 +1,59 @@
+package finki.it.phoneluxbackend.services;
+
+import finki.it.phoneluxbackend.entities.User;
+import finki.it.phoneluxbackend.repositories.UserRepository;
+import finki.it.phoneluxbackend.entities.ConfirmationToken;
+import lombok.AllArgsConstructor;
+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.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+@Service
+@AllArgsConstructor
+public class UserService implements UserDetailsService {
+    private final UserRepository userRepository;
+    private final BCryptPasswordEncoder bCryptPasswordEncoder;
+    private final ConfirmationTokenService confirmationTokenService;
+
+
+    @Override
+    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
+        return userRepository.findByEmail(email)
+                .orElseThrow(() -> new UsernameNotFoundException("User with email "+email+" not found!"));
+    }
+
+    public String signUpUser(User user)
+    {
+       boolean userExists =  userRepository.findByEmail(user.getEmail()).isPresent();
+
+       if (userExists && user.getEnabled()){
+           throw new IllegalStateException("Email "+user.getEmail()+" already taken!");
+       }
+
+       String encodedPassword = bCryptPasswordEncoder.encode(user.getPassword());
+
+       user.setPassword(encodedPassword);
+
+        String token = UUID.randomUUID().toString();
+        ConfirmationToken confirmationToken = new ConfirmationToken(token,
+                LocalDateTime.now(),
+                LocalDateTime.now().plusMinutes(15),
+                user
+                );
+
+        confirmationTokenService.saveConfirmationToken(confirmationToken);
+
+        return token;
+    }
+
+    public int enableUser(String email) {
+        return userRepository.enableUser(email);
+    }
+
+
+}
