Skip to content

Commit

Permalink
SHIBUI-2571
Browse files Browse the repository at this point in the history
Changed output for logins
  • Loading branch information
chasegawa committed Jun 2, 2023
1 parent bd12650 commit da14d5b
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,20 @@

@Data
@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "username", "login" }) })
public class UserLoginRecord {
@Id
@GeneratedValue
private Long id;

private String username;

private String login;

private Date loginDate;

public UserLoginRecord() {
}

public UserLoginRecord(String username, Date loginDate, String formattedDate) {
public UserLoginRecord(String username) {
this.username = username;
this.login = formattedDate;
this.loginDate = loginDate;
this.loginDate = new Date();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import java.util.Optional;

public interface UserLoginRecordRepository extends JpaRepository<UserLoginRecord, Long> {
Optional<UserLoginRecord> findByUsernameAndLogin(String username, String formattedDate);
Optional<UserLoginRecord> findTopByUsername(String username);

@Query(value = "SELECT count(*) FROM UserLoginRecord ulr WHERE ulr.loginDate >= :sinceDate")
int countLoginsSince(@Param("sinceDate") Date sinceDate);

@Query(value = "SELECT count(DISTINCT ulr.username) FROM UserLoginRecord ulr WHERE ulr.loginDate >= :sinceDate")
int countUniqueUserLoginsSince(@Param("sinceDate") Date sinceDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -251,21 +251,27 @@ public boolean currentUserCanEnable() {
}

/**
* Ensure there exists a login record for this username and today's date
* Ensure there exists a login record for this username and current time
* @param username
*/
public void updateLoginRecord(String username) {
Date current = new Date();
String formattedDate = DATE_FORMAT.format(current);

if (userLoginRecordRepository.findByUsernameAndLogin(username,formattedDate).isEmpty()) {
UserLoginRecord ulr = new UserLoginRecord(username, current, formattedDate);
userLoginRecordRepository.saveAndFlush(ulr);
}
UserLoginRecord ulr = new UserLoginRecord(username);
userLoginRecordRepository.saveAndFlush(ulr);
}

/**
* @return count of all logins in the last 24 hours
*/
public int getDailyLoginCount() {
Date since = DateUtils.addDays(new Date(), -1);
return userLoginRecordRepository.countLoginsSince(since);
}

/**
* @return count of unique users logged in during the last 24 hours
*/
public int getDailyUniqueUserLogins() {
Date since = DateUtils.addDays(new Date(), -1);
return userLoginRecordRepository.countUniqueUserLoginsSince(since);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ private ShibuiDetail getShibuiDetailData() {
.numberOfMetadataProviders(metadataResolverRepository.getActiveMetadataProviderCount())
.numberOfFilters(filterRepository.getActiveFilterCount())
.dailyLogins(userService.getDailyLoginCount())
.dailyUniqueUserLogins(userService.getDailyUniqueUserLogins())
.numberOfGroups((int) groupsRepository.count())
.numberOfRoles((int) roleRepository.count())
.db(this.db)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class ShibuiDetail {
private int numberOfMetadataProviders;
private int numberOfFilters;
private int dailyLogins;
private int dailyUniqueUserLogins;
private int numberOfGroups;
private int numberOfRoles;
private String installationID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.actuate.endpoint.annotation.Selector
import org.springframework.boot.actuate.health.DefaultHealthContributorRegistry
import org.springframework.boot.actuate.health.Health
import org.springframework.boot.actuate.health.HealthComponent
import org.springframework.boot.actuate.health.HealthEndpoint
import org.springframework.boot.actuate.health.HealthEndpointGroup
import org.springframework.boot.actuate.health.HealthEndpointGroups
import org.springframework.boot.actuate.health.Status
import org.springframework.boot.actuate.info.InfoContributor
import org.springframework.boot.actuate.info.InfoEndpoint
import org.springframework.boot.SpringBootConfiguration
Expand Down Expand Up @@ -141,4 +149,20 @@ class TestConfiguration {
public InfoEndpoint getInfoEndpoint() {
return new InfoEndpoint(new ArrayList<InfoContributor>());
}

@Bean
public HealthEndpoint getHealthEndpoint() {
return new HealthEndpoint(new DefaultHealthContributorRegistry(), new HealthEndpointGroups() {
@Override HealthEndpointGroup getPrimary() { return null }

@Override Set<String> getNames() { return null }

@Override HealthEndpointGroup get(String name) { return null }
}) {
@Override
HealthComponent healthForPath(@Selector(match = Selector.Match.ALL_REMAINING) String... path) {
return new Health(new Status(""), new HashMap<String, Object>());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,47 +171,51 @@ class UserServiceTests extends AbstractBaseDataJpaTest {

def "when user login - ensure record is created"() {
given:
SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yyyy")

Date current = new Date();
String formattedDate = DATE_FORMAT.format(current)
UserLoginRecord ulr = new UserLoginRecord("username", current, formattedDate)
def sinceDate = DateUtils.addDays(new Date(), -1);
UserLoginRecord ulr = new UserLoginRecord("username")

expect:
userLoginRecordRepository.findByUsernameAndLogin("username", formattedDate).isEmpty()
userLoginRecordRepository.findTopByUsername("username").isEmpty()
userLoginRecordRepository.count() == 0

when:
userService.updateLoginRecord("username")

then:
userLoginRecordRepository.findByUsernameAndLogin("username", formattedDate).isPresent()
userLoginRecordRepository.findTopByUsername("username").isPresent()
userLoginRecordRepository.count() == 1
userLoginRecordRepository.countLoginsSince(sinceDate) == 1
userLoginRecordRepository.countUniqueUserLoginsSince(sinceDate) == 1

when: 'try adding again should not change result'
when: 'repeat login change results appropriately'
userService.updateLoginRecord("username")

then:
userLoginRecordRepository.findByUsernameAndLogin("username", formattedDate).isPresent()
userLoginRecordRepository.count() == 1
userService.getDailyLoginCount() == 1
userLoginRecordRepository.findTopByUsername("username").isPresent()
userLoginRecordRepository.count() == 2
userLoginRecordRepository.countLoginsSince(sinceDate) == 2
userLoginRecordRepository.countUniqueUserLoginsSince(sinceDate) == 1

when:
when: 'new login'
userService.updateLoginRecord("username2")

then:
userLoginRecordRepository.findByUsernameAndLogin("username2", formattedDate).isPresent()
userLoginRecordRepository.count() == 2
userService.getDailyLoginCount() == 2
userLoginRecordRepository.findTopByUsername("username2").isPresent()
userLoginRecordRepository.count() == 3
userLoginRecordRepository.countLoginsSince(sinceDate) == 3
userLoginRecordRepository.countUniqueUserLoginsSince(sinceDate) == 2

when: 'older logins in db, should be same counts'
Date older = DateUtils.addDays(new Date(), -3)
String formattedDate2 = DATE_FORMAT.format(older)
UserLoginRecord ulr2 = new UserLoginRecord("username", older, formattedDate2)
UserLoginRecord ulr2 = new UserLoginRecord("username").with {
it.loginDate = older
it
}
userLoginRecordRepository.save(ulr2)

then:
userLoginRecordRepository.count() == 3
userService.getDailyLoginCount() == 2
userLoginRecordRepository.count() == 4
userLoginRecordRepository.countLoginsSince(sinceDate) == 3
userLoginRecordRepository.countUniqueUserLoginsSince(sinceDate) == 2
}
}
16 changes: 0 additions & 16 deletions delete.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
((HttpServletResponse) response).sendRedirect("/unsecured/error.html");
} else {
// User exists or has been created and has a role so we can continue on.
userService.updateLoginRecord(username);
chain.doFilter(request, response); // else, user is in the system already, carry on
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ public void validate(final Credentials credentials, final WebContext context, fi
CommonProfile profile = (CommonProfile) credentials.getUserProfile();
profile.setRoles(userService.getUserRoles(profile.getUsername()));
credentials.setUserProfile(profile);
userService.updateLoginRecord(profile.getUsername());
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package net.unicon.shibui.pac4j

import edu.internet2.tier.shibboleth.admin.ui.security.model.Group
import edu.internet2.tier.shibboleth.admin.ui.security.model.Role
import edu.internet2.tier.shibboleth.admin.ui.security.model.User
import edu.internet2.tier.shibboleth.admin.ui.security.repository.OwnershipRepository
import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository
import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserLoginRecordRepository
import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository
import edu.internet2.tier.shibboleth.admin.ui.security.service.GroupServiceForTesting
import edu.internet2.tier.shibboleth.admin.ui.security.service.IRolesService
Expand All @@ -30,7 +28,6 @@ import spock.lang.Subject
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import java.text.SimpleDateFormat

@DataJpaTest
@ContextConfiguration(classes=[Pac4JTestingConfig])
Expand All @@ -57,9 +54,6 @@ class AddNewUserFilterTests extends Specification {
@Autowired
Pac4jConfigurationProperties pac4jConfigurationProperties

@Autowired
UserLoginRecordRepository userLoginRecordRepository

@Autowired
UserRepository userRepository

Expand Down Expand Up @@ -107,44 +101,6 @@ class AddNewUserFilterTests extends Specification {
roles.each {
roleRepository.save(it)
}

Group gb = new Group()
gb.setResourceId("testingGroupBBB")
gb.setName("Group BBB")
gb.setValidationRegex("^(?:https?:\\/\\/)?(?:[^.]+\\.)?shib\\.org(\\/.*)?\$")
gb = groupService.createGroup(gb)

Optional<Role> userRole = roleRepository.findByName("ROLE_USER")
User user = new User(username: "someUser", roles:[userRole.get()], password: "foo")
user.setGroup(gb)
userService.save(user)
}

def "user logged in"() {
given:
['Username': 'someUser',
'FirstName': 'Some',
'LastName': 'User',
'Email': 'someUser@institution.edu'].each { key, value ->
saml2Profile.getAttribute(profileMapping."get${key}"()) >> [value]
}
saml2Profile.getUsername() >> "someUser"

SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yyyy")

Date current = new Date();
String formattedDate = DATE_FORMAT.format(current)

expect:
userLoginRecordRepository.findByUsernameAndLogin("someUser", formattedDate).isEmpty()
userLoginRecordRepository.count() == 0

when:
addNewUserFilter.doFilter(request, response, chain)

then:
userLoginRecordRepository.findByUsernameAndLogin("someUser", formattedDate).isPresent()
userLoginRecordRepository.count() == 1
}

def "new user created"() {
Expand Down
2 changes: 1 addition & 1 deletion testbed/authentication/shibui/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ server:
forward-headers-strategy: NATIVE
spring:
profiles:
include:
include: dev
shibui:
user-bootstrap-resource: file:/conf/users.csv
roles: ROLE_ADMIN,ROLE_NONE,ROLE_USER,ROLE_ENABLE,ROLE_PONY
Expand Down

0 comments on commit da14d5b

Please sign in to comment.