Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/main/java/mate/academy/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@

import java.time.LocalDate;
import java.time.LocalDateTime;
import mate.academy.lib.Injector;
import mate.academy.model.CinemaHall;
import mate.academy.model.Movie;
import mate.academy.model.MovieSession;
import mate.academy.security.AuthenticationService;
import mate.academy.service.CinemaHallService;
import mate.academy.service.MovieService;
import mate.academy.service.MovieSessionService;

public class Main {
public static void main(String[] args) {
MovieService movieService = null;
public static final Injector injector = Injector.getInstance("mate.academy");
private static final MovieService movieService =
(MovieService) injector.getInstance(MovieService.class);
private static final MovieSessionService movieSessionService =
(MovieSessionService) injector.getInstance(MovieSessionService.class);
private static final CinemaHallService cinemaHallService =
(CinemaHallService) injector.getInstance(CinemaHallService.class);
private static final AuthenticationService authenticationService =
(AuthenticationService) injector.getInstance(AuthenticationService.class);

public static void main(String[] args) {
Movie fastAndFurious = new Movie("Fast and Furious");
fastAndFurious.setDescription("An action film about street racing, heists, and spies.");
movieService.add(fastAndFurious);
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/mate/academy/dao/UserDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package mate.academy.dao;

import java.util.Optional;
import mate.academy.model.User;

public interface UserDao {
User add(User user);

User get(Long id);

Optional<User> findByEmail(String email);
}
54 changes: 54 additions & 0 deletions src/main/java/mate/academy/dao/impl/UserDaoImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mate.academy.dao.impl;

import java.util.Optional;
import mate.academy.dao.UserDao;
import mate.academy.exception.DataProcessingException;
import mate.academy.model.User;
import mate.academy.util.HibernateUtil;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class UserDaoImpl implements UserDao {
@Override
public User add(User user) {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
session.persist(user);
transaction.commit();
return user;
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
throw new DataProcessingException("can't save user to db" + user, e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider improving the error message by adding more context, such as the user details, to help with debugging. For example, include the user's email or ID if available.

} finally {
if (session != null) {
session.close();
}
}
}

@Override
public User get(Long id) {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
return session.get(User.class, id);
} catch (Exception e) {
throw new DataProcessingException("can't get user by id:" + id, e);
}
}

@Override
public Optional<User> findByEmail(String email) {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
return session.createQuery("FROM User u where u.email = :email", User.class)
.setParameter("email", email)
.uniqueResultOptional();
} catch (HibernateException e) {
throw new DataProcessingException("can't find user by email " + email, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package mate.academy.exception;

public class AuthenticationException extends RuntimeException {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AuthenticationException should not extend RuntimeException. Consider extending a more appropriate exception type, such as Exception, to align with the task requirements.

public AuthenticationException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package mate.academy.exception;

public class RegistrationException extends RuntimeException {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RegistrationException should not extend RuntimeException. Consider extending a more appropriate exception type, such as Exception, to align with the task requirements.

public RegistrationException(String message) {
super(message);
}
}
68 changes: 68 additions & 0 deletions src/main/java/mate/academy/model/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package mate.academy.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String email;
private String password;
private byte[] salt;

public User() {
}

public User(String email, String password) {
this.email = email;
this.password = password;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public byte[] getSalt() {
return salt;
}

public void setSalt(byte[] salt) {
this.salt = salt;
}

@Override
public String toString() {
return "User{"
+ "id=" + id
+ ", email=" + email + '\''
+ '}';
}
}
17 changes: 17 additions & 0 deletions src/main/java/mate/academy/security/AuthenticationService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package mate.academy.security;

import mate.academy.exception.AuthenticationException;
import mate.academy.exception.RegistrationException;
import mate.academy.model.User;

public interface AuthenticationService {
User login(String email, String password) throws AuthenticationException;

/**
* We should register a new user. The new user entity will contain the email and password
* @param email - user email. should be unique for each user
* @param password - user password
* @return new user instance
*/
User register(String email, String password) throws RegistrationException;
}
39 changes: 39 additions & 0 deletions src/main/java/mate/academy/security/AuthenticationServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package mate.academy.security;

import java.util.Optional;
import mate.academy.exception.AuthenticationException;
import mate.academy.exception.RegistrationException;
import mate.academy.lib.Inject;
import mate.academy.lib.Service;
import mate.academy.model.User;
import mate.academy.service.UserService;
import mate.academy.util.HashUtil;

@Service
public class AuthenticationServiceImpl implements AuthenticationService {
@Inject
private UserService userService;

@Override
public User login(String email, String password) throws AuthenticationException {
Optional<User> userFromDbOptional = userService.findByEmail(email);
if (userFromDbOptional.isEmpty()) {
throw new AuthenticationException("Can't authenticate user " + email);
}
User user = userFromDbOptional.get();
String hashedPassword = HashUtil.hashPassword(password, user.getSalt());
if (user.getPassword().equals(hashedPassword)) {
return user;
}
throw new AuthenticationException("Login or password is incorrect...");
}

@Override
public User register(String email, String password) throws RegistrationException {
Optional<User> userFromDb = userService.findByEmail(email);
if (userFromDb.isPresent() || email.isEmpty() || password.isEmpty()) {
throw new RegistrationException("This email is already taken :" + email);
Comment on lines +34 to +35

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The registration method should hash the password before storing the user. Use HashUtil.hashPassword to hash the password and store the hashed password in the User object.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message should be more descriptive. Consider specifying whether the email is taken or if the email/password is empty.

}
return userService.add(new User(email, password));
}
}
10 changes: 10 additions & 0 deletions src/main/java/mate/academy/service/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package mate.academy.service;

import java.util.Optional;
import mate.academy.model.User;

public interface UserService {
User add(User user);

Optional<User> findByEmail(String email);
}
22 changes: 22 additions & 0 deletions src/main/java/mate/academy/service/impl/UserServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package mate.academy.service.impl;

import java.util.Optional;
import mate.academy.dao.UserDao;
import mate.academy.lib.Inject;
import mate.academy.model.User;
import mate.academy.service.UserService;

public class UserServiceImpl implements UserService {
@Inject
private UserDao userDao;

@Override
public User add(User user) {
return userDao.add(user);
Comment on lines +14 to +15

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure that the user's password is hashed before calling userDao.add(user). Use HashUtil.hashPassword to hash the password and set it in the User object.

}

@Override
public Optional<User> findByEmail(String email) {
return userDao.findByEmail(email);
}
}
34 changes: 34 additions & 0 deletions src/main/java/mate/academy/util/HashUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package mate.academy.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class HashUtil {
private static final String CRYPTO_ALGORITHM = "SHA-512";

private HashUtil() {
}

public static byte[] getSalt() {
SecureRandom securerandom = new SecureRandom();
byte[] salt = new byte[16];
securerandom.nextBytes(salt);
return salt;
}

public static String hashPassword(String password, byte[] salt) {
StringBuilder hashedPassword = new StringBuilder();
try {
MessageDigest messageDigest = MessageDigest.getInstance(CRYPTO_ALGORITHM);
messageDigest.update(salt);
byte[] digest = messageDigest.digest(password.getBytes());
for (byte b : digest) {
hashedPassword.append(String.format("%02x", b));
}
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Couldn't create hash using SHA-512 algorithm", e);
}
return hashedPassword.toString();
}
}
Loading