user access dates
This commit is contained in:
parent
e240af83fb
commit
1b00ac2b4f
|
@ -28,15 +28,15 @@ 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.repository.UserRepository;
|
|
||||||
import eu.dnetlib.organizations.utils.AuthenticationUtils;
|
import eu.dnetlib.organizations.utils.AuthenticationUtils;
|
||||||
|
import eu.dnetlib.organizations.utils.DatabaseUtils;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserRepository userRepository;
|
private DatabaseUtils databaseUtils;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClientRegistrationRepository clientRegistrationRepository;
|
private ClientRegistrationRepository clientRegistrationRepository;
|
||||||
|
@ -114,7 +114,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 + userRepository.findById(oidcUser.getEmail())
|
final String role = "ROLE_" + 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());
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.dnetlib.organizations.model.view;
|
package eu.dnetlib.organizations.model.view;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
@ -35,6 +36,12 @@ public class UserView implements Serializable {
|
||||||
@Column(name = "role")
|
@Column(name = "role")
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
|
@Column(name = "first_access")
|
||||||
|
private OffsetDateTime firstAccess;
|
||||||
|
|
||||||
|
@Column(name = "last_access")
|
||||||
|
private OffsetDateTime lastAccess;
|
||||||
|
|
||||||
@Type(type = "string-array")
|
@Type(type = "string-array")
|
||||||
@Column(name = "countries", columnDefinition = "text[]")
|
@Column(name = "countries", columnDefinition = "text[]")
|
||||||
private String[] countries;
|
private String[] countries;
|
||||||
|
@ -70,4 +77,20 @@ public class UserView implements Serializable {
|
||||||
public void setCountries(final String[] countries) {
|
public void setCountries(final String[] countries) {
|
||||||
this.countries = countries;
|
this.countries = countries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getFirstAccess() {
|
||||||
|
return firstAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstAccess(final OffsetDateTime firstAccess) {
|
||||||
|
this.firstAccess = firstAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getLastAccess() {
|
||||||
|
return lastAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastAccess(final OffsetDateTime lastAccess) {
|
||||||
|
this.lastAccess = lastAccess;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
package eu.dnetlib.organizations.repository;
|
package eu.dnetlib.organizations.repository;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
|
||||||
import eu.dnetlib.organizations.model.User;
|
import eu.dnetlib.organizations.model.User;
|
||||||
|
|
||||||
public interface UserRepository extends JpaRepository<User, String> {
|
public interface UserRepository extends JpaRepository<User, String> {
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("update User set last_access = ?2 where email = ?1")
|
||||||
|
void updateLastAccess(final String email, OffsetDateTime now);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -401,6 +401,15 @@ public class DatabaseUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Optional<User> findUser(final String email) {
|
||||||
|
final Optional<User> user = userRepository.findById(email);
|
||||||
|
if (user.isPresent()) {
|
||||||
|
userRepository.updateLastAccess(email, OffsetDateTime.now());
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
private String findFirstString(final List<OrganizationView> views, final Function<OrganizationView, String> mapper) {
|
private String findFirstString(final List<OrganizationView> views, final Function<OrganizationView, String> mapper) {
|
||||||
return views.stream().map(mapper).filter(StringUtils::isNotBlank).findFirst().orElse(null);
|
return views.stream().map(mapper).filter(StringUtils::isNotBlank).findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,7 +312,9 @@ INSERT INTO user_roles VALUES ('ADMIN'), ('NATIONAL_ADMIN'), ('USER'), ('PENDING
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
email text PRIMARY KEY,
|
email text PRIMARY KEY,
|
||||||
valid boolean DEFAULT true,
|
valid boolean DEFAULT true,
|
||||||
role text NOT NULL default 'USER' REFERENCES user_roles(role)
|
role text NOT NULL default 'USER' REFERENCES user_roles(role),
|
||||||
|
first_access timestamp with time zone DEFAULT now(),
|
||||||
|
last_access timestamp with time zone DEFAULT now()
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE user_countries (
|
CREATE TABLE user_countries (
|
||||||
|
@ -507,11 +509,13 @@ CREATE VIEW users_view AS SELECT
|
||||||
u.email,
|
u.email,
|
||||||
u.valid,
|
u.valid,
|
||||||
u.role,
|
u.role,
|
||||||
|
u.first_access,
|
||||||
|
u.last_access,
|
||||||
array_remove(array_agg(uc.country), NULL) AS countries
|
array_remove(array_agg(uc.country), NULL) AS countries
|
||||||
FROM
|
FROM
|
||||||
users u
|
users u
|
||||||
LEFT OUTER JOIN user_countries uc ON (u.email = uc.email)
|
LEFT OUTER JOIN user_countries uc ON (u.email = uc.email)
|
||||||
GROUP BY u.email, u.valid, u.role
|
GROUP BY u.email, u.valid, u.role, u.first_access, u.last_access
|
||||||
ORDER BY u.email;
|
ORDER BY u.email;
|
||||||
|
|
||||||
CREATE VIEW suggestions_info_by_country_view AS SELECT c.val AS country,
|
CREATE VIEW suggestions_info_by_country_view AS SELECT c.val AS country,
|
||||||
|
|
|
@ -2,23 +2,24 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 col-md-10 col-lg-8">
|
<div class="col-sm-12 col-lg-10">
|
||||||
<input type="text" class="form-control form-control-sm mb-3" ng-model="userFilter.email" placeholder="Filter...">
|
<input type="text" class="form-control form-control-sm mb-3" ng-model="userFilter.email" placeholder="Filter...">
|
||||||
|
|
||||||
<table class="table table-sm table-hover">
|
<table class="table table-sm table-hover">
|
||||||
<thead class="thead-light">
|
<thead class="thead-light">
|
||||||
<tr class="d-flex">
|
<tr class="d-flex">
|
||||||
<th class="col-4">User</th>
|
<th class="col-3">User</th>
|
||||||
<th class="col-1 text-center">Enabled</th>
|
<th class="col-1 text-center">Enabled</th>
|
||||||
<th class="col-1 text-center">Super Admin</th>
|
<th class="col-1 text-center">Super Admin</th>
|
||||||
<th class="col-1 text-center">National Admin</th>
|
<th class="col-1 text-center">National Admin</th>
|
||||||
<th class="col-3">Countries</th>
|
<th class="col-2 text-center">First/Last access</th>
|
||||||
|
<th class="col-2">Countries</th>
|
||||||
<th class="col-2"></th>
|
<th class="col-2"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="u in users | filter:userFilter" class="d-flex">
|
<tr ng-repeat="u in users | filter:userFilter" class="d-flex">
|
||||||
<th class="col-4" ng-class="{'text-secondary': !u.valid}">{{u.email}}</th>
|
<th class="col-3" ng-class="{'text-secondary': !u.valid}">{{u.email}}</th>
|
||||||
<td class="col-1 text-center text-success">
|
<td class="col-1 text-center text-success">
|
||||||
<i class="fa fa-check-circle" ng-if="u.valid"></i>
|
<i class="fa fa-check-circle" ng-if="u.valid"></i>
|
||||||
<span class="text-warning" ng-if="u.role == 'PENDING'">not configured</span>
|
<span class="text-warning" ng-if="u.role == 'PENDING'">not configured</span>
|
||||||
|
@ -30,7 +31,11 @@
|
||||||
<td class="col-1 text-center">
|
<td class="col-1 text-center">
|
||||||
<i class="fa fa-check-circle" ng-if="u.role == 'NATIONAL_ADMIN'"></i>
|
<i class="fa fa-check-circle" ng-if="u.role == 'NATIONAL_ADMIN'"></i>
|
||||||
</td>
|
</td>
|
||||||
<td class="col-3">
|
<td class="col-2 text-center">
|
||||||
|
<span title="{{u.firstAccess}}">{{u.firstAccess | date}}</span><br />
|
||||||
|
<span title="{{u.lastAccess}}">{{u.lastAccess | date}}</span>
|
||||||
|
</td>
|
||||||
|
<td class="col-2">
|
||||||
<span ng-if="(u.role != 'ADMIN')">
|
<span ng-if="(u.role != 'ADMIN')">
|
||||||
<img ng-src="resources/images/flags/{{c}}.gif" title="{{c}}" class="mr-1" ng-repeat="c in u.countries" />
|
<img ng-src="resources/images/flags/{{c}}.gif" title="{{c}}" class="mr-1" ng-repeat="c in u.countries" />
|
||||||
<span class="text-warning" ng-if="u.countries.length == 0"><i class="fa fa-exclamation-triangle"></i> no countries</span>
|
<span class="text-warning" ng-if="u.countries.length == 0"><i class="fa fa-exclamation-triangle"></i> no countries</span>
|
||||||
|
|
Loading…
Reference in New Issue