Skip to content

Commit d7afd6b

Browse files
committed
User service hw solution
1 parent 765e1e1 commit d7afd6b

File tree

10 files changed

+314
-1
lines changed

10 files changed

+314
-1
lines changed

src/main/java/mate/academy/Main.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,24 @@
22

33
import java.time.LocalDate;
44
import java.time.LocalDateTime;
5+
import mate.academy.dao.impl.UserDaoImpl;
6+
import mate.academy.exception.AuthenticationException;
7+
import mate.academy.exception.RegistrationException;
58
import mate.academy.model.CinemaHall;
69
import mate.academy.model.Movie;
710
import mate.academy.model.MovieSession;
11+
import mate.academy.model.User;
12+
import mate.academy.service.AuthenticationService;
813
import mate.academy.service.CinemaHallService;
914
import mate.academy.service.MovieService;
1015
import mate.academy.service.MovieSessionService;
16+
import mate.academy.service.impl.AuthenticationServiceImpl;
17+
import mate.academy.service.impl.UserServiceImpl;
18+
import org.hibernate.SessionFactory;
19+
import org.hibernate.cfg.Configuration;
1120

1221
public class Main {
13-
public static void main(String[] args) {
22+
public static void main(String[] args) throws RegistrationException, AuthenticationException {
1423
MovieService movieService = null;
1524

1625
Movie fastAndFurious = new Movie("Fast and Furious");
@@ -51,5 +60,22 @@ public static void main(String[] args) {
5160
System.out.println(movieSessionService.get(yesterdayMovieSession.getId()));
5261
System.out.println(movieSessionService.findAvailableSessions(
5362
fastAndFurious.getId(), LocalDate.now()));
63+
64+
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
65+
UserDaoImpl userDao = new UserDaoImpl(sessionFactory);
66+
UserServiceImpl userService = new UserServiceImpl(userDao);
67+
AuthenticationService authenticationService = new AuthenticationServiceImpl(userService);
68+
69+
try {
70+
User registeredUser = authenticationService.register("test@example.com", "password123");
71+
System.out.println("Registered user: " + registeredUser);
72+
73+
User loggedInUser = authenticationService.login("test@example.com", "password123");
74+
System.out.println("Logged in user: " + loggedInUser);
75+
} catch (RegistrationException | AuthenticationException e) {
76+
System.out.println("Error: " + e.getMessage());
77+
} finally {
78+
sessionFactory.close();
79+
}
5480
}
5581
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package mate.academy.dao;
2+
3+
import java.util.List;
4+
import java.util.Optional;
5+
import mate.academy.model.User;
6+
7+
public interface UserDao {
8+
User add(User user);
9+
10+
Optional<User> findByEmail(String email);
11+
12+
Optional<User> findById(Long id);
13+
14+
List<User> getAll();
15+
16+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package mate.academy.dao.impl;
2+
3+
import java.util.List;
4+
import java.util.Optional;
5+
import mate.academy.dao.UserDao;
6+
import mate.academy.exception.DataProcessingException;
7+
import mate.academy.model.User;
8+
import org.hibernate.Session;
9+
import org.hibernate.SessionFactory;
10+
import org.hibernate.query.Query;
11+
12+
public class UserDaoImpl implements UserDao {
13+
14+
private final SessionFactory sessionFactory;
15+
16+
public UserDaoImpl(SessionFactory sessionFactory) {
17+
this.sessionFactory = sessionFactory;
18+
}
19+
20+
@Override
21+
public User add(User user) {
22+
try (Session session = sessionFactory.openSession()) {
23+
session.beginTransaction();
24+
session.persist(user);
25+
session.getTransaction().commit();
26+
return user;
27+
} catch (Exception e) {
28+
throw new DataProcessingException("Couldn't add user: " + user, e);
29+
}
30+
}
31+
32+
@Override
33+
public Optional<User> findByEmail(String email) {
34+
try (Session session = sessionFactory.openSession()) {
35+
Query<User> query =
36+
session.createQuery("FROM User u WHERE u.email = :email", User.class);
37+
query.setParameter("email", email);
38+
return query.uniqueResultOptional();
39+
} catch (Exception e) {
40+
throw new DataProcessingException("Couldn't find user by email: " + email, e);
41+
}
42+
}
43+
44+
@Override
45+
public Optional<User> findById(Long id) {
46+
try (Session session = sessionFactory.openSession()) {
47+
return Optional.ofNullable(session.get(User.class, id));
48+
} catch (Exception e) {
49+
throw new DataProcessingException("Couldn't find user by id: " + id, e);
50+
}
51+
}
52+
53+
@Override
54+
public List<User> getAll() {
55+
try (Session session = sessionFactory.openSession()) {
56+
Query<User> query = session.createQuery("FROM User", User.class);
57+
return query.list();
58+
} catch (Exception e) {
59+
throw new DataProcessingException("Couldn't retrieve all users", e);
60+
}
61+
}
62+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package mate.academy.exception;
2+
3+
public class AuthenticationException extends Exception {
4+
public AuthenticationException(String message) {
5+
super(message);
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package mate.academy.exception;
2+
3+
public class RegistrationException extends Exception {
4+
public RegistrationException(String message) {
5+
super(message);
6+
}
7+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package mate.academy.model;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.GeneratedValue;
5+
import jakarta.persistence.GenerationType;
6+
import jakarta.persistence.Id;
7+
import jakarta.persistence.Table;
8+
import java.util.Arrays;
9+
10+
@Entity
11+
@Table (name = "users")
12+
public class User {
13+
@Id
14+
@GeneratedValue(strategy = GenerationType.IDENTITY)
15+
private Long id;
16+
private String email;
17+
private String password;
18+
private byte[] salt;
19+
20+
public User() {
21+
}
22+
23+
public User(String email, String password) {
24+
this.email = email;
25+
this.password = password;
26+
}
27+
28+
public Long getId() {
29+
return id;
30+
}
31+
32+
public void setId(Long id) {
33+
this.id = id;
34+
}
35+
36+
public String getEmail() {
37+
return email;
38+
}
39+
40+
public void setEmail(String email) {
41+
this.email = email;
42+
}
43+
44+
public String getPassword() {
45+
return password;
46+
}
47+
48+
public void setPassword(String password) {
49+
this.password = password;
50+
}
51+
52+
public byte[] getSalt() {
53+
return salt;
54+
}
55+
56+
public void setSalt(byte[] salt) {
57+
this.salt = salt;
58+
}
59+
60+
@Override
61+
public String toString() {
62+
return "User{"
63+
+ "id=" + id
64+
+ ", email='" + email + '\''
65+
+ ", password='" + password + '\''
66+
+ ", salt=" + Arrays.toString(salt) + '}';
67+
}
68+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package mate.academy.service;
2+
3+
import mate.academy.exception.AuthenticationException;
4+
import mate.academy.exception.RegistrationException;
5+
import mate.academy.model.User;
6+
7+
public interface AuthenticationService {
8+
User login(String email, String password) throws AuthenticationException;
9+
10+
User register(String email, String password) throws RegistrationException;
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package mate.academy.service;
2+
3+
import java.util.Optional;
4+
import mate.academy.model.User;
5+
6+
public interface UserService {
7+
User add(User user);
8+
9+
Optional<User> findByEmail(String email);
10+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package mate.academy.service.impl;
2+
3+
import java.security.MessageDigest;
4+
import java.security.NoSuchAlgorithmException;
5+
import java.security.SecureRandom;
6+
import java.util.Optional;
7+
import mate.academy.exception.AuthenticationException;
8+
import mate.academy.exception.RegistrationException;
9+
import mate.academy.lib.Inject;
10+
import mate.academy.lib.Service;
11+
import mate.academy.model.User;
12+
import mate.academy.service.AuthenticationService;
13+
import mate.academy.service.UserService;
14+
15+
@Service
16+
public class AuthenticationServiceImpl implements AuthenticationService {
17+
18+
private static final String HASHING_ALGORITHM = "SHA-256";
19+
@Inject
20+
private final UserService userService;
21+
22+
public AuthenticationServiceImpl(UserService userService) {
23+
this.userService = userService;
24+
}
25+
26+
@Override
27+
public User login(String email, String password) throws AuthenticationException {
28+
Optional<User> optionalUser = userService.findByEmail(email);
29+
if (optionalUser.isEmpty()) {
30+
throw new AuthenticationException("User not found by email: " + email);
31+
}
32+
User user = optionalUser.get();
33+
String hashedPassword = hashPassword(password, user.getSalt());
34+
if (!user.getPassword().equals(hashedPassword)) {
35+
throw new AuthenticationException("Invalid password");
36+
}
37+
return user;
38+
}
39+
40+
@Override
41+
public User register(String email, String password) throws RegistrationException {
42+
if (userService.findByEmail(email).isPresent()) {
43+
throw new RegistrationException("Email is already taken: " + email);
44+
}
45+
byte[] salt = generateSalt();
46+
String hashedPassword = hashPassword(password, salt);
47+
User user = new User(email, hashedPassword);
48+
user.setSalt(salt);
49+
return userService.add(user);
50+
}
51+
52+
private String hashPassword(String password, byte[] salt) {
53+
try {
54+
MessageDigest digest = MessageDigest.getInstance(HASHING_ALGORITHM);
55+
digest.update(salt);
56+
byte[] hashedBytes = digest.digest(password.getBytes());
57+
StringBuilder hashedPassword = new StringBuilder();
58+
for (byte b : hashedBytes) {
59+
hashedPassword.append(String.format("%02x", b));
60+
}
61+
return hashedPassword.toString();
62+
} catch (NoSuchAlgorithmException e) {
63+
throw new RuntimeException("Could not hash password", e);
64+
}
65+
}
66+
67+
private byte[] generateSalt() {
68+
byte[] salt = new byte[16];
69+
new SecureRandom().nextBytes(salt);
70+
return salt;
71+
}
72+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package mate.academy.service.impl;
2+
3+
import java.util.Optional;
4+
import mate.academy.dao.UserDao;
5+
import mate.academy.exception.DataProcessingException;
6+
import mate.academy.model.User;
7+
import mate.academy.service.UserService;
8+
9+
public class UserServiceImpl implements UserService {
10+
11+
private final UserDao userDao;
12+
13+
public UserServiceImpl(UserDao userDao) {
14+
this.userDao = userDao;
15+
}
16+
17+
@Override
18+
public User add(User user) {
19+
try {
20+
return userDao.add(user);
21+
} catch (Exception e) {
22+
throw new DataProcessingException("Couldn't add user: " + user, e);
23+
}
24+
}
25+
26+
@Override
27+
public Optional<User> findByEmail(String email) {
28+
try {
29+
return userDao.findByEmail(email);
30+
} catch (Exception e) {
31+
throw new DataProcessingException("Couldn't find user by email: " + email, e);
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)