simple authentication in DEV profile

This commit is contained in:
Michele Artini 2020-11-23 12:02:33 +01:00
parent 843fc1f93f
commit 3ff5ef9bd6
14 changed files with 253 additions and 65 deletions

View File

@ -0,0 +1,103 @@
package eu.dnetlib.organizations;
import javax.sql.DataSource;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import eu.dnetlib.organizations.controller.UserInfo;
import eu.dnetlib.organizations.utils.OpenOrgsConstants;
@Profile("dev")
@Configuration
@EnableWebSecurity
public class MockSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Value("${openaire.api.valid.subnet}")
private String openaireApiValidSubnet;
private static final String DEFAULT_PASSWORD = "dnet";
private static Logger logger = LoggerFactory.getLogger(MockSecurityConfig.class);
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/", "/api/**")
.hasAnyRole(OpenOrgsConstants.VALID_ROLES)
.antMatchers("/registration_api/**")
.hasRole(OpenOrgsConstants.NOT_AUTORIZED_ROLE)
.antMatchers("/resources/**", "/webjars/**")
.permitAll()
.antMatchers("/oa_api/**")
.hasIpAddress(openaireApiValidSubnet)
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler());
}
private AccessDeniedHandler accessDeniedHandler() {
return (req, res, e) -> {
final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
logger
.warn(String.format("User '%s' (%s) attempted to access the protected URL: %s", auth.getName(), req.getRemoteAddr(), req.getRequestURI()));
}
if (UserInfo.isNotAuthorized(auth)) {
res.sendRedirect(req.getContextPath() + "/authorizationRequest");
} else {
res.sendRedirect(req.getContextPath() + "/alreadyRegistered");
}
};
}
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select ?, '{MD5}" + DigestUtils.md5Hex(DEFAULT_PASSWORD) + "', true")
.authoritiesByUsernameQuery("with const as (SELECT ? as email) "
+ "select c.email, 'ROLE_" + OpenOrgsConstants.OPENORGS_ROLE_PREFIX + "'||coalesce(u.role, '"
+ OpenOrgsConstants.NOT_AUTORIZED_ROLE
+ "') from const c left outer join users u on (u.email = c.email)");
}
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}

View File

@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@ -28,12 +29,13 @@ import org.springframework.security.web.access.AccessDeniedHandler;
import eu.dnetlib.organizations.controller.UserInfo; import eu.dnetlib.organizations.controller.UserInfo;
import eu.dnetlib.organizations.controller.UserRole; import eu.dnetlib.organizations.controller.UserRole;
import eu.dnetlib.organizations.model.User; import eu.dnetlib.organizations.model.User;
import eu.dnetlib.organizations.utils.AuthenticationUtils;
import eu.dnetlib.organizations.utils.DatabaseUtils; import eu.dnetlib.organizations.utils.DatabaseUtils;
import eu.dnetlib.organizations.utils.OpenOrgsConstants;
@Profile("!dev")
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private DatabaseUtils databaseUtils; private DatabaseUtils databaseUtils;
@ -44,17 +46,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${openaire.api.valid.subnet}") @Value("${openaire.api.valid.subnet}")
private String openaireApiValidSubnet; private String openaireApiValidSubnet;
private static String OPENORGS_ROLE_PREFIX = "OPENORGS_"; private static Logger logger = LoggerFactory.getLogger(OAuth2WebSecurityConfig.class);
private static Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
private static final String[] VALID_ROLES = {
OPENORGS_ROLE_PREFIX + UserRole.ADMIN,
OPENORGS_ROLE_PREFIX + UserRole.NATIONAL_ADMIN,
OPENORGS_ROLE_PREFIX + UserRole.USER
};
private static final String NOT_AUTORIZED_ROLE = OPENORGS_ROLE_PREFIX + UserRole.NOT_AUTHORIZED;
@Override @Override
protected void configure(final HttpSecurity http) throws Exception { protected void configure(final HttpSecurity http) throws Exception {
@ -62,9 +54,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.disable() .disable()
.authorizeRequests() .authorizeRequests()
.antMatchers("/main", "/api/**") .antMatchers("/main", "/api/**")
.hasAnyRole(VALID_ROLES) .hasAnyRole(OpenOrgsConstants.VALID_ROLES)
.antMatchers("/registration_api/**") .antMatchers("/registration_api/**")
.hasRole(NOT_AUTORIZED_ROLE) .hasRole(OpenOrgsConstants.NOT_AUTORIZED_ROLE)
.antMatchers("/", "/resources/**", "/webjars/**") .antMatchers("/", "/resources/**", "/webjars/**")
.permitAll() .permitAll()
.antMatchers("/oa_api/**") .antMatchers("/oa_api/**")
@ -86,7 +78,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) { if (authentication != null) {
logger.warn(String logger.warn(String
.format("User '%s' (%s) attempted to access the protected URL: %s", AuthenticationUtils.extractEmail(authentication), req .format("User '%s' (%s) attempted to access the protected URL: %s", UserInfo.getEmail(authentication), req
.getRemoteAddr(), req.getRequestURI())); .getRemoteAddr(), req.getRequestURI()));
} }
@ -114,7 +106,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
return (userRequest) -> { return (userRequest) -> {
final OidcUser oidcUser = delegate.loadUser(userRequest); final OidcUser oidcUser = delegate.loadUser(userRequest);
final String role = "ROLE_" + OPENORGS_ROLE_PREFIX + databaseUtils.findUser(oidcUser.getEmail()) final String role = "ROLE_" + OpenOrgsConstants.OPENORGS_ROLE_PREFIX + databaseUtils.findUser(oidcUser.getEmail())
.map(User::getRole) .map(User::getRole)
.filter(StringUtils::isNotBlank) .filter(StringUtils::isNotBlank)
.orElse(UserRole.NOT_AUTHORIZED.toString()); .orElse(UserRole.NOT_AUTHORIZED.toString());

View File

@ -1,14 +1,22 @@
package eu.dnetlib.organizations.controller; package eu.dnetlib.organizations.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
@Controller @Controller
public class HomeController { public class HomeController {
@Autowired
private Environment env;
@GetMapping("/") @GetMapping("/")
public String home() { public String home() {
return "home"; return env.acceptsProfiles(Profiles.of("dev")) ? "redirect:main" : "home";
} }
@GetMapping("/main") @GetMapping("/main")
@ -31,6 +39,11 @@ public class HomeController {
return "alreadyRegistered"; return "alreadyRegistered";
} }
@ModelAttribute("email")
public String getUserEmail(final Authentication authentication) {
return authentication != null ? UserInfo.getEmail(authentication) : null;
}
@GetMapping({ @GetMapping({
"/doc", "/swagger" "/doc", "/swagger"
}) })

View File

@ -41,7 +41,6 @@ import eu.dnetlib.organizations.repository.readonly.OrganizationInfoViewReposito
import eu.dnetlib.organizations.repository.readonly.OrganizationSimpleViewRepository; import eu.dnetlib.organizations.repository.readonly.OrganizationSimpleViewRepository;
import eu.dnetlib.organizations.repository.readonly.OrganizationViewRepository; import eu.dnetlib.organizations.repository.readonly.OrganizationViewRepository;
import eu.dnetlib.organizations.repository.readonly.SuggestionInfoViewByCountryRepository; import eu.dnetlib.organizations.repository.readonly.SuggestionInfoViewByCountryRepository;
import eu.dnetlib.organizations.utils.AuthenticationUtils;
import eu.dnetlib.organizations.utils.DatabaseUtils; import eu.dnetlib.organizations.utils.DatabaseUtils;
import eu.dnetlib.organizations.utils.OrganizationStatus; import eu.dnetlib.organizations.utils.OrganizationStatus;
@ -78,9 +77,9 @@ public class OrganizationController {
} else if (StringUtils.isBlank(org.getType())) { } else if (StringUtils.isBlank(org.getType())) {
throw new RuntimeException("Missing field: type"); throw new RuntimeException("Missing field: type");
} else if (UserInfo.isSuperAdmin(authentication) } else if (UserInfo.isSuperAdmin(authentication)
|| userCountryRepository.verifyAuthorizationForCountry(org.getCountry(), AuthenticationUtils.extractEmail(authentication))) { || userCountryRepository.verifyAuthorizationForCountry(org.getCountry(), UserInfo.getEmail(authentication))) {
final String orgId = final String orgId =
databaseUtils.insertOrUpdateOrganization(org, AuthenticationUtils.extractEmail(authentication), UserInfo.isSimpleUser(authentication)); databaseUtils.insertOrUpdateOrganization(org, UserInfo.getEmail(authentication), UserInfo.isSimpleUser(authentication));
return Arrays.asList(orgId); return Arrays.asList(orgId);
} else { } else {
throw new RuntimeException("User not authorized"); throw new RuntimeException("User not authorized");
@ -99,7 +98,7 @@ public class OrganizationController {
if (UserInfo.isSuperAdmin(authentication)) { if (UserInfo.isSuperAdmin(authentication)) {
suggestionInfoViewByCountryRepository.findAll().forEach(info::add); suggestionInfoViewByCountryRepository.findAll().forEach(info::add);
} else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) { } else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) {
userCountryRepository.getCountriesForUser(AuthenticationUtils.extractEmail(authentication)) userCountryRepository.getCountriesForUser(UserInfo.getEmail(authentication))
.stream() .stream()
.map(suggestionInfoViewByCountryRepository::findById) .map(suggestionInfoViewByCountryRepository::findById)
.filter(Optional::isPresent) .filter(Optional::isPresent)
@ -114,7 +113,7 @@ public class OrganizationController {
final OrganizationView org = organizationViewRepository.findById(id).get(); final OrganizationView org = organizationViewRepository.findById(id).get();
if (UserInfo.isSuperAdmin(authentication) if (UserInfo.isSuperAdmin(authentication)
|| userCountryRepository.verifyAuthorizationForCountry(org.getCountry(), AuthenticationUtils.extractEmail(authentication))) { || userCountryRepository.verifyAuthorizationForCountry(org.getCountry(), UserInfo.getEmail(authentication))) {
return org; return org;
} else { } else {
throw new RuntimeException("User not authorized"); throw new RuntimeException("User not authorized");
@ -123,7 +122,7 @@ public class OrganizationController {
@GetMapping("/conflicts") @GetMapping("/conflicts")
public List<OrganizationConflict> conflicts(@RequestParam final String id, final Authentication authentication) { public List<OrganizationConflict> conflicts(@RequestParam final String id, final Authentication authentication) {
if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, AuthenticationUtils.extractEmail(authentication))) { if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, UserInfo.getEmail(authentication))) {
return databaseUtils.listConflictsForId(id); return databaseUtils.listConflictsForId(id);
} else { } else {
throw new RuntimeException("User not authorized"); throw new RuntimeException("User not authorized");
@ -132,7 +131,7 @@ public class OrganizationController {
@GetMapping("/duplicates") @GetMapping("/duplicates")
public List<OpenaireDuplicateView> duplicates(@RequestParam final String id, final Authentication authentication) { public List<OpenaireDuplicateView> duplicates(@RequestParam final String id, final Authentication authentication) {
if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, AuthenticationUtils.extractEmail(authentication))) { if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, UserInfo.getEmail(authentication))) {
return openaireDuplicateViewRepository.findByLocalId(id); return openaireDuplicateViewRepository.findByLocalId(id);
} else { } else {
throw new RuntimeException("User not authorized"); throw new RuntimeException("User not authorized");
@ -145,7 +144,7 @@ public class OrganizationController {
if (UserInfo.isSuperAdmin(authentication)) { if (UserInfo.isSuperAdmin(authentication)) {
return groupConflicts(conflictGroupViewRepository.findByCountry1OrCountry2(country, country).stream()); return groupConflicts(conflictGroupViewRepository.findByCountry1OrCountry2(country, country).stream());
} else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) { } else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) {
final Stream<ConflictGroupView> list = userCountryRepository.getCountriesForUser(AuthenticationUtils.extractEmail(authentication)) final Stream<ConflictGroupView> list = userCountryRepository.getCountriesForUser(UserInfo.getEmail(authentication))
.stream() .stream()
.filter(country::equalsIgnoreCase) .filter(country::equalsIgnoreCase)
.map(c -> conflictGroupViewRepository.findByCountry1OrCountry2(c, c).stream()) .map(c -> conflictGroupViewRepository.findByCountry1OrCountry2(c, c).stream())
@ -164,7 +163,7 @@ public class OrganizationController {
if (UserInfo.isSuperAdmin(authentication)) { if (UserInfo.isSuperAdmin(authentication)) {
return duplicateGroupViewRepository.findByCountry(country); return duplicateGroupViewRepository.findByCountry(country);
} else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) { } else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) {
return userCountryRepository.getCountriesForUser(AuthenticationUtils.extractEmail(authentication)) return userCountryRepository.getCountriesForUser(UserInfo.getEmail(authentication))
.stream() .stream()
.filter(country::equalsIgnoreCase) .filter(country::equalsIgnoreCase)
.map(duplicateGroupViewRepository::findByCountry) .map(duplicateGroupViewRepository::findByCountry)
@ -197,10 +196,10 @@ public class OrganizationController {
|| simrels.stream() || simrels.stream()
.map(OpenaireDuplicate::getLocalId) .map(OpenaireDuplicate::getLocalId)
.distinct() .distinct()
.allMatch(id -> userCountryRepository.verifyAuthorizationForId(id, AuthenticationUtils.extractEmail(authentication))); .allMatch(id -> userCountryRepository.verifyAuthorizationForId(id, UserInfo.getEmail(authentication)));
if (b) { if (b) {
databaseUtils.saveDuplicates(simrels, AuthenticationUtils.extractEmail(authentication)); databaseUtils.saveDuplicates(simrels, UserInfo.getEmail(authentication));
return openaireDuplicateViewRepository.findByLocalId(simrels.get(0).getLocalId()); return openaireDuplicateViewRepository.findByLocalId(simrels.get(0).getLocalId());
} else { } else {
throw new RuntimeException("User not authorized"); throw new RuntimeException("User not authorized");
@ -226,7 +225,7 @@ public class OrganizationController {
return UserInfo.isSuperAdmin(authentication) return UserInfo.isSuperAdmin(authentication)
? organizationSimpleViewRepository.search(q, statuses, PageRequest.of(page, size)) ? organizationSimpleViewRepository.search(q, statuses, PageRequest.of(page, size))
: organizationSimpleViewRepository.searchForUser(q, AuthenticationUtils.extractEmail(authentication), statuses, PageRequest.of(page, size)); : organizationSimpleViewRepository.searchForUser(q, UserInfo.getEmail(authentication), statuses, PageRequest.of(page, size));
} }
@ -237,7 +236,7 @@ public class OrganizationController {
@PathVariable final int size, @PathVariable final int size,
final Authentication authentication) { final Authentication authentication) {
if (UserInfo.isSuperAdmin(authentication) if (UserInfo.isSuperAdmin(authentication)
|| userCountryRepository.verifyAuthorizationForCountry(code, AuthenticationUtils.extractEmail(authentication))) { || userCountryRepository.verifyAuthorizationForCountry(code, UserInfo.getEmail(authentication))) {
if (status.equalsIgnoreCase("all")) { if (status.equalsIgnoreCase("all")) {
return organizationSimpleViewRepository.findByCountryOrderByName(code, PageRequest.of(page, size)); return organizationSimpleViewRepository.findByCountryOrderByName(code, PageRequest.of(page, size));
} else { } else {
@ -253,7 +252,7 @@ public class OrganizationController {
@PathVariable final String code, @PathVariable final String code,
final Authentication authentication) { final Authentication authentication) {
if (UserInfo.isSuperAdmin(authentication) if (UserInfo.isSuperAdmin(authentication)
|| userCountryRepository.verifyAuthorizationForCountry(code, AuthenticationUtils.extractEmail(authentication))) { || userCountryRepository.verifyAuthorizationForCountry(code, UserInfo.getEmail(authentication))) {
if (status.equalsIgnoreCase("all")) { if (status.equalsIgnoreCase("all")) {
return organizationSimpleViewRepository.findByCountryOrderByName(code); return organizationSimpleViewRepository.findByCountryOrderByName(code);
} else { } else {
@ -279,10 +278,10 @@ public class OrganizationController {
} }
} else { } else {
if (status.equalsIgnoreCase("all")) { if (status.equalsIgnoreCase("all")) {
return organizationSimpleViewRepository.findByTypeForUser(type, AuthenticationUtils.extractEmail(authentication), PageRequest.of(page, size)); return organizationSimpleViewRepository.findByTypeForUser(type, UserInfo.getEmail(authentication), PageRequest.of(page, size));
} else { } else {
return organizationSimpleViewRepository return organizationSimpleViewRepository
.findByTypeAndStatusForUser(type, status, AuthenticationUtils.extractEmail(authentication), PageRequest.of(page, size)); .findByTypeAndStatusForUser(type, status, UserInfo.getEmail(authentication), PageRequest.of(page, size));
} }
} }
@ -292,21 +291,21 @@ public class OrganizationController {
public List<BrowseEntry> browseCountries(final Authentication authentication) { public List<BrowseEntry> browseCountries(final Authentication authentication) {
return UserInfo.isSuperAdmin(authentication) return UserInfo.isSuperAdmin(authentication)
? databaseUtils.browseCountries() ? databaseUtils.browseCountries()
: databaseUtils.browseCountriesForUser(AuthenticationUtils.extractEmail(authentication)); : databaseUtils.browseCountriesForUser(UserInfo.getEmail(authentication));
} }
@GetMapping("/browse/types") @GetMapping("/browse/types")
public List<BrowseEntry> browseOrganizationTypes(final Authentication authentication) { public List<BrowseEntry> browseOrganizationTypes(final Authentication authentication) {
return UserInfo.isSuperAdmin(authentication) return UserInfo.isSuperAdmin(authentication)
? databaseUtils.browseTypes() ? databaseUtils.browseTypes()
: databaseUtils.browseTypesForUser(AuthenticationUtils.extractEmail(authentication)); : databaseUtils.browseTypesForUser(UserInfo.getEmail(authentication));
} }
@PostMapping("/conflicts/fix/similar") @PostMapping("/conflicts/fix/similar")
public List<String> fixConflictSim(final Authentication authentication, @RequestBody final List<String> ids) { public List<String> fixConflictSim(final Authentication authentication, @RequestBody final List<String> ids) {
if (ids.size() > 1 && UserInfo.isSuperAdmin(authentication) if (ids.size() > 1 && UserInfo.isSuperAdmin(authentication)
|| userCountryRepository.verifyAuthorizationForId(ids.get(0), AuthenticationUtils.extractEmail(authentication))) { || userCountryRepository.verifyAuthorizationForId(ids.get(0), UserInfo.getEmail(authentication))) {
final String newOrgId = databaseUtils.fixConflictSimilars(ids, AuthenticationUtils.extractEmail(authentication)); final String newOrgId = databaseUtils.fixConflictSimilars(ids, UserInfo.getEmail(authentication));
return Arrays.asList(newOrgId); return Arrays.asList(newOrgId);
} else { } else {
return new ArrayList<>(); return new ArrayList<>();
@ -316,8 +315,8 @@ public class OrganizationController {
@PostMapping("/conflicts/fix/different") @PostMapping("/conflicts/fix/different")
public List<String> fixConflictDiff(final Authentication authentication, @RequestBody final List<String> ids) { public List<String> fixConflictDiff(final Authentication authentication, @RequestBody final List<String> ids) {
if (ids.size() > 1 && UserInfo.isSuperAdmin(authentication) if (ids.size() > 1 && UserInfo.isSuperAdmin(authentication)
|| userCountryRepository.verifyAuthorizationForId(ids.get(0), AuthenticationUtils.extractEmail(authentication))) { || userCountryRepository.verifyAuthorizationForId(ids.get(0), UserInfo.getEmail(authentication))) {
databaseUtils.fixConflictDifferents(ids, AuthenticationUtils.extractEmail(authentication)); databaseUtils.fixConflictDifferents(ids, UserInfo.getEmail(authentication));
return ids; return ids;
} else { } else {
return new ArrayList<>(); return new ArrayList<>();

View File

@ -20,7 +20,6 @@ import eu.dnetlib.organizations.model.utils.VocabularyTerm;
import eu.dnetlib.organizations.model.view.UserView; import eu.dnetlib.organizations.model.view.UserView;
import eu.dnetlib.organizations.repository.UserRepository; import eu.dnetlib.organizations.repository.UserRepository;
import eu.dnetlib.organizations.repository.readonly.UserViewRepository; import eu.dnetlib.organizations.repository.readonly.UserViewRepository;
import eu.dnetlib.organizations.utils.AuthenticationUtils;
import eu.dnetlib.organizations.utils.DatabaseUtils; import eu.dnetlib.organizations.utils.DatabaseUtils;
@RestController @RestController
@ -37,7 +36,7 @@ public class UserController {
@PostMapping(value = "/registration_api/newUser") @PostMapping(value = "/registration_api/newUser")
public Map<String, Integer> newUser(final @RequestBody List<String> countries, final Authentication authentication) { public Map<String, Integer> newUser(final @RequestBody List<String> countries, final Authentication authentication) {
final String email = AuthenticationUtils.extractEmail(authentication); final String email = UserInfo.getEmail(authentication);
final Map<String, Integer> res = new HashMap<>(); final Map<String, Integer> res = new HashMap<>();
@ -58,7 +57,7 @@ public class UserController {
// IMPORTANT: a national admin can manage ONLY the users where ALL the countries are under his control // IMPORTANT: a national admin can manage ONLY the users where ALL the countries are under his control
final List<UserView> res = new ArrayList<>(); final List<UserView> res = new ArrayList<>();
final List<String> myCountries = dbUtils.listCountriesForUser(AuthenticationUtils.extractEmail(authentication)) final List<String> myCountries = dbUtils.listCountriesForUser(UserInfo.getEmail(authentication))
.stream() .stream()
.map(VocabularyTerm::getValue) .map(VocabularyTerm::getValue)
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -76,14 +75,14 @@ public class UserController {
@PostMapping("/api/users") @PostMapping("/api/users")
public Iterable<UserView> save(@RequestBody final UserView userView, final Authentication authentication) { public Iterable<UserView> save(@RequestBody final UserView userView, final Authentication authentication) {
if (AuthenticationUtils.extractEmail(authentication).equals(userView.getEmail())) { throw new RuntimeException("You can't edit your own user"); } if (UserInfo.getEmail(authentication).equals(userView.getEmail())) { throw new RuntimeException("You can't edit your own user"); }
dbUtils.saveUser(userView); dbUtils.saveUser(userView);
return users(authentication); return users(authentication);
} }
@DeleteMapping("/api/users") @DeleteMapping("/api/users")
public Iterable<UserView> delete(final @RequestParam String email, final Authentication authentication) { public Iterable<UserView> delete(final @RequestParam String email, final Authentication authentication) {
if (AuthenticationUtils.extractEmail(authentication).equals(email)) { throw new RuntimeException("You can't delete your own user"); } if (UserInfo.getEmail(authentication).equals(email)) { throw new RuntimeException("You can't delete your own user"); }
dbUtils.deleteUser(email); dbUtils.deleteUser(email);
return users(authentication); return users(authentication);
} }

View File

@ -4,8 +4,7 @@ import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import eu.dnetlib.organizations.utils.AuthenticationUtils;
public class UserInfo { public class UserInfo {
@ -39,7 +38,7 @@ public class UserInfo {
} }
public static UserInfo generate(final Authentication authentication) { public static UserInfo generate(final Authentication authentication) {
return new UserInfo(AuthenticationUtils.extractEmail(authentication), findRole(authentication)); return new UserInfo(getEmail(authentication), findRole(authentication));
} }
public static UserRole findRole(final Authentication authentication) { public static UserRole findRole(final Authentication authentication) {
@ -88,4 +87,9 @@ public class UserInfo {
return false; return false;
} }
public static String getEmail(final Authentication authentication) {
final Object user = authentication.getPrincipal();
return user instanceof DefaultOidcUser ? ((DefaultOidcUser) user).getEmail() : authentication.getName();
}
} }

View File

@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import eu.dnetlib.organizations.model.utils.VocabularyTerm; import eu.dnetlib.organizations.model.utils.VocabularyTerm;
import eu.dnetlib.organizations.utils.AuthenticationUtils;
import eu.dnetlib.organizations.utils.DatabaseUtils; import eu.dnetlib.organizations.utils.DatabaseUtils;
import eu.dnetlib.organizations.utils.DatabaseUtils.VocabularyTable; import eu.dnetlib.organizations.utils.DatabaseUtils.VocabularyTable;
import eu.dnetlib.organizations.utils.RelationType; import eu.dnetlib.organizations.utils.RelationType;
@ -40,7 +39,7 @@ public class VocabulariesController {
.collect(Collectors.toList())); .collect(Collectors.toList()));
if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) { if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) {
vocs.put("countries", databaseUtils.listCountriesForUser(AuthenticationUtils.extractEmail(authentication))); vocs.put("countries", databaseUtils.listCountriesForUser(UserInfo.getEmail(authentication)));
} else if (UserInfo.isSuperAdmin(authentication)) { } else if (UserInfo.isSuperAdmin(authentication)) {
vocs.put("countries", databaseUtils.listValuesOfVocabularyTable(VocabularyTable.countries)); vocs.put("countries", databaseUtils.listValuesOfVocabularyTable(VocabularyTable.countries));
} else { } else {

View File

@ -1,12 +0,0 @@
package eu.dnetlib.organizations.utils;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
public class AuthenticationUtils {
public static String extractEmail(final Authentication authentication) {
final Object user = authentication.getPrincipal();
return user instanceof DefaultOidcUser ? ((DefaultOidcUser) user).getEmail() : authentication.getName();
}
}

View File

@ -1,8 +1,20 @@
package eu.dnetlib.organizations.utils; package eu.dnetlib.organizations.utils;
import eu.dnetlib.organizations.controller.UserRole;
public class OpenOrgsConstants { public class OpenOrgsConstants {
public static final String OPENORGS_PREFIX = "openorgs____::"; public static final String OPENORGS_PREFIX = "openorgs____::";
public static final String OPENORGS_MESH_PREFIX = "openorgsmesh::"; public static final String OPENORGS_MESH_PREFIX = "openorgsmesh::";
public static final String OPENORGS_ROLE_PREFIX = "OPENORGS_";
public static final String[] VALID_ROLES = {
OPENORGS_ROLE_PREFIX + UserRole.ADMIN,
OPENORGS_ROLE_PREFIX + UserRole.NATIONAL_ADMIN,
OPENORGS_ROLE_PREFIX + UserRole.USER
};
public static final String NOT_AUTORIZED_ROLE = OPENORGS_ROLE_PREFIX + UserRole.NOT_AUTHORIZED;
} }

View File

@ -1,5 +1,7 @@
server.port=8480 server.port=8480
#spring.profiles.active=dev
spring.main.banner-mode = off spring.main.banner-mode = off
logging.level.root = INFO logging.level.root = INFO

View File

@ -29,7 +29,7 @@
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Already registered</h5> <h5 class="card-title">Already registered</h5>
<p class="card-text" th:inline="text"> <p class="card-text" th:inline="text">
Hello <b sec:authentication="principal.email" id="current_user"></b>,<br /> Hello <b th:text="${email}" id="current_user"></b>,<br />
<span sec:authorize="hasRole('ROLE_OPENORGS_ADMIN') or hasRole('ROLE_OPENORGS_NATIONAL_ADMIN') or hasRole('ROLE_OPENORGS_USER')"> <span sec:authorize="hasRole('ROLE_OPENORGS_ADMIN') or hasRole('ROLE_OPENORGS_NATIONAL_ADMIN') or hasRole('ROLE_OPENORGS_USER')">
You are already registered. You are already registered.
</span> </span>

View File

@ -34,7 +34,7 @@
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Authorization request</h5> <h5 class="card-title">Authorization request</h5>
<p class="card-text" th:inline="text"> <p class="card-text" th:inline="text">
Hello '<span sec:authentication="principal.email" id="current_user"></span>', you don't have a role yet <br /> Hello '<span th:text="${email}" id="current_user"></span>', you don't have a role yet <br />
To apply as data curator compile the form below, an administrator will authorize you as soon as possible. To apply as data curator compile the form below, an administrator will authorize you as soon as possible.
</p> </p>

View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="Cache-Control"
content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="resources/css/bootstrap.min.css" />
<title>Organizations Database: Login</title>
</head>
<body>
<div>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand" href="#">
<img src="resources/images/openaire_logo_small.png" width="30" height="30" alt="OpenOrgs Database"> OpenOrgs Database
</a>
</nav>
</div>
<div class="container-fluid">
<div class="row" style="margin-top: 20px">
<div class="col-xs-12 col-sm-10 col-md-8 col-lg-4 offset-sm-1 offset-md-2 offset-lg-4">
<div class="card">
<div class="card-header">
<ul id="tabList" class="nav nav-tabs card-header-tabs">
<li class="nav-item"><a href="#tabLogin" class="nav-link active">Sign In</a></li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active" id="tabLogin">
<form th:action="@{/login}" method="post">
<div th:if="${param.error}">
<div class="alert alert-danger">Invalid username and password.</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-info">You have been logged out.</div>
</div>
<div class="form-group">
<input type="text" name="username" id="username" class="form-control input-lg" placeholder="Email" required="true" autofocus="true" />
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg" placeholder="Password" required="true" />
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<input type="submit" class="btn btn-lg btn-primary btn-block" value="Sign In" />
</div>
<div class="col-xs-6 col-sm-6 col-md-6"></div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="resources/js/jquery-3.4.1.min.js"></script>
<script src="resources/js/popper.min.js"></script>
<script src="resources/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -111,7 +111,7 @@ fieldset > legend { font-size : 1.2rem !important; }
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown"><i class="fa fa-user"></i></a> <a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown"><i class="fa fa-user"></i></a>
<div class="dropdown-menu dropdown-menu-right"> <div class="dropdown-menu dropdown-menu-right">
<p class="px-4 pt-2 text-muted small"> <p class="px-4 pt-2 text-muted small">
<b>Logged as:</b><br /><span sec:authentication="principal.email" id="current_user"></span><br /> <b>Logged as:</b><br /><span th:text="${email}" id="current_user"></span><br />
<b>Role:</b><br /> <b>Role:</b><br />
<span sec:authorize="hasRole('ROLE_OPENORGS_ADMIN')">Super Admin</span> <span sec:authorize="hasRole('ROLE_OPENORGS_ADMIN')">Super Admin</span>
<span sec:authorize="hasRole('ROLE_OPENORGS_NATIONAL_ADMIN')">National Admin</span> <span sec:authorize="hasRole('ROLE_OPENORGS_NATIONAL_ADMIN')">National Admin</span>