Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patches and Enhancements #1951

Merged
merged 53 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
e11dc54
Fix Test failure regarding EmailRecipientContactTest file.
kaladay Jul 12, 2024
1f2bfcb
Merge pull request #85 from TAMULib/sprint2-fix_breaking_EmailRecipie…
wwelling Jul 12, 2024
ce7785a
Sort action log by date to obtain most recent action
wwelling Jul 12, 2024
2022e5f
Fix new field value controller
wwelling Jul 12, 2024
86178a1
Update submission list filter by graduation semester
wwelling Jul 12, 2024
02f2969
Make title unique on submission list column
wwelling Jul 15, 2024
3b6ca23
Add Student Name submission list column with combined predicate
wwelling Jul 15, 2024
0bb5566
Update the submission query to afford sorting on combined predicate
wwelling Jul 15, 2024
5c769a6
Update submission list to render column for combined predicates
wwelling Jul 15, 2024
5016d6f
Sort the graduation semesters
wwelling Jul 16, 2024
1324851
Update system data loader test
wwelling Jul 17, 2024
ca2581d
Fix organization management controller tests
wwelling Jul 17, 2024
3961eee
Make user netid unique
wwelling Jul 17, 2024
20145c8
Add find by netid user repository method
wwelling Jul 17, 2024
f586e46
Optionally use netid as user unique identifier
wwelling Jul 17, 2024
1375dbf
Update credentials service to respect shibboleth configurations
wwelling Jul 18, 2024
f654a01
Update shibboleth mapping configurations
wwelling Jul 18, 2024
a92542d
Update system organization field profiles with mapped shib attribute
wwelling Jul 18, 2024
fab5b9b
Remove system out println
wwelling Jul 18, 2024
caa1ccd
Fix field profile repo tests
wwelling Jul 19, 2024
46e00bb
Merge pull request #95 from TAMULib/sprint2-91-user-credentials-shibb…
wwelling Jul 19, 2024
2491915
Add exception handler for file not found
wwelling Jul 22, 2024
c2d377a
Ignore hibernate contact info properties
wwelling Jul 22, 2024
db0d5b2
Afford sorting and filtering by last action of submission
wwelling Jul 22, 2024
0f8fc87
Make graduation semester sort method exception safe
wwelling Jul 30, 2024
1218ca7
Update role when admin email defined in properties
wwelling Jul 30, 2024
85e5528
Check submission action logs have at least one entry to avoid null po…
wwelling Jul 30, 2024
7b02834
Do not repeat yourself and use strict equality
wwelling Jul 30, 2024
fd364b6
Remove redundant string builder appends
wwelling Jul 30, 2024
490cfed
Map submission list column field values
wwelling Jul 31, 2024
cebc35b
Restore further filter by graduation semester as date
wwelling Jul 31, 2024
f4f6d00
Add filter by graduation semester as list
wwelling Jul 31, 2024
a7620e8
Coalesce named search filter group by first selected filter from subm…
wwelling Jul 31, 2024
3e9122d
Merge branch 'sprint2-53-graduation-semester-facet' of github.com:TAM…
wwelling Jul 31, 2024
083ee75
Merge branch 'sprint2-82-duplicate-submission-list-column-options' of…
wwelling Jul 31, 2024
ac37354
Merge branch 'sprint2-51-combined-column-sort' of github.com:TAMULib/…
wwelling Jul 31, 2024
ba11ea5
Merge branch 'sprint2-fix-ci-build' of github.com:TAMULib/Vireo into …
wwelling Jul 31, 2024
84f8fd2
Merge branch 'sprint2-91-user-unique-identifier' of github.com:TAMULi…
wwelling Jul 31, 2024
3cb2784
Merge branch 'sprint2-91-user-credentials-shibboleth-mapping' of gith…
wwelling Jul 31, 2024
0becbb6
Merge branch 'sprint2-81-last-action-list-view' of github.com:TAMULib…
wwelling Jul 31, 2024
55572e1
Update system data loader test for additional system submission list …
wwelling Jul 31, 2024
271cf01
Update submission list controller tests
wwelling Jul 31, 2024
b8fd6d9
Update both username and email when shibEmail changes
wwelling Jul 31, 2024
c1901d6
Null check submission list column on named search filter
wwelling Jul 31, 2024
4030aca
Fail gracefully when columnValues are not defined in response to dyna…
wwelling Jul 31, 2024
8bf2444
Remove unused imports and replace stream lambda with for loop
wwelling Jul 31, 2024
497c7d8
Switch performance logging back to debug
wwelling Aug 1, 2024
da71370
Merge pull request #102 from TAMULib/sprint2-staging-patches
wwelling Aug 1, 2024
1062d37
Increment patch release as snapshot
wwelling Aug 1, 2024
b034db0
Merge branch 'main' into 4.2.8
wwelling Aug 1, 2024
1fd1efa
Remove snapshot from version
wwelling Aug 1, 2024
b0b182d
Fix user role being reassigned on login
wwelling Aug 2, 2024
60134c4
Merge branch 'main' into 4.2.8
wwelling Sep 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>org.tdl</groupId>
<artifactId>vireo</artifactId>
<version>4.2.7</version>
<version>4.2.8</version>

<name>Vireo</name>
<description>Vireo Thesis and Dissertation Submission System</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.tdl.vireo.config.constant.ConfigurationName;
import org.tdl.vireo.model.Role;
Expand All @@ -17,80 +19,134 @@
@Service
public class VireoUserCredentialsService extends UserCredentialsService<User, UserRepo> {

private static final String NETID = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_NETID;
private static final String EMAIL = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_EMAIL;
private static final String BIRTH_YEAR = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR;
private static final String FIRST_NAME = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_FIRST_NAME;
private static final String MIDDLE_NAME = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_MIDDLE_NAME;
private static final String LAST_NAME = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_LAST_NAME;
private static final String ORCID = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_ORCID;
private static final String INSTITUTIONAL_IDENTIFIER = ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER;

private static final String SHIBBOLETH = "shibboleth";

private static final Map<String, String> shibSettings = new HashMap<>();

static {
shibSettings.put(NETID, "netid");
shibSettings.put(EMAIL, "email");
shibSettings.put(BIRTH_YEAR, "birthYear");
shibSettings.put(FIRST_NAME, "firstName");
shibSettings.put(MIDDLE_NAME, "middleName");
shibSettings.put(LAST_NAME, "lastName");
shibSettings.put(ORCID, "orcid");
shibSettings.put(INSTITUTIONAL_IDENTIFIER, "uin");
}

@Autowired
private ConfigurationRepo configurationRepo;

@Value("${app.useNetidAsIdentifier:false}")
private boolean useNetidAsIdentifier;

@Override
public synchronized User updateUserByCredentials(Credentials credentials) {
User user = userRepo.findByEmail(credentials.getEmail());
Map<String, String> shibValues = new HashMap<>();

Map<String, String> shibSettings = new HashMap<String, String>();
Map<String, String> shibValues = new HashMap<String, String>();
shibSettings.forEach((k, v) ->
shibValues.put(k, configurationRepo.getValueByNameAndType(k, SHIBBOLETH) != null ? configurationRepo.getValueByNameAndType(k, SHIBBOLETH) : v)
);

shibSettings.put(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_NETID, "netid");
shibSettings.put(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR, "birthYear");
shibSettings.put(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_MIDDLE_NAME, "middleName");
shibSettings.put(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_ORCID, "orcid");
shibSettings.put(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER, "uin");
String shibNetid = credentials.getAllCredentials().get(shibValues.get(NETID));
String shibEmail = credentials.getAllCredentials().get(shibValues.get(EMAIL));
String shibFirstName = credentials.getAllCredentials().get(shibValues.get(FIRST_NAME));
String shibMiddleName = credentials.getAllCredentials().get(shibValues.get(MIDDLE_NAME));
String shibLastName = credentials.getAllCredentials().get(shibValues.get(LAST_NAME));
String shibOrcid = credentials.getAllCredentials().get(shibValues.get(ORCID));

shibSettings.forEach((k, v) -> {
shibValues.put(k, configurationRepo.getValueByNameAndType(k, "shibboleth") != null ? configurationRepo.getValueByNameAndType(k, "shibboleth") : v);
});
User user = useNetidAsIdentifier
? userRepo.findByNetid(shibNetid)
: userRepo.findByEmail(shibEmail);

String uin = credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER));
if (uin == null) {
uin = credentials.getEmail();
}

// TODO: check to see if credentials is from basic login or shibboleth
// do not create new user from basic login credentials that have no user!
if (user == null) {

Role role = Role.ROLE_STUDENT;

if (credentials.getRole() == null) {
credentials.setRole(role.toString());
}

String shibEmail = credentials.getEmail();

for (String email : admins) {
if (email.equals(shibEmail)) {
role = Role.ROLE_ADMIN;
credentials.setRole(role.toString());
}
}

user = userRepo.create(credentials.getEmail(), credentials.getFirstName(), credentials.getLastName(), role);
user = userRepo.create(shibEmail, shibFirstName, shibLastName, role);

user.setNetid(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_NETID)));
if (credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR)) != null) {
user.setBirthYear(Integer.parseInt(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR))));
user.setNetid(shibNetid);
user.setMiddleName(shibMiddleName);
user.setOrcid(shibOrcid);

if (credentials.getAllCredentials().containsKey(shibValues.get(BIRTH_YEAR))) {
String shibBirthYearValue = credentials.getAllCredentials().get(shibValues.get(BIRTH_YEAR));
if (StringUtils.isNotEmpty(shibBirthYearValue)) {
user.setBirthYear(Integer.parseInt(shibBirthYearValue));
}
}
user.setMiddleName(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_MIDDLE_NAME)));
user.setOrcid(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_ORCID)));
user.setUsername(credentials.getEmail());

user = userRepo.save(user);
} else {
boolean isUserUpdated = false;

// TODO: update only if user properties does not match current credentials
if (StringUtils.isNotEmpty(shibNetid) && !user.getNetid().equals(shibNetid)) {
user.setNetid(shibNetid);
isUserUpdated = true;
}

if (credentials.getAllCredentials().containsKey(shibValues.get(BIRTH_YEAR))) {
String shibBirthYearValue = credentials.getAllCredentials().get(shibValues.get(BIRTH_YEAR));

//DONT OVERWRITE WITH NULL VALUE
//MORE WORK NEEDED
//user.setNetid(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER)));
if (credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR)) != null) {
user.setBirthYear(Integer.parseInt(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR))));
if (StringUtils.isNotEmpty(shibBirthYearValue)) {
int shibBirthYear = Integer.parseInt(shibBirthYearValue);
if (shibBirthYear != user.getBirthYear()) {
user.setBirthYear(shibBirthYear);
isUserUpdated = true;
}
}
}
user.setMiddleName(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_MIDDLE_NAME)));
user.setOrcid(credentials.getAllCredentials().get(shibValues.get(ConfigurationName.APPLICATION_AUTH_SHIB_ATTRIBUTE_ORCID)));
user.setUsername(credentials.getEmail());

user = userRepo.save(user);
if (StringUtils.isNotEmpty(shibFirstName) && !user.getFirstName().equals(shibFirstName)) {
user.setFirstName(shibFirstName);
isUserUpdated = true;
}

if (StringUtils.isNotEmpty(shibMiddleName) && !user.getMiddleName().equals(shibMiddleName)) {
user.setMiddleName(shibMiddleName);
isUserUpdated = true;
}

if (StringUtils.isNotEmpty(shibLastName) && !user.getLastName().equals(shibLastName)) {
user.setLastName(shibLastName);
isUserUpdated = true;
}

if (StringUtils.isNotEmpty(shibOrcid) && !user.getOrcid().equals(shibOrcid)) {
user.setOrcid(shibOrcid);
isUserUpdated = true;
}

if (StringUtils.isNotEmpty(shibEmail) && !user.getUsername().equals(shibEmail)) {
user.setEmail(shibEmail);
user.setUsername(shibEmail);
isUserUpdated = true;
}

if (isUserUpdated) {
user = userRepo.save(user);
}
}

credentials.setRole(user.getRole().toString());
credentials.setUin(user.getUsername());

credentials.setNetid(user.getNetid());
credentials.setFirstName(user.getFirstName());
credentials.setLastName(user.getLastName());

return user;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class FieldValueController {
@GetMapping("/predicate/{value}")
@PreAuthorize("hasRole('STUDENT')")
public ApiResponse getFieldValuesByPredicateValue(@PathVariable String value) {
return new ApiResponse(SUCCESS, fieldValueRepo.getAllValuesByFieldPredicateValue("submission_type"));
return new ApiResponse(SUCCESS, fieldValueRepo.getAllValuesByFieldPredicateValue(value));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
import static edu.tamu.weaver.response.ApiStatus.SUCCESS;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import edu.tamu.weaver.auth.annotation.WeaverUser;
import edu.tamu.weaver.response.ApiResponse;
import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -36,6 +35,10 @@
import org.tdl.vireo.model.repo.UserRepo;
import org.tdl.vireo.service.DefaultSubmissionListColumnService;

import edu.tamu.weaver.auth.annotation.WeaverUser;
import edu.tamu.weaver.response.ApiResponse;
import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel;

@RestController
@RequestMapping("/submission-list")
public class SubmissionListController {
Expand Down Expand Up @@ -228,7 +231,19 @@ public ApiResponse addFilterCriterion(@WeaverUser User user, @RequestBody Map<St
}

if (namedSearchFilter == null) {
namedSearchFilter = namedSearchFilterRepo.create(submissionListColumnRepo.findByTitle(criterionName));
SubmissionListColumn column = submissionListColumnRepo.findByTitle(criterionName);
for (NamedSearchFilter existingFilter : activeFilter.getNamedSearchFilters()) {
if (existingFilter.getSubmissionListColumn() != null &&
existingFilter.getSubmissionListColumn().getPredicate().equals(column.getPredicate()) &&
existingFilter.getSubmissionListColumn().getValuePath().equals(column.getValuePath())) {
namedSearchFilter = existingFilter;
break;
}
}

if (namedSearchFilter == null) {
namedSearchFilter = namedSearchFilterRepo.create(column);
}
}

namedSearchFilter.addFilter(filterCriterionRepo.create(filterValue, filterGloss));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import javax.persistence.EntityNotFoundException;

import java.nio.file.NoSuchFileException;

import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -72,6 +74,15 @@ public ApiResponse handleEntityNotFoundException(EntityNotFoundException excepti
return new ApiResponse(ERROR, exception.getMessage());
}

@ExceptionHandler(NoSuchFileException.class)
@ResponseStatus(value = HttpStatus.NOT_FOUND)
@ResponseBody
public ApiResponse handleNoSuchFileExceptionn(NoSuchFileException exception) {
logger.error(exception.getMessage());
logger.debug(exception.getMessage(), exception);
return new ApiResponse(ERROR, exception.getMessage());
}

@ExceptionHandler(MultipartException.class)
@ResponseStatus(value = HttpStatus.PAYLOAD_TOO_LARGE)
@ResponseBody
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/tdl/vireo/model/ActionLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ public class ActionLog extends ValidatingBaseEntity {
@ManyToOne(optional = true)
private User user;

@JsonView(Views.SubmissionIndividual.class)
@JsonView(Views.SubmissionList.class)
@Column(nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Calendar actionDate;

@JsonView(Views.SubmissionIndividual.class)
@JsonView(Views.SubmissionList.class)
@Column(nullable = false, columnDefinition = "text")
private String entry;

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/tdl/vireo/model/ContactInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
import javax.persistence.Entity;
import javax.persistence.OneToOne;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.tdl.vireo.model.validation.ContactInfoValidator;

import edu.tamu.weaver.validation.model.ValidatingBaseEntity;

@Entity
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class ContactInfo extends ValidatingBaseEntity {

@OneToOne(cascade = { DETACH, MERGE, REFRESH, REMOVE }, fetch = EAGER, optional = true, orphanRemoval = true)
Expand Down
Loading
Loading