Skip to content

Commit

Permalink
Cria a entidade Account e configura Spring Security
Browse files Browse the repository at this point in the history
  • Loading branch information
AlefMemTav committed Aug 15, 2024
1 parent b722cb2 commit 71b2cfe
Show file tree
Hide file tree
Showing 11 changed files with 404 additions and 3 deletions.
4 changes: 4 additions & 0 deletions mvp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand Down
122 changes: 122 additions & 0 deletions mvp/src/main/java/com/mymarket/mvp/accounts/Account.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.mymarket.mvp.accounts;

import java.io.Serial;
import java.io.Serializable;

import org.hibernate.validator.constraints.Length;

import com.fasterxml.jackson.annotation.JsonIgnore;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

/**
* The Account entity represents user account in the application.
*
* @author Pedro Lucas
* @since 1.0
*/
@Entity
@Table(name = "accounts", uniqueConstraints = {@UniqueConstraint(columnNames = {"username"})})
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = "id")
@ToString(of = {"id", "firstName"})
public final class Account implements Serializable {

/**
* The serialVersionUID.
*/
@Serial
private static final long serialVersionUID = 221625420706334299L;

/**
* The unique identifier for the account.
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

/**
* The username for authentication. Must contain only letters and numbers.
*/
@Column(length = 23, nullable = false, unique = true)
@Length(min = 6, max = 23)
@NotBlank(message = "The username cannot be blank")
@Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z\\d]+$", message = "The username must contain only letters (at least one letter) and numbers (at least one number)")
private String username;

/**
* The password for authentication. Must contain at least one letter and one
* number.
*/
@Column(name = "password", nullable = false)
@JsonIgnore
@NotBlank(message = "The password cannot be blank")
private String password;

/**
* The first name of the account holder.
*/
@Column(length = 30, nullable = false)
@Length(min = 1, max = 30)
@NotBlank(message = "The name cannot be blank")
private String firstName;

/**
* (Optional) The last name or surname of the account holder.
*/
@Column(length = 30)
@Length(max = 30)
private String lastName;

/**
* Indicates whether it is account non expired. False by default.
*/
@Column(columnDefinition = "boolean default false", nullable = false)
private boolean isAccountNonExpired;

/**
* Indicates whether it is account non-locked. False by default.
*/
@Column(columnDefinition = "boolean default false", nullable = false)
private boolean isAccountNonLocked;

/**
* Indicates whether it is account with credentials non expired. False by
* default.
*/
@Column(columnDefinition = "boolean default false", nullable = false)
private boolean isCredentialsNonExpired;

/**
* Indicates whether it is enabled. False by default.
*/
@Column(columnDefinition = "boolean default false", nullable = false)
private boolean isEnabled;

/**
* The role of the account in the system.
*/
@Column(name = "role", nullable = false)
@Enumerated(EnumType.STRING)
private Role role;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mymarket.mvp.accounts;

public class AccountController {

}
11 changes: 11 additions & 0 deletions mvp/src/main/java/com/mymarket/mvp/accounts/AccountRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.mymarket.mvp.accounts;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AccountRepository extends JpaRepository<Account, Long>{
Optional<Account> findByUsername(String username);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mymarket.mvp.accounts;

public class AccountService {

}
16 changes: 16 additions & 0 deletions mvp/src/main/java/com/mymarket/mvp/accounts/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.mymarket.mvp.accounts;

public enum Role {
ROLE_ADMIN("admin"), ROLE_USER("user");

private final String value;

Role(String value) {
this.value = value;
}

public String getValue() {
return value;
}

}
69 changes: 69 additions & 0 deletions mvp/src/main/java/com/mymarket/mvp/accounts/UserDetail.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.mymarket.mvp.accounts;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serial;
import java.util.Collection;
import java.util.List;

/**
* UserDetail implements the UserDetails interface for Spring Security
* integration.
*
* @since 1.0
* @author Pedro Lucas
*/
public class UserDetail implements UserDetails {

/** The serial version UID. */
@Serial
private static final long serialVersionUID = -6676620567638122748L;

private final Account account;

public UserDetail(Account account) {
this.account = account;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
if (this.account.getRole() == Role.ROLE_ADMIN) {
return List.of(new SimpleGrantedAuthority("ROLE_ADMIN"), new SimpleGrantedAuthority("ROLE_USER"));
} else {
return List.of(new SimpleGrantedAuthority("ROLE_USER"));
}
}

@Override
public String getPassword() {
return this.account.getPassword();
}

@Override
public String getUsername() {
return this.account.getUsername();
}

@Override
public boolean isAccountNonExpired() {
return this.account.isAccountNonExpired();
}

@Override
public boolean isAccountNonLocked() {
return this.account.isAccountNonLocked();
}

@Override
public boolean isCredentialsNonExpired() {
return this.account.isCredentialsNonExpired();
}

@Override
public boolean isEnabled() {
return this.account.isEnabled();
}

}
21 changes: 21 additions & 0 deletions mvp/src/main/java/com/mymarket/mvp/accounts/UserDetailService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mymarket.mvp.accounts;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserDetailService implements UserDetailsService {
private final AccountRepository accountRepository;

public UserDetailService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return this.accountRepository.findByUsername(username).map(UserDetail::new)
.orElseThrow(() -> new UsernameNotFoundException("Username not found: " + username));
}
}
32 changes: 32 additions & 0 deletions mvp/src/main/java/com/mymarket/mvp/shared/config/MvcConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.mymarket.mvp.shared.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

@Bean
LocaleResolver localeResolver() {
return new SessionLocaleResolver();
}

@Bean
LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}

@Override
public void addInterceptors(@NonNull InterceptorRegistry interceptorRegistry) {
interceptorRegistry.addInterceptor(localeChangeInterceptor());
}

}
Loading

0 comments on commit 71b2cfe

Please sign in to comment.