Skip to content

Commit

Permalink
sp
Browse files Browse the repository at this point in the history
  • Loading branch information
nkonev committed Nov 16, 2023
1 parent 285eac3 commit aa408cd
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 35 deletions.
2 changes: 2 additions & 0 deletions aaa/src/main/java/com/github/nkonev/aaa/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public static class PathVariables {

public static final String DELETED = "deleted";

public static final Long NonExistentUser = -65000L;

public static final Set<String> FORBIDDEN_USERNAMES = Set.of(DELETED, "all", "here");

public static final int MIN_PASSWORD_LENGTH = 6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,30 @@ public com.github.nkonev.aaa.dto.UserAccountDTOExtended convertToUserAccountDTOE
);
}

public com.github.nkonev.aaa.dto.UserAccountDTOExtended convertToUserAccountDTOExtendedForAdmin(UserAccount userAccount) {
if (userAccount == null) { return null; }
com.github.nkonev.aaa.dto.UserAccountDTOExtended.DataDTO dataDTO;
if (aaaSecurityService.hasSessionManagementPermissionForAdmin()){
dataDTO = new com.github.nkonev.aaa.dto.UserAccountDTOExtended.DataDTO(userAccount.enabled(), userAccount.expired(), userAccount.locked(), Set.of(userAccount.role()));
} else {
dataDTO = null;
}
return new UserAccountDTOExtended(
userAccount.id(),
userAccount.username(),
userAccount.avatar(),
userAccount.avatarBig(),
userAccount.shortInfo(),
dataDTO,
userAccount.lastLoginDateTime(),
convertOauth(userAccount.oauth2Identifiers()),
aaaSecurityService.canLock(currentUser, userAccount),
aaaSecurityService.canDelete(currentUser, userAccount),
aaaSecurityService.canChangeRole(currentUser, userAccount)
);
}


private static void validateUserPassword(String password) {
Assert.notNull(password, "password must be set");
if (password.length() < Constants.MIN_PASSWORD_LENGTH || password.length() > Constants.MAX_PASSWORD_LENGTH) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package com.github.nkonev.aaa.dto;

import java.util.Set;

public record UserAccountEventDTO(
ForWho forWho,
Set<UserRole> forWhoRoles,
Long userId, // nullable
String eventType,

UserAccountDTO userAccount
Object userAccount
) {

public enum ForWho {
FOR_MYSELF,
FOR_ROLE,
FOR_ROLE_USER,
FOR_ROLE_ADMIN,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Optional;

/**
Expand All @@ -24,37 +25,31 @@ public class AaaSecurityService {
@Autowired
private UserAccountRepository userAccountRepository;

public boolean hasSessionManagementPermission(UserAccountDetailsDTO userAccount) {
private UserAccount deleted;

@PostConstruct
public void postConstruct() {
deleted = userAccountRepository.findByUsername(Constants.DELETED).orElseThrow();
}

public boolean hasSessionManagementPermission(PrincipalToCheck userAccount) {
if (userAccount==null){
return false;
}
return roleHierarchy.getReachableGrantedAuthorities(userAccount.getAuthorities()).contains(new SimpleGrantedAuthority(UserRole.ROLE_ADMIN.name()));
return userAccount.isAdmin();
}

public boolean canLock(UserAccountDetailsDTO userAccount, LockDTO lockDTO) {
public boolean canLock(PrincipalToCheck userAccount, LockDTO lockDTO) {
if (userAccount==null){
return false;
}
if (lockDTO!=null && userAccount.getId().equals(lockDTO.userId())){
return false;
}
if (roleHierarchy.getReachableGrantedAuthorities(userAccount.getAuthorities()).contains(new SimpleGrantedAuthority(UserRole.ROLE_ADMIN.name()))){
return true;
} else {
return false;
}
}

public boolean hasSettingsPermission(UserAccountDetailsDTO userAccount) {
return Optional
.ofNullable(userAccount)
.map(u -> u.getAuthorities()
.contains(new SimpleGrantedAuthority(UserRole.ROLE_ADMIN.name())))
.orElse(false);
return userAccount.isAdmin();
}

public boolean canDelete(UserAccountDetailsDTO userAccount, long userIdToDelete) {
UserAccount deleted = userAccountRepository.findByUsername(Constants.DELETED).orElseThrow();
if (deleted.id().equals(userIdToDelete)){
return false;
}
Expand All @@ -71,31 +66,30 @@ public boolean canSelfDelete(UserAccountDetailsDTO userAccount) {
.ofNullable(userAccount).isPresent();
}

public boolean canChangeRole(UserAccountDetailsDTO currentUser, long userAccountId) {
public boolean canChangeRole(PrincipalToCheck currentUser, long userAccountId) {
UserAccount userAccount = userAccountRepository.findById(userAccountId).orElseThrow();
return lockAndDelete(currentUser, userAccount);
}

public boolean canLock(UserAccountDetailsDTO currentUser, UserAccount userAccount) {
public boolean canLock(PrincipalToCheck currentUser, UserAccount userAccount) {
return lockAndDelete(currentUser, userAccount);
}

public boolean canDelete(UserAccountDetailsDTO currentUser, UserAccount userAccount) {
public boolean canDelete(PrincipalToCheck currentUser, UserAccount userAccount) {
return lockAndDelete(currentUser, userAccount);
}

public boolean canChangeRole(UserAccountDetailsDTO currentUser, UserAccount userAccount) {
public boolean canChangeRole(PrincipalToCheck currentUser, UserAccount userAccount) {
return lockAndDelete(currentUser, userAccount);
}

private boolean lockAndDelete(UserAccountDetailsDTO currentUser, UserAccount userAccount) {
private boolean lockAndDelete(PrincipalToCheck currentUser, UserAccount userAccount) {
if (userAccount == null) {
return false;
}
if (currentUser == null) {
return false;
return false;
}
UserAccount deleted = userAccountRepository.findByUsername(Constants.DELETED).orElseThrow();
if (deleted.id().equals(userAccount.id())){
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.github.nkonev.aaa.security;

import com.github.nkonev.aaa.dto.UserAccountDetailsDTO;
import com.github.nkonev.aaa.dto.UserRole;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import static com.github.nkonev.aaa.Constants.NonExistentUser;

public sealed interface PrincipalToCheck permits KnownAdmin, UserToCheck {
boolean isAdmin();

Long getId();

static PrincipalToCheck knownAdmin() {
return new KnownAdmin();
}

static PrincipalToCheck ofUserAccount(UserAccountDetailsDTO userAccount, RoleHierarchy roleHierarchy) {
return new UserToCheck(userAccount, roleHierarchy);
}
}

final class KnownAdmin implements PrincipalToCheck {

@Override
public boolean isAdmin() {
return true;
}

@Override
public Long getId() {
return NonExistentUser;
}
}

final class UserToCheck implements PrincipalToCheck {

private final UserAccountDetailsDTO userAccount;

private final RoleHierarchy roleHierarchy;

UserToCheck(UserAccountDetailsDTO userAccount, RoleHierarchy roleHierarchy) {
this.userAccount = userAccount;
this.roleHierarchy = roleHierarchy;
}

@Override
public boolean isAdmin() {
return roleHierarchy.getReachableGrantedAuthorities(userAccount.getAuthorities()).contains(new SimpleGrantedAuthority(UserRole.ROLE_ADMIN.name()));
}

@Override
public Long getId() {
return userAccount.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,33 @@

import static com.github.nkonev.aaa.config.RabbitMqConfig.EXCHANGE_PROFILE_EVENTS_NAME;
import static com.github.nkonev.aaa.config.RabbitMqConfig.EXCHANGE_ONLINE_EVENTS_NAME;
import static com.github.nkonev.aaa.converter.UserAccountConverter.convertToUserAccountDetailsDTO;

@Service
public class EventService {

@Autowired
private RabbitTemplate rabbitTemplate;

@Autowired
private UserAccountConverter userAccountConverter;

public void notifyProfileUpdated(UserAccount userAccount) {
var data = Set.of(
new UserAccountEventDTO(
UserAccountEventDTO.ForWho.FOR_MYSELF,
null,
userAccount.id(),
"user_account_changed",
UserAccountConverter.convertToUserAccountDTOExtended(userAccount)
userAccountConverter.convertToUserAccountDTOExtended(convertToUserAccountDetailsDTO(userAccount), userAccount)
),
new UserAccountEventDTO(
UserAccountEventDTO.ForWho.FOR_ROLE,
Set.of(UserRole.ROLE_ADMIN),
UserAccountEventDTO.ForWho.FOR_ROLE_ADMIN,
null,
"user_account_changed",
UserAccountConverter.convertToUserAccountDTO(userAccount)
userAccountConverter.convertToUserAccountDTOExtendedForAdmin(userAccount)
),
new UserAccountEventDTO(
UserAccountEventDTO.ForWho.FOR_ROLE,
Set.of(UserRole.ROLE_USER),
UserAccountEventDTO.ForWho.FOR_ROLE_USER,
null,
"user_account_changed",
UserAccountConverter.convertToUserAccountDTO(userAccount)
Expand Down

0 comments on commit aa408cd

Please sign in to comment.