user access dates

This commit is contained in:
Michele Artini 2020-11-12 15:47:41 +01:00
parent e240af83fb
commit 1b00ac2b4f
6 changed files with 62 additions and 13 deletions

View File

@ -28,15 +28,15 @@ import org.springframework.security.web.access.AccessDeniedHandler;
import eu.dnetlib.organizations.controller.UserInfo;
import eu.dnetlib.organizations.controller.UserRole;
import eu.dnetlib.organizations.model.User;
import eu.dnetlib.organizations.repository.UserRepository;
import eu.dnetlib.organizations.utils.AuthenticationUtils;
import eu.dnetlib.organizations.utils.DatabaseUtils;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserRepository userRepository;
private DatabaseUtils databaseUtils;
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@ -114,7 +114,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
return (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)
.filter(StringUtils::isNotBlank)
.orElse(UserRole.NOT_AUTHORIZED.toString());

View File

@ -1,6 +1,7 @@
package eu.dnetlib.organizations.model.view;
import java.io.Serializable;
import java.time.OffsetDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
@ -16,7 +17,7 @@ import com.vladmihalcea.hibernate.type.array.StringArrayType;
@Entity
@Table(name = "users_view")
@TypeDefs({
@TypeDef(name = "string-array", typeClass = StringArrayType.class)
@TypeDef(name = "string-array", typeClass = StringArrayType.class)
})
public class UserView implements Serializable {
@ -35,6 +36,12 @@ public class UserView implements Serializable {
@Column(name = "role")
private String role;
@Column(name = "first_access")
private OffsetDateTime firstAccess;
@Column(name = "last_access")
private OffsetDateTime lastAccess;
@Type(type = "string-array")
@Column(name = "countries", columnDefinition = "text[]")
private String[] countries;
@ -70,4 +77,20 @@ public class UserView implements Serializable {
public void setCountries(final String[] 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;
}
}

View File

@ -1,9 +1,17 @@
package eu.dnetlib.organizations.repository;
import java.time.OffsetDateTime;
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;
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);
}

View File

@ -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) {
return views.stream().map(mapper).filter(StringUtils::isNotBlank).findFirst().orElse(null);
}

View File

@ -310,9 +310,11 @@ CREATE TABLE user_roles(role text PRIMARY KEY);
INSERT INTO user_roles VALUES ('ADMIN'), ('NATIONAL_ADMIN'), ('USER'), ('PENDING'), ('NOT_AUTHORIZED');
CREATE TABLE users (
email text PRIMARY KEY,
valid boolean DEFAULT true,
role text NOT NULL default 'USER' REFERENCES user_roles(role)
email text PRIMARY KEY,
valid boolean DEFAULT true,
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 (
@ -507,11 +509,13 @@ CREATE VIEW users_view AS SELECT
u.email,
u.valid,
u.role,
u.first_access,
u.last_access,
array_remove(array_agg(uc.country), NULL) AS countries
FROM
users u
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;
CREATE VIEW suggestions_info_by_country_view AS SELECT c.val AS country,

View File

@ -2,23 +2,24 @@
<br />
<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...">
<table class="table table-sm table-hover">
<thead class="thead-light">
<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">Super 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>
</tr>
</thead>
<tbody>
<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">
<i class="fa fa-check-circle" ng-if="u.valid"></i>
<span class="text-warning" ng-if="u.role == 'PENDING'">not configured</span>
@ -30,7 +31,11 @@
<td class="col-1 text-center">
<i class="fa fa-check-circle" ng-if="u.role == 'NATIONAL_ADMIN'"></i>
</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')">
<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>