extends the functionality of oauth in Stirling PDF

This commit is contained in:
Ludy87 2024-05-12 19:58:34 +02:00
parent f2b7aeeb1c
commit 811c19e00d
No known key found for this signature in database
GPG key ID: 92696155E0220F94
49 changed files with 724 additions and 210 deletions

View file

@ -3,10 +3,12 @@ package stirling.software.SPDF.config.security;
import java.io.IOException;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
@ -18,9 +20,12 @@ import stirling.software.SPDF.model.User;
@Component
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Autowired private final LoginAttemptService loginAttemptService;
private LoginAttemptService loginAttemptService;
@Autowired private final UserService userService; // Inject the UserService
private UserService userService;
private static final Logger logger =
LoggerFactory.getLogger(CustomAuthenticationFailureHandler.class);
public CustomAuthenticationFailureHandler(
LoginAttemptService loginAttemptService, UserService userService) {
@ -34,22 +39,28 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
String ip = request.getRemoteAddr();
logger.error("Failed login attempt from IP: " + ip);
String username = request.getParameter("username");
if (!isDemoUser(username)) {
if (loginAttemptService.loginAttemptCheck(username)) {
setDefaultFailureUrl("/login?error=locked");
response.sendRedirect("/login?error=locked");
return;
} else {
if (exception.getClass().isAssignableFrom(LockedException.class)) {
setDefaultFailureUrl("/login?error=locked");
response.sendRedirect("/login?error=locked");
return;
} else if (exception instanceof UsernameNotFoundException) {
response.sendRedirect("/login?error=oauth2AuthenticationError");
return;
}
}
}
if (exception.getClass().isAssignableFrom(BadCredentialsException.class)) {
setDefaultFailureUrl("/login?error=badcredentials");
response.sendRedirect("/login?error=badcredentials");
return;
}
super.onAuthenticationFailure(request, response, exception);

View file

@ -2,7 +2,6 @@ package stirling.software.SPDF.config.security;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.SavedRequest;
@ -18,15 +17,10 @@ import stirling.software.SPDF.utils.RequestUriUtils;
public class CustomAuthenticationSuccessHandler
extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired private LoginAttemptService loginAttemptService;
@Override
public void onAuthenticationSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws ServletException, IOException {
String username = request.getParameter("username");
loginAttemptService.loginSucceeded(username);
// Get the saved request
HttpSession session = request.getSession(false);
SavedRequest savedRequest =

View file

@ -2,10 +2,9 @@ package stirling.software.SPDF.config.security;
import java.io.IOException;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import jakarta.servlet.ServletException;
@ -14,10 +13,8 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Autowired SessionRegistry sessionRegistry;
@Override
public void onLogoutSuccess(
@ -26,14 +23,9 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
HttpSession session = request.getSession(false);
if (session != null) {
String sessionId = session.getId();
sessionRegistry().removeSessionInformation(sessionId);
sessionRegistry.removeSessionInformation(sessionId);
}
if (request.getParameter("oauth2AutoCreateDisabled") != null) {
response.sendRedirect(
request.getContextPath() + "/login?error=oauth2AutoCreateDisabled");
} else {
response.sendRedirect(request.getContextPath() + "/login?logout=true");
}
}
}

View file

@ -22,7 +22,11 @@ public class CustomUserDetailsService implements UserDetailsService {
@Autowired private UserRepository userRepository;
@Autowired private LoginAttemptService loginAttemptService;
private LoginAttemptService loginAttemptService;
CustomUserDetailsService(LoginAttemptService loginAttemptService) {
this.loginAttemptService = loginAttemptService;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
@ -39,6 +43,10 @@ public class CustomUserDetailsService implements UserDetailsService {
"Your account has been locked due to too many failed login attempts.");
}
if (user.getPassword() == null || user.getPassword().isEmpty()) {
throw new UsernameNotFoundException("Password must not be null");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),

View file

@ -7,6 +7,8 @@ import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -21,6 +23,8 @@ public class InitialSecuritySetup {
@Autowired ApplicationProperties applicationProperties;
private static final Logger logger = LoggerFactory.getLogger(InitialSecuritySetup.class);
@PostConstruct
public void init() {
if (!userService.hasUsers()) {
@ -29,6 +33,20 @@ public class InitialSecuritySetup {
applicationProperties.getSecurity().getInitialLogin().getUsername();
String initialPassword =
applicationProperties.getSecurity().getInitialLogin().getPassword();
try {
// https://github.com/Stirling-Tools/Stirling-PDF/issues/976
userService.isUsernameValidWithReturn(initialUsername);
} catch (IllegalArgumentException e) {
Path pathToFile = Paths.get("configs/settings.yml");
try {
if (Files.exists(pathToFile)) {
Files.delete(pathToFile);
}
} catch (IOException ex) {
logger.info(ex.getMessage());
}
throw e;
}
if (initialUsername != null && initialPassword != null) {
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
} else {

View file

@ -30,12 +30,13 @@ public class LoginAttemptService {
new ConcurrentHashMap<>();
public void loginSucceeded(String key) {
attemptsCache.remove(key);
attemptsCache.remove(key.toLowerCase());
}
public boolean loginAttemptCheck(String key) {
attemptsCache.compute(
key,
return attemptsCache
.compute(
key.toLowerCase(),
(k, attemptCounter) -> {
if (attemptCounter == null
|| attemptCounter.shouldReset(ATTEMPT_INCREMENT_TIME)) {
@ -44,14 +45,16 @@ public class LoginAttemptService {
attemptCounter.increment();
return attemptCounter;
}
});
return attemptsCache.get(key).getAttemptCount() >= MAX_ATTEMPTS;
})
.getAttemptCount()
>= MAX_ATTEMPTS;
}
public boolean isBlocked(String key) {
AttemptCounter attemptCounter = attemptsCache.get(key);
AttemptCounter attemptCounter = attemptsCache.get(key.toLowerCase());
if (attemptCounter != null) {
return attemptCounter.getAttemptCount() >= MAX_ATTEMPTS;
return attemptCounter.getAttemptCount() >= MAX_ATTEMPTS
&& !attemptCounter.shouldReset(ATTEMPT_INCREMENT_TIME);
}
return false;
}

View file

@ -1,6 +1,5 @@
package stirling.software.SPDF.config.security;
import java.io.IOException;
import java.util.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -14,33 +13,30 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.savedrequest.NullRequestCache;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
@ -49,7 +45,7 @@ import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
@EnableMethodSecurity
public class SecurityConfiguration {
@Autowired private UserDetailsService userDetailsService;
@Autowired private CustomUserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
@ -111,18 +107,7 @@ public class SecurityConfiguration {
new AntPathRequestMatcher("/logout"))
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
.invalidateHttpSession(true) // Invalidate session
.deleteCookies("JSESSIONID", "remember-me")
.addLogoutHandler(
(request, response, authentication) -> {
HttpSession session =
request.getSession(false);
if (session != null) {
String sessionId = session.getId();
sessionRegistry()
.removeSessionInformation(
sessionId);
}
}))
.deleteCookies("JSESSIONID", "remember-me"))
.rememberMe(
rememberMeConfigurer ->
rememberMeConfigurer // Use the configurator directly
@ -176,35 +161,25 @@ public class SecurityConfiguration {
is set as true, else login fails with an error message advising the same.
*/
.successHandler(
new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws ServletException, IOException {
OAuth2User oauthUser =
(OAuth2User)
authentication
.getPrincipal();
if (userService.processOAuth2PostLogin(
oauthUser.getAttribute("email"),
applicationProperties
.getSecurity()
.getOAUTH2()
.getAutoCreateUser())) {
response.sendRedirect("/");
} else {
response.sendRedirect(
"/logout?oauth2AutoCreateDisabled=true");
}
}
})
new CustomOAuth2AuthenticationSuccessHandler(
applicationProperties, userService))
.failureHandler(
new CustomOAuth2AuthenticationFailureHandler())
// Add existing Authorities from the database
.userInfoEndpoint(
userInfoEndpoint ->
userInfoEndpoint.userAuthoritiesMapper(
userAuthoritiesMapper())));
userInfoEndpoint
.oidcUserService(
new CustomOAuth2UserService(
applicationProperties))
.userAuthoritiesMapper(
userAuthoritiesMapper())))
.userDetailsService(userDetailsService)
.logout(
logout ->
logout.logoutSuccessHandler(
new CustomOAuth2LogoutSuccessHandler(
this.applicationProperties)));
}
} else {
http.csrf(csrf -> csrf.disable())
@ -225,13 +200,13 @@ public class SecurityConfiguration {
}
private ClientRegistration oidcClientRegistration() {
return ClientRegistrations.fromOidcIssuerLocation(
applicationProperties.getSecurity().getOAUTH2().getIssuer())
OAUTH2 oauth = applicationProperties.getSecurity().getOAUTH2();
return ClientRegistrations.fromIssuerLocation(oauth.getIssuer())
.registrationId("oidc")
.clientId(applicationProperties.getSecurity().getOAUTH2().getClientId())
.clientSecret(applicationProperties.getSecurity().getOAUTH2().getClientSecret())
.scope("openid", "profile", "email")
.userNameAttributeName("email")
.clientId(oauth.getClientId())
.clientSecret(oauth.getClientSecret())
.scope(oauth.getScopes())
.userNameAttributeName(oauth.getUseAsUsername())
.clientName("OIDC")
.build();
}
@ -256,9 +231,14 @@ public class SecurityConfiguration {
// Add Authorities from database for existing user, if user is present.
if (authority instanceof OAuth2UserAuthority oauth2Auth) {
String useAsUsername =
applicationProperties
.getSecurity()
.getOAUTH2()
.getUseAsUsername();
Optional<User> userOpt =
userService.findByUsernameIgnoreCase(
(String) oauth2Auth.getAttributes().get("email"));
(String) oauth2Auth.getAttributes().get(useAsUsername));
if (userOpt.isPresent()) {
User user = userOpt.get();
if (user != null) {

View file

@ -8,6 +8,8 @@ import java.util.UUID;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
@ -18,6 +20,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User;
@ -33,19 +36,19 @@ public class UserService implements UserServiceInterface {
@Autowired private PasswordEncoder passwordEncoder;
@Autowired private MessageSource messageSource;
// Handle OAUTH2 login and user auto creation.
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser) {
if (!isUsernameValidWithReturn(username).equals(username)) {
return false;
}
Optional<User> existUser = userRepository.findByUsernameIgnoreCase(username);
if (existUser.isPresent()) {
return true;
}
if (autoCreateUser) {
User user = new User();
user.setUsername(username);
user.setEnabled(true);
user.setFirstLogin(false);
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
userRepository.save(user);
saveUser(username, AuthenticationType.OAUTH2);
return true;
}
return false;
@ -128,30 +131,46 @@ public class UserService implements UserServiceInterface {
return userOpt.isPresent() && userOpt.get().getApiKey().equals(apiKey);
}
public void saveUser(String username, String password) {
public void saveUser(String username, AuthenticationType authenticationType)
throws IllegalArgumentException {
User user = new User();
user.setUsername(username);
user.setPassword(passwordEncoder.encode(password));
user.setUsername(isUsernameValidWithReturn(username));
user.setEnabled(true);
user.setFirstLogin(false);
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
user.setAuthenticationType(authenticationType);
userRepository.save(user);
}
public void saveUser(String username, String password, String role, boolean firstLogin) {
public void saveUser(String username, String password) throws IllegalArgumentException {
User user = new User();
user.setUsername(username);
user.setUsername(isUsernameValidWithReturn(username));
user.setPassword(passwordEncoder.encode(password));
user.setEnabled(true);
user.setAuthenticationType(AuthenticationType.WEB);
userRepository.save(user);
}
public void saveUser(String username, String password, String role, boolean firstLogin)
throws IllegalArgumentException {
User user = new User();
user.setUsername(isUsernameValidWithReturn(username));
user.setPassword(passwordEncoder.encode(password));
user.addAuthority(new Authority(role, user));
user.setEnabled(true);
user.setAuthenticationType(AuthenticationType.WEB);
user.setFirstLogin(firstLogin);
userRepository.save(user);
}
public void saveUser(String username, String password, String role) {
public void saveUser(String username, String password, String role)
throws IllegalArgumentException {
User user = new User();
user.setUsername(username);
user.setUsername(isUsernameValidWithReturn(username));
user.setPassword(passwordEncoder.encode(password));
user.addAuthority(new Authority(role, user));
user.setEnabled(true);
user.setAuthenticationType(AuthenticationType.WEB);
user.setFirstLogin(false);
userRepository.save(user);
}
@ -209,8 +228,8 @@ public class UserService implements UserServiceInterface {
return authorityRepository.findByUserId(user.getId());
}
public void changeUsername(User user, String newUsername) {
user.setUsername(newUsername);
public void changeUsername(User user, String newUsername) throws IllegalArgumentException {
user.setUsername(isUsernameValidWithReturn(newUsername));
userRepository.save(user);
}
@ -235,6 +254,40 @@ public class UserService implements UserServiceInterface {
}
public boolean isUsernameValid(String username) {
return username.matches("[a-zA-Z0-9]+");
// Checks whether the simple username is formatted correctly
boolean isValidSimpleUsername =
username.matches("^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$");
// Checks whether the email address is formatted correctly
boolean isValidEmail =
username.matches(
"^(?=.{1,64}@)[A-Za-z0-9]+(\\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$");
return isValidSimpleUsername || isValidEmail;
}
public String isUsernameValidWithReturn(String username) throws IllegalArgumentException {
if (!isUsernameValid(username)) {
String message =
messageSource.getMessage(
"invalidUsernameMessage", null, LocaleContextHolder.getLocale());
throw new IllegalArgumentException(message);
}
return username;
}
public boolean hasPassword(String username) {
Optional<User> user = userRepository.findByUsernameIgnoreCase(username);
if (user.isPresent() && user.get().hasPassword()) {
return true;
}
return false;
}
public boolean isAuthenticationTypeByUsername(
String username, AuthenticationType authenticationType) {
Optional<User> user = userRepository.findByUsernameIgnoreCase(username);
if (user.isPresent() && user.get().getAuthenticationType() != null) {
return user.get().getAuthenticationType().equalsIgnoreCase(authenticationType.name());
}
return false;
}
}

View file

@ -0,0 +1,40 @@
package stirling.software.SPDF.config.security.oauth2;
import java.io.IOException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class CustomOAuth2AuthenticationFailureHandler
extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
if (exception instanceof OAuth2AuthenticationException) {
OAuth2Error error = ((OAuth2AuthenticationException) exception).getError();
getRedirectStrategy()
.sendRedirect(request, response, "/login?error=oAuth::" + error.getErrorCode());
} else if (exception instanceof LockedException) {
getRedirectStrategy().sendRedirect(request, response, "/login?error=locked");
} else if (exception instanceof UsernameNotFoundException) {
getRedirectStrategy()
.sendRedirect(request, response, "/login?error=oauth2AuthenticationError");
} else {
super.onAuthenticationFailure(request, response, exception);
}
}
}

View file

@ -0,0 +1,74 @@
package stirling.software.SPDF.config.security.oauth2;
import java.io.IOException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.utils.RequestUriUtils;
@Component
public class CustomOAuth2AuthenticationSuccessHandler
extends SavedRequestAwareAuthenticationSuccessHandler {
ApplicationProperties applicationProperties;
UserService userService;
public CustomOAuth2AuthenticationSuccessHandler(
ApplicationProperties applicationProperties, UserService userService) {
this.applicationProperties = applicationProperties;
this.userService = userService;
}
@Override
public void onAuthenticationSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws ServletException, IOException {
OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
// Get the saved request
HttpSession session = request.getSession(false);
SavedRequest savedRequest =
session != null
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
: null;
if (savedRequest != null
&& !RequestUriUtils.isStaticResource(savedRequest.getRedirectUrl())) {
// Redirect to the original destination
super.onAuthenticationSuccess(request, response, authentication);
} else {
OAUTH2 oAuth = applicationProperties.getSecurity().getOAUTH2();
String username = oauthUser.getAttribute(oAuth.getUseAsUsername());
if (userService.usernameExistsIgnoreCase(username)
&& userService.hasPassword(username)
&& !userService.isAuthenticationTypeByUsername(
username, AuthenticationType.OAUTH2)
&& oAuth.getAutoCreateUser()) {
response.sendRedirect(
request.getContextPath() + "/logout?oauth2AuthenticationError=true");
return;
} else {
try {
userService.processOAuth2PostLogin(username, oAuth.getAutoCreateUser());
response.sendRedirect("/");
return;
} catch (IllegalArgumentException e) {
response.sendRedirect("/logout?invalidUsername=true");
return;
}
}
}
}
}

View file

@ -0,0 +1,87 @@
package stirling.software.SPDF.config.security.oauth2;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
@Component
public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Autowired SessionRegistry sessionRegistry;
private ApplicationProperties applicationProperties;
public CustomOAuth2LogoutSuccessHandler(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
@Override
public void onLogoutSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
boolean isOAuthUser = true;
String param = "logout=true";
if (authentication == null) {
response.sendRedirect("/");
return;
}
Object pri = authentication.getPrincipal();
if (pri instanceof UserDetails) {
UserDetails userDetails = (UserDetails) pri;
isOAuthUser = userDetails.getPassword() == null;
} else if (pri instanceof OAuth2User) {
isOAuthUser = true;
}
OAUTH2 oauth = applicationProperties.getSecurity().getOAUTH2();
String provider = oauth.getProvider() != null && isOAuthUser ? oauth.getProvider() : "";
if (request.getParameter("oauth2AuthenticationError") != null) {
param = "error=oauth2AuthenticationError";
} else if (request.getParameter("invalidUsername") != null) {
param = "error=invalidUsername";
}
HttpSession session = request.getSession(false);
if (session != null) {
String sessionId = session.getId();
sessionRegistry.removeSessionInformation(sessionId);
}
switch (provider) {
case "keycloak":
String logoutUrl =
oauth.getIssuer()
+ "/protocol/openid-connect/logout"
+ "?client_id="
+ oauth.getClientId()
+ "&post_logout_redirect_uri="
+ response.encodeRedirectURL(
"http://" + request.getHeader("host") + "/login?" + param);
response.sendRedirect(logoutUrl);
break;
case "google":
default:
if (request.getParameter("oauth2AutoCreateDisabled") != null) {
response.sendRedirect(
request.getContextPath() + "/login?error=oauth2AutoCreateDisabled");
} else {
response.sendRedirect(request.getContextPath() + "/login?logout=true");
}
break;
}
}
}

View file

@ -0,0 +1,52 @@
package stirling.software.SPDF.config.security.oauth2;
import java.util.HashMap;
import java.util.Map;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import stirling.software.SPDF.model.ApplicationProperties;
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
private final OidcUserService delegate = new OidcUserService();
private ApplicationProperties applicationProperties;
public CustomOAuth2UserService(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
String usernameAttribute =
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername();
try {
OidcUser user = delegate.loadUser(userRequest);
Map<String, Object> attributes = new HashMap<>(user.getAttributes());
// Ensure the preferred username attribute is present
if (!attributes.containsKey(usernameAttribute)) {
attributes.put(usernameAttribute, attributes.getOrDefault("email", ""));
usernameAttribute = "email";
}
// Return a new OidcUser with adjusted attributes
return new DefaultOidcUser(
user.getAuthorities(),
userRequest.getIdToken(),
user.getUserInfo(),
usernameAttribute);
} catch (java.lang.IllegalArgumentException e) {
throw new OAuth2AuthenticationException(
new OAuth2Error(e.getMessage()), e.getMessage(), e);
}
}
}

View file

@ -0,0 +1,57 @@
package stirling.software.SPDF.config.security.oauth2;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import stirling.software.SPDF.model.ApplicationProperties;
public class CustomOAuthUserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
private static final Logger logger = LoggerFactory.getLogger(CustomOAuthUserService.class);
private final OidcUserService delegate = new OidcUserService();
private ApplicationProperties applicationProperties;
public CustomOAuthUserService(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
String usernameAttribute =
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername();
try {
OidcUser user = delegate.loadUser(userRequest);
Map<String, Object> attributes = new HashMap<>(user.getAttributes());
// Ensure the preferred username attribute is present
if (!attributes.containsKey(usernameAttribute)) {
attributes.put(usernameAttribute, attributes.getOrDefault("email", ""));
usernameAttribute = "email";
logger.info("Adjusted username attribute to use email");
}
// Return a new OidcUser with adjusted attributes
return new DefaultOidcUser(
user.getAuthorities(),
userRequest.getIdToken(),
user.getUserInfo(),
usernameAttribute);
} catch (java.lang.IllegalArgumentException e) {
throw new OAuth2AuthenticationException(
new OAuth2Error(e.getMessage()), e.getMessage(), e);
}
}
}

View file

@ -47,8 +47,11 @@ public class UserController {
model.addAttribute("error", "Username already exists");
return "register";
}
try {
userService.saveUser(requestModel.getUsername(), requestModel.getPassword());
} catch (IllegalArgumentException e) {
return "redirect:/login?messageType=invalidUsername";
}
return "redirect:/login?registered=true";
}
@ -92,7 +95,11 @@ public class UserController {
}
if (newUsername != null && newUsername.length() > 0) {
try {
userService.changeUsername(user, newUsername);
} catch (IllegalArgumentException e) {
return new RedirectView("/account?messageType=invalidUsername");
}
}
// Logout using Spring's utility

View file

@ -109,8 +109,9 @@ public class AccountWebController {
OAuth2User userDetails = (OAuth2User) principal;
// Retrieve username and other attributes
username = userDetails.getAttribute("email");
username =
userDetails.getAttribute(
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername());
// Add oAuth2 Login attributes to the model
model.addAttribute("oAuth2Login", true);
}

View file

@ -1,6 +1,10 @@
package stirling.software.SPDF.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@ -221,6 +225,10 @@ public class ApplicationProperties {
private String clientId;
private String clientSecret;
private boolean autoCreateUser;
private String useAsUsername;
private String provider;
private Collection<String> scopes = new ArrayList<String>();
public boolean getEnabled() {
return enabled;
@ -262,6 +270,37 @@ public class ApplicationProperties {
this.autoCreateUser = autoCreateUser;
}
public String getUseAsUsername() {
if (useAsUsername != null && useAsUsername.trim().length() > 0) {
return useAsUsername;
}
return "email";
}
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
public String getProvider() {
return provider;
}
public void setProvider(String provider) {
this.provider = provider;
}
public Collection<String> getScopes() {
return scopes;
}
public void setScopes(String scpoes) {
List<String> scopesList =
Arrays.stream(scpoes.split(","))
.map(String::trim)
.collect(Collectors.toList());
this.scopes.addAll(scopesList);
}
@Override
public String toString() {
return "OAUTH2 [enabled="
@ -274,6 +313,12 @@ public class ApplicationProperties {
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", autoCreateUser="
+ autoCreateUser
+ ", useAsUsername="
+ useAsUsername
+ ", provider"
+ provider
+ ", scopes="
+ scopes
+ "]";
}
}

View file

@ -0,0 +1,6 @@
package stirling.software.SPDF.model;
public enum AuthenticationType {
WEB,
OAUTH2
}

View file

@ -47,6 +47,9 @@ public class User {
@Column(name = "roleName")
private String roleName;
@Column(name = "authenticationtype")
private String authenticationType;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user")
private Set<Authority> authorities = new HashSet<>();
@ -116,6 +119,14 @@ public class User {
this.enabled = enabled;
}
public void setAuthenticationType(AuthenticationType authenticationType) {
this.authenticationType = authenticationType.toString().toLowerCase();
}
public String getAuthenticationType() {
return authenticationType;
}
public Set<Authority> getAuthorities() {
return authorities;
}
@ -137,4 +148,8 @@ public class User {
.map(Authority::getAuthority)
.collect(Collectors.joining(", "));
}
public boolean hasPassword() {
return this.getPassword() != "" ? true : false;
}
}

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=لا يمكن خفض دور المستخدم الحالي
downgradeCurrentUserLongMessage=لا يمكن تخفيض دور المستخدم الحالي. وبالتالي، لن يظهر المستخدم الحالي.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=تغيير دور المستخدم
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Потребителят не е автентикира
userNotFoundMessage=Потребителят не е намерен
incorrectPasswordMessage=Текущата парола е неправилна.
usernameExistsMessage=Новият потребител вече съществува.
invalidUsernameMessage=Невалидно потребителско име, потребителското име трябва да съдържа само букви и цифри.
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Грешка
oops=Опаа!
help=Помощ
@ -164,7 +165,7 @@ adminUserSettings.header=Настройки за администраторск
adminUserSettings.admin=Администратор
adminUserSettings.user=Потребител
adminUserSettings.addUser=Добавяне на нов потребител
adminUserSettings.usernameInfo=Потребителското име трябва да съдържа само букви и цифри, без интервали или специални знаци.
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
adminUserSettings.roles=Роли
adminUserSettings.role=Роля
adminUserSettings.actions=Действия
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Вътрешен API потребител
adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане
adminUserSettings.submit=Съхранете потребителя
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=No es pot reduir la funció de l'usuari actual
downgradeCurrentUserLongMessage=No es pot baixar la funció de l'usuari actual. Per tant, no es mostrarà l'usuari actual.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Usuari Admin Opcions Control
adminUserSettings.admin=Admin
adminUserSettings.user=Usuari
adminUserSettings.addUser=Afegir Usuari
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rols
adminUserSettings.role=Rol
adminUserSettings.actions=Accions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Desar Usuari
adminUserSettings.changeUserRole=Canvia el rol de l'usuari
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Benutzer nicht authentifiziert.
userNotFoundMessage=Benutzer nicht gefunden.
incorrectPasswordMessage=Das Passwort ist falsch.
usernameExistsMessage=Neuer Benutzername existiert bereits.
invalidUsernameMessage=Ungültiger Benutzername. Der Benutzername darf nur Buchstaben und Zahlen enthalten.
invalidUsernameMessage=Ungültiger Benutzername. Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
deleteCurrentUserMessage=Der aktuell angemeldete Benutzer kann nicht gelöscht werden.
deleteUsernameExistsMessage=Der Benutzername existiert nicht und kann nicht gelöscht werden.
downgradeCurrentUserMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden
downgradeCurrentUserLongMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden. Daher wird der aktuelle Benutzer nicht angezeigt.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Fehler
oops=Hoppla!
help=Hilfe
@ -164,7 +165,7 @@ adminUserSettings.header=Administrator-Benutzerkontrolle
adminUserSettings.admin=Administrator
adminUserSettings.user=Benutzer
adminUserSettings.addUser=Neuen Benutzer hinzufügen
adminUserSettings.usernameInfo=Der Benutzername darf nur Buchstaben und Zahlen enthalten, keine Leerzeichen oder Sonderzeichen.
adminUserSettings.usernameInfo=Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
adminUserSettings.roles=Rollen
adminUserSettings.role=Rolle
adminUserSettings.actions=Aktion
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Interner API-Benutzer
adminUserSettings.forceChange=Benutzer dazu zwingen, Benutzernamen/Passwort bei der Anmeldung zu ändern
adminUserSettings.submit=Benutzer speichern
adminUserSettings.changeUserRole=Benutzerrolle ändern
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Ο χρήστης δεν έχει αυθεντικοπο
userNotFoundMessage=Ο χρήστης δεν βρέθηκε.
incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος.
usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη.
invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, το όνομα χρήστη πρέπει να περιέχει μόνο αλφαβητικούς χαρακτήρες και αριθμούς.
invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, όνομα χρήστη μπορεί να περιέχει μόνο γράμματα, αριθμούς και τους ακόλουθους ειδικούς χαρακτήρες @._+- ή πρέπει να είναι έγκυρη διεύθυνση email.
deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη.
deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί.
downgradeCurrentUserMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη
downgradeCurrentUserLongMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη. Ως εκ τούτου, ο τρέχων χρήστης δεν θα εμφανίζεται.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Σφάλμα
oops=Ωχ!
help=Βοήθεια
@ -164,7 +165,7 @@ adminUserSettings.header=Ρυθμίσεις ελέγχου Διαχειριστ
adminUserSettings.admin=Διαχειριστής
adminUserSettings.user=Χρήστης
adminUserSettings.addUser=Προσθήκη νέου Χρήστη
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Ρόλοι
adminUserSettings.role=Ρόλος
adminUserSettings.actions=Ενέργειες
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Εσωτερικός API χρήστης
adminUserSettings.forceChange=Αναγκάστε τον χρήστη να αλλάξει το όνομα χρήστη/κωδικό πρόσβασης κατά τη σύνδεση
adminUserSettings.submit=Αποθήκευση Χρήστη
adminUserSettings.changeUserRole=Αλλαγή ρόλου χρήστη
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role
downgradeCurrentUserLongMessage=Cannot downgrade current user's role. Hence, current user will not be shown.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Change User's Role
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role
downgradeCurrentUserLongMessage=Cannot downgrade current user's role. Hence, current user will not be shown.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Change User's Role
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Usuario no autentificado.
userNotFoundMessage=Usuario no encontrado.
incorrectPasswordMessage=La contraseña actual no es correcta.
usernameExistsMessage=El nuevo nombre de usuario está en uso.
invalidUsernameMessage=Nombre de usuario no válido, El nombre de ususario debe contener únicamente números y caracteres alfabéticos.
invalidUsernameMessage=Nombre de usuario no válido, el nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
deleteCurrentUserMessage=No puede eliminar el usuario que tiene la sesión actualmente en uso.
deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse.
downgradeCurrentUserMessage=No se puede degradar el rol del usuario actual
downgradeCurrentUserLongMessage=No se puede degradar el rol del usuario actual. Por lo tanto, el usuario actual no se mostrará.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Ups!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Configuración de control de usuario administrador
adminUserSettings.admin=Administrador
adminUserSettings.user=Usuario
adminUserSettings.addUser=Añadir Nuevo Usuario
adminUserSettings.usernameInfo=El nombrede usuario debe contener únicamente letras y números, no espacios ni caracteres especiales.
adminUserSettings.usernameInfo=El nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
adminUserSettings.roles=Roles
adminUserSettings.role=Rol
adminUserSettings.actions=Acciones
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Usuario interno de API
adminUserSettings.forceChange=Forzar usuario a cambiar usuario/contraseña en el acceso
adminUserSettings.submit=Guardar Usuario
adminUserSettings.changeUserRole=Cambiar rol de usuario
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Ezin da uneko erabiltzailearen rola jaitsi
downgradeCurrentUserLongMessage=Ezin da uneko erabiltzailearen rola jaitsi. Beraz, oraingo erabiltzailea ez da erakutsiko.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin Erabiltzailearen Ezarpenen Kontrolak
adminUserSettings.admin=Admin
adminUserSettings.user=Erabiltzaile
adminUserSettings.addUser=Erabiltzaile berria
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rolak
adminUserSettings.role=Rol
adminUserSettings.actions=Ekintzak
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Gorde Erabiltzailea
adminUserSettings.changeUserRole=Erabiltzailearen rola aldatu
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Utilisateur non authentifié.
userNotFoundMessage=Utilisateur non trouvé.
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
usernameExistsMessage=Le nouveau nom dutilisateur existe déjà.
invalidUsernameMessage=Nom dutilisateur invalide, le nom dutilisateur ne peut contenir que des chiffres et des lettres.
invalidUsernameMessage=Nom dutilisateur invalide, le nom dutilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
deleteCurrentUserMessage=Impossible de supprimer lutilisateur actuellement connecté.
deleteUsernameExistsMessage=Le nom dutilisateur nexiste pas et ne peut pas être supprimé.
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel
downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Erreur
oops=Oups !
help=Aide
@ -164,7 +165,7 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
adminUserSettings.admin=Administateur
adminUserSettings.user=Utilisateur
adminUserSettings.addUser=Ajouter un utilisateur
adminUserSettings.usernameInfo=Le nom dutilisateur ne doit contenir que des lettres et des chiffres, sans espaces ni caractères spéciaux.
adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
adminUserSettings.roles=Rôles
adminUserSettings.role=Rôle
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Forcer lutilisateur à changer son nom dutilisateur/mot de passe lors de la connexion
adminUserSettings.submit=Ajouter
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=उपयोगकर्ता प्रमाणित
userNotFoundMessage=उपयोगकर्ता नहीं मिला।
incorrectPasswordMessage=वर्तमान पासवर्ड गलत है।
usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है।
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता
downgradeCurrentUserLongMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता। इसलिए, वर्तमान उपयोगकर्ता को नहीं दिखाया जाएगा।
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=व्यवस्थापक उपयोगकर्
adminUserSettings.admin=व्यवस्थापक
adminUserSettings.user=उपयोगकर्ता
adminUserSettings.addUser=नया उपयोगकर्ता जोड़ें
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=रोल्स
adminUserSettings.role=रोल
adminUserSettings.actions=क्रियाएँ
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=उपयोगकर्ता को लॉगिन पर उपयोगकर्ता नाम/पासवर्ड बदलने के लिए मजबूर करें
adminUserSettings.submit=उपयोगकर्ता को सहेजें
adminUserSettings.changeUserRole=यूज़र की भूमिका बदलें
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Felhasználó nincs hitelesítve.
userNotFoundMessage=A felhasználó nem található.
incorrectPasswordMessage=A jelenlegi jelszó helytelen.
usernameExistsMessage=Az új felhasználónév már létezik.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=A jelenlegi felhasználó szerepkörét nem lehet visszaminősíteni
downgradeCurrentUserLongMessage=Az aktuális felhasználó szerepkörét nem lehet visszaminősíteni. Ezért az aktuális felhasználó nem jelenik meg.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Adminisztrátori Felhasználói Vezérlési Beállítá
adminUserSettings.admin=Adminisztrátor
adminUserSettings.user=Felhasználó
adminUserSettings.addUser=Új felhasználó hozzáadása
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Szerepek
adminUserSettings.role=Szerep
adminUserSettings.actions=Műveletek
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Kényszerítse a felhasználót a felhasználónév/jelszó megváltoztatására bejelentkezéskor
adminUserSettings.submit=Felhasználó mentése
adminUserSettings.changeUserRole=Felhasználó szerepkörének módosítása
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
userNotFoundMessage=Pengguna tidak ditemukan.
incorrectPasswordMessage=Kata sandi saat ini salah.
usernameExistsMessage=Nama pengguna baru sudah ada.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
downgradeCurrentUserLongMessage=Tidak dapat menurunkan peran pengguna saat ini. Oleh karena itu, pengguna saat ini tidak akan ditampilkan.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Pengaturan Kontrol Admin
adminUserSettings.admin=Admin
adminUserSettings.user=Pengguna
adminUserSettings.addUser=Tambahkan Pengguna Baru
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Peran
adminUserSettings.role=Peran
adminUserSettings.actions=Tindakan
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk
adminUserSettings.submit=Simpan Pengguna
adminUserSettings.changeUserRole=Ubah Peran Pengguna
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Utente non autenticato.
userNotFoundMessage=Utente non trovato.
incorrectPasswordMessage=La password attuale non è corretta.
usernameExistsMessage=Il nuovo nome utente esiste già.
invalidUsernameMessage=Nome utente non valido, il nome utente deve contenere solo caratteri alfabetici e numeri.
invalidUsernameMessage=Nome utente non valido, il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- o deve essere un indirizzo email valido.
deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
downgradeCurrentUserMessage=Impossibile declassare il ruolo dell'utente corrente
downgradeCurrentUserLongMessage=Impossibile declassare il ruolo dell'utente corrente. Pertanto, l'utente corrente non verrà visualizzato.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Errore
oops=Oops!
help=Aiuto
@ -164,7 +165,7 @@ adminUserSettings.header=Impostazioni di controllo utente amministratore
adminUserSettings.admin=Amministratore
adminUserSettings.user=Utente
adminUserSettings.addUser=Aggiungi un nuovo Utente
adminUserSettings.usernameInfo=Il nome utente deve contenere solo lettere e numeri, senza spazi o caratteri speciali.
adminUserSettings.usernameInfo=Il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- oppure deve essere un indirizzo email valido.
adminUserSettings.roles=Ruoli
adminUserSettings.role=Ruolo
adminUserSettings.actions=Azioni
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=API utente interna
adminUserSettings.forceChange=Forza l'utente a cambiare nome username/password all'accesso
adminUserSettings.submit=Salva utente
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=ユーザーが認証されていません。
userNotFoundMessage=ユーザーが見つかりません。
incorrectPasswordMessage=現在のパスワードが正しくありません。
usernameExistsMessage=新しいユーザー名はすでに存在します。
invalidUsernameMessage=ユーザー名が無効です。ユーザー名にはアルファベットと数字のみを使用してください
invalidUsernameMessage=ユーザー名が無効です。ユーザー名には文字、数字、およびそれに続く特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります
deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。
deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。
downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません
downgradeCurrentUserLongMessage=現在のユーザーの役割をダウングレードできません。したがって、現在のユーザーは表示されません。
userAlreadyExistsMessage=OAuth2: User already exists.
error=エラー
oops=おっと!
help=ヘルプ
@ -164,7 +165,7 @@ adminUserSettings.header=管理者ユーザー制御設定
adminUserSettings.admin=管理者
adminUserSettings.user=ユーザー
adminUserSettings.addUser=新しいユーザを追加
adminUserSettings.usernameInfo=ユーザー名には文字と数字のみが使用でき、スペースや特殊文字は使用できません
adminUserSettings.usernameInfo=ユーザー名には、文字、数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります
adminUserSettings.roles=役割
adminUserSettings.role=役割
adminUserSettings.actions=アクション
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=内部APIユーザー
adminUserSettings.forceChange=ログイン時にユーザー名/パスワードを強制的に変更する
adminUserSettings.submit=ユーザーの保存
adminUserSettings.changeUserRole=ユーザーの役割を変更する
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=사용자가 인증되지 않았습니다.
userNotFoundMessage=사용자를 찾을 수 없습니다.
incorrectPasswordMessage=현재 비밀번호가 틀립니다.
usernameExistsMessage=새 사용자명이 이미 존재합니다.
invalidUsernameMessage=사용자 이름이 잘못되었습니다. 사용자 이름에는 알파벳 문자와 숫자만 포함되어야 합니다.
invalidUsernameMessage=잘못된 사용자 이름입니다. 사용자 이름에는 문자, 숫자 및 다음 특수 문자(@._+-)만 포함할 수 있거나 유효한 이메일 주소여야 합니다.
deleteCurrentUserMessage=현재 로그인한 사용자를 삭제할 수 없습니다.
deleteUsernameExistsMessage=사용자 이름이 존재하지 않으며 삭제할 수 없습니다.
downgradeCurrentUserMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다
downgradeCurrentUserLongMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다. 따라서 현재 사용자는 표시되지 않습니다.
userAlreadyExistsMessage=OAuth2: User already exists.
error=오류
oops=어머나!
help=도움말
@ -164,7 +165,7 @@ adminUserSettings.header=사용자 관리
adminUserSettings.admin=관리자
adminUserSettings.user=사용자
adminUserSettings.addUser=새 사용자 추가
adminUserSettings.usernameInfo=사용자 이름은 문자와 숫자만 포함해야 하며 공백이나 특수 문자는 포함할 수 없습니다.
adminUserSettings.usernameInfo=사용자 이름은 문자, 숫자, 특수 문자 @._+-만 포함할 수 있으며 유효한 이메일 주소여야 합니다.
adminUserSettings.roles=역할
adminUserSettings.role=역할
adminUserSettings.actions=동작
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=내부 API 사용자
adminUserSettings.forceChange=다음 로그인 때 사용자명과 비밀번호를 변경하도록 강제
adminUserSettings.submit=사용자 저장
adminUserSettings.changeUserRole=사용자의 역할 변경
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Gebruiker niet ingelogd.
userNotFoundMessage=Gebruiker niet gevonden.
incorrectPasswordMessage=Huidige wachtwoord is onjuist.
usernameExistsMessage=Nieuwe gebruikersnaam bestaat al.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden
downgradeCurrentUserLongMessage=Kan de rol van de huidige gebruiker niet downgraden. Huidige gebruiker wordt dus niet weergegeven.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Beheer gebruikers
adminUserSettings.admin=Beheerder
adminUserSettings.user=Gebruiker
adminUserSettings.addUser=Voeg nieuwe gebruiker toe
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rollen
adminUserSettings.role=Rol
adminUserSettings.actions=Acties
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Forceer gebruiker om gebruikersnaam/wachtwoord te wijzigen bij inloggen
adminUserSettings.submit=Gebruiker opslaan
adminUserSettings.changeUserRole=De rol van de gebruiker wijzigen
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
downgradeCurrentUserLongMessage=Nie można obniżyć roli bieżącego użytkownika. W związku z tym bieżący użytkownik nie zostanie wyświetlony.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Zmień rolę użytkownika
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário atual
downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do usuário atual. Portanto, o usuário atual não será mostrado.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Alterar Função de Usuário
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Utilizador não autenticado.
userNotFoundMessage=Utilizador inexistente.
incorrectPasswordMessage=Senha incorreta.
usernameExistsMessage=Esse utilizador já existe.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do utilizador atual
downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do utilizador atual. Portanto, o utilizador atual não será mostrado.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Alterar usuário
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Rolul utilizatorului curent nu poate fi retrogradat
downgradeCurrentUserLongMessage=Rolul utilizatorului curent nu poate fi retrogradat. Prin urmare, utilizatorul curent nu va fi afișat.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Schimbați rolul utilizatorului
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Пользователь не прошел провер
userNotFoundMessage=Пользователь не найден.
incorrectPasswordMessage=Текущий пароль неверен.
usernameExistsMessage=Новое имя пользователя уже существует.
invalidUsernameMessage=Недопустимое имя пользователя, Имя пользователя должно содержать только буквы алфавита и цифры.
invalidUsernameMessage=Неверное имя пользователя. Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
deleteCurrentUserMessage=Невозможно удалить пользователя, вошедшего в систему.
deleteUsernameExistsMessage=Имя пользователя не существует и не может быть удалено.
downgradeCurrentUserMessage=Невозможно понизить роль текущего пользователя
downgradeCurrentUserLongMessage=Невозможно понизить роль текущего пользователя. Следовательно, текущий пользователь не будет отображаться.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Ошибка
oops=Ой!
help=Помощь
@ -164,7 +165,7 @@ adminUserSettings.header=Настройки контроля пользоват
adminUserSettings.admin=Администратор
adminUserSettings.user=Пользователь
adminUserSettings.addUser=Добавить нового пользователя
adminUserSettings.usernameInfo=Имя пользователя должно содержать только буквы и цифры, без пробелов и специальных символов.
adminUserSettings.usernameInfo=Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
adminUserSettings.roles=Роли
adminUserSettings.role=Роль
adminUserSettings.actions=Действия
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Внутренний пользователь
adminUserSettings.forceChange=Просить пользователя изменить пароль при входе в систему
adminUserSettings.submit=Сохранить пользователя
adminUserSettings.changeUserRole=Изменить роль пользователя
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Korisnik nije autentifikovan.
userNotFoundMessage=Korisnik nije pronađen.
incorrectPasswordMessage=Trenutna šifra je netačna.
usernameExistsMessage=Novi korisnik već postoji
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Nije moguće degradirati ulogu trenutnog korisnika
downgradeCurrentUserLongMessage=Nije moguće unazaditi ulogu trenutnog korisnika. Dakle, trenutni korisnik neće biti prikazan.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Podešavanja kontrole korisnika za administratora
adminUserSettings.admin=Administrator
adminUserSettings.user=Korisnik
adminUserSettings.addUser=Dodaj novog korisnika
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Uloge
adminUserSettings.role=Uloga
adminUserSettings.actions=Akcije
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Prisili korisnika da promeni korisničko ime/lozinku pri prijavi
adminUserSettings.submit=Sačuvaj korisnika
adminUserSettings.changeUserRole=Promenite ulogu korisnika
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Kan inte nedgradera nuvarande användares roll
downgradeCurrentUserLongMessage=Kan inte nedgradera nuvarande användares roll. Därför kommer den aktuella användaren inte att visas.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Ändra användarens roll
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Kullanıcı doğrulanmadı.
userNotFoundMessage=Kullanıcı bulunamadı.
incorrectPasswordMessage=Mevcut şifre yanlış.
usernameExistsMessage=Yeni Kullanıcı Adı zaten var.
invalidUsernameMessage=Geçersiz kullanıcı adı, Kullanıcı adı yalnızca alfabe karakterleri ve sayılar içermelidir.
invalidUsernameMessage=Geçersiz kullanıcı adı, kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor.
deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez.
downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor
downgradeCurrentUserLongMessage=Mevcut kullanıcının rolü düşürülemiyor. Bu nedenle, mevcut kullanıcı gösterilmeyecektir.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Hata
oops=Tüh!
help=Yardım
@ -164,7 +165,7 @@ adminUserSettings.header=Yönetici Kullanıcı Kontrol Ayarları
adminUserSettings.admin=Yönetici
adminUserSettings.user=Kullanıcı
adminUserSettings.addUser=Yeni Kullanıcı Ekle
adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf ve rakamlardan oluşmalı, boşluk veya özel karakter içermemelidir.
adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
adminUserSettings.roles=Roller
adminUserSettings.role=Rol
adminUserSettings.actions=Eylemler
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Dahili API Kullanıcısı
adminUserSettings.forceChange=Kullanıcının girişte kullanıcı adı/şifre değiştirmesini zorla
adminUserSettings.submit=Kullanıcıyı Kaydet
adminUserSettings.changeUserRole=Kullanıcı rolünü değiştir
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=Користувач не пройшов перевір
userNotFoundMessage=Користувача не знайдено.
incorrectPasswordMessage=Поточний пароль невірний.
usernameExistsMessage=Нове ім'я користувача вже існує.
invalidUsernameMessage=Недійсне ім'я користувача, Ім'я користувача повинно містити тільки літери алфавіту та цифри.
invalidUsernameMessage=Недійсне ім’я користувача, ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
deleteCurrentUserMessage=Неможливо видалити користувача, який увійшов в систему.
deleteUsernameExistsMessage=Ім'я користувача не існує і не може бути видалено.
downgradeCurrentUserMessage=Неможливо понизити роль поточного користувача
downgradeCurrentUserLongMessage=Неможливо понизити роль поточного користувача. Отже, поточний користувач не відображатиметься.
userAlreadyExistsMessage=OAuth2: User already exists.
error=Error
oops=Oops!
help=Help
@ -164,7 +165,7 @@ adminUserSettings.header=Налаштування контролю корист
adminUserSettings.admin=Адміністратор
adminUserSettings.user=Користувач
adminUserSettings.addUser=Додати нового користувача
adminUserSettings.usernameInfo=Ім'я користувача має містити тільки літери та цифри, без пробілів та спеціальних символів.
adminUserSettings.usernameInfo=Ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
adminUserSettings.roles=Ролі
adminUserSettings.role=Роль
adminUserSettings.actions=Дії
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=Внутрішній користувач API
adminUserSettings.forceChange=Примусити користувача змінити пароль при вході в систему
adminUserSettings.submit=Зберегти користувача
adminUserSettings.changeUserRole=Змінити роль користувача
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=用户未经过身份验证。
userNotFoundMessage=未找到用户。
incorrectPasswordMessage=当前密码不正确。
usernameExistsMessage=新用户名已存在。
invalidUsernameMessage=用户名无效,用户名只能由字母字符和数字组成
invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址
deleteCurrentUserMessage=无法删除当前登录的用户。
deleteUsernameExistsMessage=用户名不存在,无法删除。
downgradeCurrentUserMessage=无法降级当前用户的角色
downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。
userAlreadyExistsMessage=OAuth2: User already exists.
error=错误
oops=哎呀!
help=帮助
@ -164,7 +165,7 @@ adminUserSettings.header=管理员用户控制设置
adminUserSettings.admin=管理员
adminUserSettings.user=用户
adminUserSettings.addUser=添加新用户
adminUserSettings.usernameInfo=用户名只能由字母和数字组成,不能包含空格或特殊字符
adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址
adminUserSettings.roles=角色
adminUserSettings.role=角色
adminUserSettings.actions=操作
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=内部API用户
adminUserSettings.forceChange=强制用户在登录时更改用户名/密码
adminUserSettings.submit=保存用户
adminUserSettings.changeUserRole=更改用户角色
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -54,11 +54,12 @@ notAuthenticatedMessage=使用者未認證。
userNotFoundMessage=找不到使用者。
incorrectPasswordMessage=目前密碼不正確。
usernameExistsMessage=新使用者名稱已存在。
invalidUsernameMessage=使用者名無效,使用者名只能包含字母字元和數位
invalidUsernameMessage=使用者名稱無效,使用者名稱只能包含字母、數字和以下特殊字元@._+- 或必須是有效的電子郵件地址
deleteCurrentUserMessage=無法刪除目前登錄的使用者。
deleteUsernameExistsMessage=使用者名不存在,無法刪除。
downgradeCurrentUserMessage=無法降級目前使用者的角色
downgradeCurrentUserLongMessage=無法降級目前使用者的角色。因此,不會顯示目前的使用者。
userAlreadyExistsMessage=OAuth2: User already exists.
error=錯誤
oops=哎呀!
help=幫助
@ -164,7 +165,7 @@ adminUserSettings.header=管理使用者控制設定
adminUserSettings.admin=管理員
adminUserSettings.user=使用者
adminUserSettings.addUser=新增使用者
adminUserSettings.usernameInfo=使用者名只能包含字母和數位,不能包含空格或特殊字元
adminUserSettings.usernameInfo=使用者名稱只能包含字母、數字和以下特殊字元@._+-,或必須是有效的電子郵件地址
adminUserSettings.roles=角色
adminUserSettings.role=角色
adminUserSettings.actions=操作
@ -176,6 +177,7 @@ adminUserSettings.internalApiUser=內部 API 使用者
adminUserSettings.forceChange=強制使用者在登入時修改使用者名稱/密碼
adminUserSettings.submit=儲存
adminUserSettings.changeUserRole=更改使用者身份
adminUserSettings.authenticated=Authentication type
#############
# HOME-PAGE #

View file

@ -7,12 +7,16 @@ security:
csrfDisabled: true
loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts
#oauth2:
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# oauth2:
# enabled: true # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
# clientId: "" # Client ID from your provider
# clientSecret: "" # Client Secret from your provider
# autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
# autoCreateUser: true # set to 'true' to allow auto-creation of non-existing users
# autoCreateUser: true # Set to 'true' to automatically create users who do not already exist in the system
# useAsUsername: "email" # Default is 'email'; custom fields can be used as the username
# scopes: "openid, profile, email" # Specify the scopes for which the application will request permissions
# provider: "google" # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)

View file

@ -26,6 +26,7 @@
<th th:text="#{username}">Username</th>
<th th:text="#{adminUserSettings.roles}">Roles</th>
<th th:text="#{adminUserSettings.actions}">Actions</th>
<th th:text="#{adminUserSettings.authenticated}">Authentication type</th>
</tr>
</thead>
<tbody>
@ -37,6 +38,7 @@
<button type="submit" th:text="#{delete}">Delete</button>
</form>
</td>
<td th:text="${user.authenticationType}"></td>
</tr>
</tbody>
</table>
@ -46,10 +48,11 @@
<span th:if="${param.messageType[0] == 'usernameExists'}" th:text="#{usernameExistsMessage}">Default message if not found</span>
<span th:if="${param.messageType[0] == 'invalidUsername'}" th:text="#{invalidUsernameMessage}">Default message if not found</span>
</div>
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button>
<form action="/api/v1/user/admin/saveUser" method="post">
<div class="mb-3">
<label for="username" th:text="#{username}">Username</label>
<input type="text" class="form-control" name="username" pattern="[a-zA-Z0-9]+" th:title="#{adminUserSettings.usernameInfo}" required>
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
</div>
<div class="mb-3">
<label for="password" th:text="#{password}">Password</label>

View file

@ -132,22 +132,34 @@
}
}
</script>
<div th:if="${logoutMessage}" class="alert alert-success" th:text="${logoutMessage}"></div>
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'credsUpdated'}" class="alert alert-success">
<span th:text="#{changedCredsMessage}">Default message if not found</span>
</div>
<form th:action="@{login}" method="post">
<img class="mb-4" src="favicon.svg?v=2" alt="" width="144" height="144">
<h1 class="h1 mb-3 fw-normal" th:text="${@appName}">Stirling-PDF</h1>
<div th:if="${oAuth2Enabled}">
<a href="oauth2/authorization/oidc" class="w-100 btn btn-lg btn-primary" th:text="#{login.ssoSignIn}">Login Via SSO</a>
<div class="text-danger text-center">
<div th:if="${error == 'oauth2AutoCreateDisabled'}" th:text="#{login.oauth2AutoCreateDisabled}">OAUTH2 Auto-Create User Disabled.</div>
<br>
<div th:if="${error}" class="alert alert-danger text-danger text-center">
<!-- oauth2AutoCreateDisabled -->
<div th:if="${error == 'oauth2AutoCreateDisabled'}" th:text="#{login.oauth2AutoCreateDisabled}">OAuth2: Auto-Create User Disabled.</div>
<!-- oauth2AuthenticationError -->
<div th:if="${error == 'oauth2AuthenticationError'}" th:text="#{userAlreadyExistsMessage}">OAuth2: User already exists.</div>
<!-- invalidUsername -->
<div th:if="${error == 'invalidUsername'}" th:text="#{invalidUsernameMessage}">OAUTH2: Invalid username.</div>
<!-- badcredentials -->
<div th:if="${error == 'badcredentials'}" th:text="#{login.invalid}">Invalid username or password.</div>
<!-- locked -->
<div th:if="${error == 'locked'}" th:text="#{login.locked}">Your account has been locked. </div>
</div>
<hr />
</div>
<h2 class="h5 mb-3 fw-normal" th:text="#{login.signinTitle}">Please sign in</h2>
<h2 class="h5 mb-3 fw-normal" th:text="#{login.signinTitle}">Please sign in</h2>
<div class="text-danger text-center">
<div th:if="${logoutMessage}" class="alert alert-success" th:text="${logoutMessage}"></div>
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'credsUpdated'}" class="alert alert-success">
<span th:text="#{changedCredsMessage}">Default message if not found</span>
</div>
</div>
<form th:action="@{login}" method="post">
<div class="form-floating">
<input type="text" class="form-control bg-dark text-light" id="username" name="username" placeholder="admin">
<label for="username" th:text="#{username}">Username</label>
@ -175,10 +187,6 @@
</div>
</div>
</div>
<div class="text-danger text-center">
<div th:if="${error == 'badcredentials'}" th:text="#{login.invalid}">Invalid username or password.</div>
<div th:if="${error == 'locked'}" th:text="#{login.locked}">Your account has been locked. </div>
</div>
</main>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>