root/resilient#3 Melhorias no registo de utilizadores
This commit is contained in:
parent
2aa75f0e13
commit
af63377a1e
11 changed files with 186 additions and 15 deletions
|
@ -76,6 +76,12 @@ public class User extends AbstractAuditingEntity<Long> implements Serializable {
|
|||
@Column(nullable = false)
|
||||
private boolean activated = false;
|
||||
|
||||
@Column(name = "allow_user_pwd_auth")
|
||||
private boolean allowUserPwdAuthentication = false;
|
||||
|
||||
@Column(name = "allow_saml_auth")
|
||||
private boolean allowSamlAuthentication = false;
|
||||
|
||||
@Size(min = 2, max = 10)
|
||||
@Column(name = "lang_key", length = 10)
|
||||
private String langKey;
|
||||
|
@ -183,6 +189,22 @@ public class User extends AbstractAuditingEntity<Long> implements Serializable {
|
|||
return activationKey;
|
||||
}
|
||||
|
||||
public void setAllowSamlAuthentication(boolean allowSamlAuthentication) {
|
||||
this.allowSamlAuthentication = allowSamlAuthentication;
|
||||
}
|
||||
|
||||
public boolean getAllowSamlAuthentication() {
|
||||
return allowSamlAuthentication;
|
||||
}
|
||||
|
||||
public void setAllowUserPwdAuthentication(boolean allowUserPwdAuthentication) {
|
||||
this.allowUserPwdAuthentication = allowUserPwdAuthentication;
|
||||
}
|
||||
|
||||
public boolean getAllowUserPwdAuthentication() {
|
||||
return allowUserPwdAuthentication;
|
||||
}
|
||||
|
||||
public void setActivationKey(String activationKey) {
|
||||
this.activationKey = activationKey;
|
||||
}
|
||||
|
@ -260,8 +282,19 @@ public class User extends AbstractAuditingEntity<Long> implements Serializable {
|
|||
// prettier-ignore
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" + "login='" + login + '\'' + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\''
|
||||
+ ", email='" + email + '\'' + ", imageUrl='" + imageUrl + '\'' + ", activated='" + activated + '\''
|
||||
+ ", langKey='" + langKey + '\'' + ", activationKey='" + activationKey + '\'' + "}";
|
||||
//@formatter:off
|
||||
return "User{"
|
||||
+ "login='" + login + '\''
|
||||
+ ", firstName='" + firstName + '\''
|
||||
+ ", lastName='" + lastName + '\''
|
||||
+ ", email='" + email + '\''
|
||||
+ ", imageUrl='" + imageUrl + '\''
|
||||
+ ", activated='" + activated + '\''
|
||||
+ ", allowSamlAuthentication='" + allowSamlAuthentication + '\''
|
||||
+ ", allowUserPwdAuthentication='" + allowUserPwdAuthentication + '\''
|
||||
+ ", langKey='" + langKey + '\''
|
||||
+ ", activationKey='" + activationKey + '\''
|
||||
+ "}";
|
||||
//@formatter:on
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.oguerreiro.resilient.security;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator;
|
||||
|
@ -66,16 +67,44 @@ public class DomainUserDetailsService implements UserDetailsService {
|
|||
public UserDetails loadUserByUsername(final String login) {
|
||||
log.debug("Authenticating {}", login);
|
||||
|
||||
UserDetails userDetails = null;
|
||||
AtomicBoolean allowUserPwdAuthentication = new AtomicBoolean(false);
|
||||
|
||||
if (new EmailValidator().isValid(login, null)) {
|
||||
return userRepository.findOneWithAuthoritiesByEmailIgnoreCase(login).map(
|
||||
user -> createResilientSecurityUser(login, user)).orElseThrow(
|
||||
() -> new UsernameNotFoundException("User with email " + login + " was not found in the database"));
|
||||
//@formatter:off
|
||||
userDetails = userRepository.findOneWithAuthoritiesByEmailIgnoreCase(login)
|
||||
.map(user -> {
|
||||
allowUserPwdAuthentication.set(user.getAllowUserPwdAuthentication());
|
||||
return createResilientSecurityUser(login, user);
|
||||
})
|
||||
.orElseThrow(
|
||||
() -> new UsernameNotFoundException("User with email " + login + " was not found in the database")
|
||||
);
|
||||
//@formatter:on
|
||||
} else {
|
||||
String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
|
||||
//@formatter:off
|
||||
userDetails = userRepository.findOneWithAuthoritiesByLogin(lowercaseLogin)
|
||||
.map(user -> {
|
||||
allowUserPwdAuthentication.set(user.getAllowUserPwdAuthentication());
|
||||
return createResilientSecurityUser(lowercaseLogin, user);
|
||||
})
|
||||
.orElseThrow(
|
||||
() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database")
|
||||
);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
|
||||
return userRepository.findOneWithAuthoritiesByLogin(lowercaseLogin).map(
|
||||
user -> createResilientSecurityUser(lowercaseLogin, user)).orElseThrow(
|
||||
() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database"));
|
||||
if (userDetails == null) {
|
||||
throw new UsernameNotFoundException("User " + login + " was not found in the database");
|
||||
}
|
||||
|
||||
if (!allowUserPwdAuthentication.get()) {
|
||||
// The user can't login with User + Password
|
||||
throw new UsernameNotFoundException("User " + login + " not allowed for login with User + Password.");
|
||||
}
|
||||
|
||||
return userDetails;
|
||||
}
|
||||
|
||||
private org.springframework.security.core.userdetails.User createSpringSecurityUser(String lowercaseLogin,
|
||||
|
|
|
@ -84,6 +84,13 @@ public class Saml2AuthenticationHandler implements AuthenticationSuccessHandler,
|
|||
|
||||
User user = userRepository.findOneByLogin(username).orElse(null);
|
||||
if (user != null) {
|
||||
// This user can login with SAML2 ?
|
||||
if (!user.getAllowSamlAuthentication()) {
|
||||
log.error("The user '" + username + "' it's not allowed to login with SAML2 authentication.");
|
||||
this.invalidateLogin(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
// User found. Setup permissions from resilient config
|
||||
authorities = user.getAuthorities().stream()
|
||||
|
|
|
@ -201,6 +201,8 @@ public class UserService {
|
|||
}
|
||||
user.setImageUrl(userDTO.getImageUrl());
|
||||
user.setActivated(userDTO.isActivated());
|
||||
user.setAllowSamlAuthentication(userDTO.isAllowSamlAuthentication());
|
||||
user.setAllowUserPwdAuthentication(userDTO.isAllowUserPwdAuthentication());
|
||||
user.setLangKey(userDTO.getLangKey());
|
||||
Set<Authority> managedAuthorities = user.getAuthorities();
|
||||
managedAuthorities.clear();
|
||||
|
|
|
@ -47,6 +47,8 @@ public class AdminUserDTO implements Serializable {
|
|||
private String imageUrl;
|
||||
|
||||
private boolean activated = false;
|
||||
private boolean allowUserPwdAuthentication = false;
|
||||
private boolean allowSamlAuthentication = false;
|
||||
|
||||
@Size(min = 2, max = 10)
|
||||
private String langKey;
|
||||
|
@ -76,6 +78,8 @@ public class AdminUserDTO implements Serializable {
|
|||
this.lastName = user.getLastName();
|
||||
this.email = user.getEmail();
|
||||
this.activated = user.isActivated();
|
||||
this.allowSamlAuthentication = user.getAllowSamlAuthentication();
|
||||
this.allowUserPwdAuthentication = user.getAllowUserPwdAuthentication();
|
||||
this.imageUrl = user.getImageUrl();
|
||||
this.langKey = user.getLangKey();
|
||||
this.createdBy = user.getCreatedBy();
|
||||
|
@ -221,13 +225,43 @@ public class AdminUserDTO implements Serializable {
|
|||
this.parentOrganization = parentOrganization;
|
||||
}
|
||||
|
||||
public boolean isAllowUserPwdAuthentication() {
|
||||
return allowUserPwdAuthentication;
|
||||
}
|
||||
|
||||
public void setAllowUserPwdAuthentication(boolean allowUserPwdAuthentication) {
|
||||
this.allowUserPwdAuthentication = allowUserPwdAuthentication;
|
||||
}
|
||||
|
||||
public boolean isAllowSamlAuthentication() {
|
||||
return allowSamlAuthentication;
|
||||
}
|
||||
|
||||
public void setAllowSamlAuthentication(boolean allowSamlAuthentication) {
|
||||
this.allowSamlAuthentication = allowSamlAuthentication;
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AdminUserDTO{" + "login='" + login + '\'' + ", firstName='" + firstName + '\'' + ", lastName='" + lastName
|
||||
+ '\'' + ", email='" + email + '\'' + ", imageUrl='" + imageUrl + '\'' + ", activated=" + activated
|
||||
+ ", langKey='" + langKey + '\'' + ", createdBy=" + createdBy + ", createdDate=" + createdDate
|
||||
+ ", lastModifiedBy='" + lastModifiedBy + '\'' + ", lastModifiedDate=" + lastModifiedDate + ", authorities="
|
||||
+ authorities + "}";
|
||||
//@formatter:off
|
||||
return "AdminUserDTO{"
|
||||
+ "login='" + login + '\''
|
||||
+ ", firstName='" + firstName + '\''
|
||||
+ ", lastName='" + lastName + '\''
|
||||
+ ", email='" + email + '\''
|
||||
+ ", imageUrl='" + imageUrl + '\''
|
||||
+ ", activated=" + activated
|
||||
+ ", allowSamlAuthentication=" + allowSamlAuthentication
|
||||
+ ", allowUserPwdAuthentication=" + allowUserPwdAuthentication
|
||||
+ ", langKey='" + langKey + '\''
|
||||
+ ", createdBy=" + createdBy
|
||||
+ ", createdDate=" + createdDate
|
||||
+ ", lastModifiedBy='" + lastModifiedBy + '\''
|
||||
+ ", lastModifiedDate=" + lastModifiedDate
|
||||
+ ", authorities=" + authorities
|
||||
+ "}";
|
||||
//@formatter:
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
|
||||
|
||||
<!--
|
||||
Alter the entity User.
|
||||
Add flags for allowUserPwdAuth & allowSamlAuth
|
||||
-->
|
||||
<changeSet id="20250604123000-1" author="omg">
|
||||
<!-- User can authenticate with USER+PWD -->
|
||||
<addColumn tableName="jhi_user">
|
||||
<column name="allow_user_pwd_auth" type="boolean" valueBoolean="false"/>
|
||||
</addColumn>
|
||||
|
||||
<!-- User can authenticate with IDP (SAML2) -->
|
||||
<addColumn tableName="jhi_user">
|
||||
<column name="allow_saml_auth" type="boolean" valueBoolean="false"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="20250604123000-2" author="omg">
|
||||
<!-- Update allow_user_pwd_auth to TRUE -->
|
||||
<update tableName="jhi_users">
|
||||
<column name="allow_user_pwd" valueBoolean="true"/>
|
||||
</update>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
|
@ -104,5 +104,6 @@
|
|||
<include file="config/liquibase/changelog/20252104104000_added_entity_ResilientLog.xml" relativeToChangelogFile="false"/>
|
||||
<include file="config/liquibase/changelog/20250502222301_added_entity_DashboardComponentOrganization.xml" relativeToChangelogFile="false"/>
|
||||
<include file="config/liquibase/changelog/20250506120000_altered_entity_ResilientLog.xml" relativeToChangelogFile="false"/>
|
||||
<include file="config/liquibase/changelog/20250604123000_altered_entity_User.xml" relativeToChangelogFile="false"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
|
|
@ -137,6 +137,34 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="form-check-label" for="allowUserPwdAuthentication">
|
||||
<input
|
||||
class="form-check-input"
|
||||
[attr.disabled]="editForm.value.id === undefined ? 'disabled' : null"
|
||||
type="checkbox"
|
||||
id="allowUserPwdAuthentication"
|
||||
name="allowUserPwdAuthentication"
|
||||
formControlName="allowUserPwdAuthentication"
|
||||
/>
|
||||
<span jhiTranslate="userManagement.allowUserPwdAuthentication">Permite autenticação Utilizador+Password</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="form-check-label" for="allowSamlAuthentication">
|
||||
<input
|
||||
class="form-check-input"
|
||||
[attr.disabled]="editForm.value.id === undefined ? 'disabled' : null"
|
||||
type="checkbox"
|
||||
id="allowSamlAuthentication"
|
||||
name="allowSamlAuthentication"
|
||||
formControlName="allowSamlAuthentication"
|
||||
/>
|
||||
<span jhiTranslate="userManagement.allowSamlAuthentication">Permite autenticação SAML2</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-secondary" (click)="previousState()">
|
||||
<fa-icon icon="ban"></fa-icon> <span jhiTranslate="entity.action.cancel">Cancelar</span>
|
||||
</button>
|
||||
|
|
|
@ -52,6 +52,8 @@ export default class UserManagementUpdateComponent implements OnInit {
|
|||
langKey: new FormControl(userTemplate.langKey, { nonNullable: true }),
|
||||
authorities: new FormControl(userTemplate.authorities, { nonNullable: true }),
|
||||
securityGroup: new FormControl(userTemplate.securityGroup, { nonNullable: true }),
|
||||
allowSamlAuthentication: new FormControl(userTemplate.allowSamlAuthentication, { nonNullable: true }),
|
||||
allowUserPwdAuthentication: new FormControl(userTemplate.allowUserPwdAuthentication, { nonNullable: true }),
|
||||
});
|
||||
|
||||
private userService = inject(UserManagementService);
|
||||
|
|
|
@ -14,6 +14,8 @@ export interface IUser {
|
|||
lastModifiedBy?: string;
|
||||
lastModifiedDate?: Date;
|
||||
securityGroup?: ISecurityGroup;
|
||||
allowUserPwdAuthentication?: boolean;
|
||||
allowSamlAuthentication?: boolean;
|
||||
}
|
||||
|
||||
export class User implements IUser {
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
"lastName": "Último nome",
|
||||
"email": "Email",
|
||||
"activated": "Ativo",
|
||||
"allowSamlAuthentication": "Permite autenticação por SAML2 ?",
|
||||
"allowUserPwdAuthentication": "Permite autenticação por Utlizador/Password ?",
|
||||
"deactivated": "Inativo",
|
||||
"profiles": "Perfis",
|
||||
"langKey": "Linguagem",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue