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
4 changes: 2 additions & 2 deletions RestroHub-FrontEnd/src/pages/public/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ const Login = () => {
}
} catch (err) {
toast.error(
err.response?.data?.message || "Invalid username or password"
err.response?.data?.message || "Invalid email or password"
);
Comment on lines 187 to 190
} finally {
setIsLoading(false);
Expand Down Expand Up @@ -327,7 +327,7 @@ const handleGoogleLogin = async (credentialResponse) => {
value={formik.values.username}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
className={inputClass("username")}
className={inputClass("email")}
/>
<span className="pointer-events-none absolute right-4 top-1/2 -translate-y-1/2">
<EmailIcon />
Expand Down
3 changes: 1 addition & 2 deletions RestroHub-FrontEnd/src/services/common/api.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import axios from "axios";

const api = axios.create({
baseURL:
import.meta.env.VITE_API_BASE_URL || "http://localhost:8181/restroly",
baseURL: import.meta.env.VITE_API_BASE_URL || "http://localhost:8181/restroly",
});

// Add interceptor
Expand Down
2 changes: 1 addition & 1 deletion RestroHub-FrontEnd/src/services/public/ApiService.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Handles all API calls for the application
// ============================================

const API_BASE_URL = 'http://localhost:8181/restroly';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8181/restroly';

// Helper function for making API requests
const apiRequest = async (endpoint, options = {}) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public ResponseEntity<ApiResponse<AuthResponse>> register(
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 86400,
"username": "admin",
"email": "admin@restroly.com",
"roles": ["ROLE_ADMIN"]
},
"timestamp": "2024-01-15T10:30:00"
Expand All @@ -107,7 +107,7 @@ public ResponseEntity<ApiResponse<AuthResponse>> register(
{
"status": 401,
"error": "UNAUTHORIZED",
"message": "Invalid username or password",
"message": "Invalid email or password",
"path": "/api/v1/auth/login",
Comment on lines 107 to 111
"timestamp": "2024-01-15T10:30:00",
"traceId": "abc123"
Expand All @@ -124,7 +124,7 @@ public ResponseEntity<ApiResponse<AuthResponse>> register(
schema = @Schema(implementation = LoginRequest.class),
examples = @ExampleObject(value = """
{
"username": "admin",
"email": "admin@restroly.com",
"password": "admin123"
}
""")
Expand All @@ -133,7 +133,7 @@ public ResponseEntity<ApiResponse<AuthResponse>> register(
public ResponseEntity<ApiResponse<AuthResponse>> login(
@Valid @RequestBody LoginRequest loginRequest) {

log.info("Login request received for user: {}", loginRequest.getUsername());
log.info("Login request received for user: {}", loginRequest.getEmail());

AuthResponse authResponse = authService.login(loginRequest);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public class AuthResponse {
@Schema(description = "Token expiration time in seconds", example = "86400")
private Long expiresIn;

@Schema(description = "Username of authenticated user", example = "admin")
private String username;
@Schema(description = "Email of authenticated user", example = "admin@restroly.com")
private String email;
Comment on lines +31 to +32

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@latakshsariyapatidar changes username to emails in other classes

Comment on lines +31 to +32

@Schema(description = "User roles", example = "[\"ROLE_ADMIN\"]")
private List<String> roles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
@Schema(description = "Login request payload")
public class LoginRequest {

@NotBlank(message = "Username is required")
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
@Schema(description = "Username", example = "admin", requiredMode = Schema.RequiredMode.REQUIRED)
private String username;
@NotBlank(message = "Email is required")
@jakarta.validation.constraints.Email(message = "Invalid email format")
@Schema(description = "Email", example = "admin@restroly.com", requiredMode = Schema.RequiredMode.REQUIRED)
private String email;
Comment on lines +15 to +18

@NotBlank(message = "Password is required")
@Size(min = 6, max = 100, message = "Password must be between 6 and 100 characters")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ public class AuthServiceImpl implements AuthService {

@Override
public AuthResponse login(LoginRequest loginRequest) {
log.info("Login attempt for user: {}", loginRequest.getUsername());
log.info("Login attempt for user: {}", loginRequest.getEmail());

try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getEmail(),
loginRequest.getPassword()
)
);
Expand All @@ -64,22 +64,22 @@ public AuthResponse login(LoginRequest loginRequest) {
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList());

log.info("User {} logged in successfully", loginRequest.getUsername());
log.info("User {} logged in successfully", loginRequest.getEmail());

return AuthResponse.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.tokenType("Bearer")
.expiresIn(jwtTokenProvider.getExpirationInSeconds())
.username(userDetails.getUsername())
.email(userDetails.getUsername())
.roles(roles)
.build();

} catch (BadCredentialsException ex) {
log.warn("Failed login attempt for user: {}", loginRequest.getUsername());
log.warn("Failed login attempt for user: {}", loginRequest.getEmail());
throw new BadCredentialsException("Invalid username or password");

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@latakshsariyapatidar Change this

} catch (AuthenticationException ex) {
log.error("Authentication error for user {}: {}", loginRequest.getUsername(), ex.getMessage());
log.error("Authentication error for user {}: {}", loginRequest.getEmail(), ex.getMessage());
throw new BusinessException("Authentication failed: " + ex.getMessage());
}
}
Expand Down Expand Up @@ -116,7 +116,7 @@ public AuthResponse refreshToken(RefreshTokenRequest refreshTokenRequest) {
.refreshToken(newRefreshToken)
.tokenType("Bearer")
.expiresIn(jwtTokenProvider.getExpirationInSeconds())
.username(username)
.email(username)
.roles(roles)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.restroly.qrmenu.config;

import com.restroly.qrmenu.user.entity.Role;
import com.restroly.qrmenu.user.entity.User;
import com.restroly.qrmenu.user.repository.RoleRepository;
import com.restroly.qrmenu.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

@Component
@RequiredArgsConstructor
@Slf4j
public class DataInitializer implements CommandLineRunner {
Comment on lines +9 to +20

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@latakshsariyapatidar Delete DataInitializer class as it is not required.


private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final PasswordEncoder passwordEncoder;

@Override
@Transactional
public void run(String... args) {
log.info("Initializing default roles and users...");

// Initialize Roles
Role adminRole = createRoleIfNotFound("ROLE_ADMIN", "Administrator role");
Role userRole = createRoleIfNotFound("ROLE_USER", "Standard user role");
Role ownerRole = createRoleIfNotFound("ROLE_RESTAURANT_OWNER", "Restaurant owner role");

// Initialize Users
createUserIfNotFound("admin@restroly.com", "admin123", "System Admin", Arrays.asList(adminRole, userRole));
createUserIfNotFound("owner@restroly.com", "owner123", "Restaurant Owner", Arrays.asList(ownerRole, userRole));
createUserIfNotFound("user@restroly.com", "user123", "Normal User", Arrays.asList(userRole));

log.info("Data initialization completed.");
}

private Role createRoleIfNotFound(String name, String description) {
return roleRepository.findByName(name)
.orElseGet(() -> {
Role role = Role.builder()
.name(name)
.description(description)
.isActive(true)
.build();
return roleRepository.save(role);
});
}

private void createUserIfNotFound(String email, String password, String name, List<Role> roles) {
if (!userRepository.existsByEmail(email)) {
User user = User.builder()
.email(email)
.password(passwordEncoder.encode(password))
.name(name)
.roles(roles)
.isActive(true)
.build();
userRepository.save(user);
log.info("Created default user: {}", email);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.restroly.qrmenu.security;

import com.restroly.qrmenu.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
Expand All @@ -8,9 +9,9 @@
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;


import com.restroly.qrmenu.security.exception.UserDisabledException;
import com.restroly.qrmenu.security.exception.UserLockedException;

import java.util.List;
import java.util.stream.Collectors;

Expand All @@ -19,8 +20,9 @@
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {

private final UserRepository userRepository;
private final com.restroly.qrmenu.user.repository.UserRepository userRepository;

Comment on lines +23 to +25

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@latakshsariyapatidar remove 1 userRepository as it is declared twice

@Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
Expand All @@ -31,6 +33,7 @@ public UserDetails loadUserByUsername(String email)
log.warn("User not found with email: {}", email);
return new UsernameNotFoundException("User not found with email: " + email);
});

// Check if the user account is active
if (!user.isActive()) {
log.warn("User account is inactive: {}", email);
Expand All @@ -42,7 +45,6 @@ public UserDetails loadUserByUsername(String email)
log.warn("User account is locked: {}", email);
throw new UserLockedException("User account is locked");
}

List<SimpleGrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
Expand All @@ -52,9 +54,9 @@ public UserDetails loadUserByUsername(String email)
return org.springframework.security.core.userdetails.User.builder()
.username(user.getEmail())
.password(user.getPassword())
.authorities(authorities)
.disabled(!user.isActive())
.accountLocked(user.isLocked())
.authorities(authorities)
.build();
}
}