Skip to content

Commit

Permalink
Merge pull request #1011 from AtlasOfLivingAustralia/feature/issue1007
Browse files Browse the repository at this point in the history
#1007 org method get all collections; requires database update
  • Loading branch information
chrisala authored Sep 13, 2024
2 parents e20ce93 + 02ac134 commit a7c6824
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 5 deletions.
18 changes: 18 additions & 0 deletions grails-app/controllers/au/org/ala/ecodata/ParatooController.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ class ParatooController {
respond projects: paratooService.userProjects(userService.currentUserDetails.userId)
}

@GET
@SecurityRequirements([@SecurityRequirement(name = "jwt"), @SecurityRequirement(name = "openIdConnect"), @SecurityRequirement(name = "oauth")])
@Path("/get-all-collections")
@Operation(
method = "GET",
summary = "Gets the list of all org minted uuids submitted by an authenticated user.",
description = "Gets the list of all org minted uuids submitted by an authenticated user.",
responses = [
@ApiResponse(responseCode = "200", description = "Returns the list of all org minted uuids submitted by the user.", content = @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = Map.class)))),
@ApiResponse(responseCode = "403", description = "Forbidden"),
@ApiResponse(responseCode = "404", description = "Not found")
],
tags = "Org Interface"
)
def userCollections() {
respond collections: paratooService.userCollections(userService.currentUserDetails.userId)
}

@SkipApiKeyCheck
@POST
@Path("/validate-token")
Expand Down
6 changes: 6 additions & 0 deletions grails-app/controllers/au/org/ala/ecodata/UrlMappings.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ class UrlMappings {
action = 'hasWriteAccess'
}

"/ws/paratoo/get-all-collections" {
controller = 'paratoo'
action = [GET:'userCollections', OPTIONS:'options']
}


"/ws/paratoo/validate-token" {
controller = 'paratoo'
action = [POST:'validateToken', OPTIONS:'options']
Expand Down
6 changes: 1 addition & 5 deletions grails-app/domain/au/org/ala/ecodata/Activity.groovy
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package au.org.ala.ecodata

import au.org.ala.ecodata.graphql.mappers.ActivityGraphQLMapper
import grails.util.Holders
import graphql.schema.DataFetcher
import graphql.schema.DataFetchingEnvironment
import org.bson.types.ObjectId
import org.grails.gorm.graphql.entity.dsl.GraphQLMapping

/**
* Currently this holds both activities and assessments.
*/
Expand Down Expand Up @@ -44,6 +39,7 @@ class Activity {
}

static hasMany = [externalIds:ExternalId]
static embedded = ['externalIds']

ObjectId id
String activityId
Expand Down
17 changes: 17 additions & 0 deletions grails-app/services/au/org/ala/ecodata/ParatooService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,23 @@ class ParatooService {
projects.findAll { it.protocols }
}

List<String> userCollections (String userId) {
Set<String> collectionIds = new HashSet<String>()
List<Activity> activities = Activity.createCriteria().list {
eq('userId', userId)
ne('status', Status.DELETED)
eq('externalIds.idType', ExternalId.IdType.MONITOR_MINTED_COLLECTION_ID)
}

activities?.each { Activity activity ->
ExternalId externalId = activity.externalIds?.find { it.idType == ExternalId.IdType.MONITOR_MINTED_COLLECTION_ID }
if (externalId?.externalId)
collectionIds.add(externalId.externalId)
}

collectionIds.toList()
}

private List findProjectProtocols(ParatooProject project) {
log.debug "Finding protocols for ${project.id} ${project.name}"
List<ActivityForm> protocols = []
Expand Down
26 changes: 26 additions & 0 deletions scripts/releases/5.0/updateMissingActivityExternalIds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
load('../../utils/audit.js');
let adminUserId = 'system';
let count = 0;
db.activity.find({"description" : "Activity submitted by monitor"}).forEach(function(activity) {
if (!activity.externalIds || activity.externalIds.length == 0) {
var project = db.project.findOne({projectId: activity.projectId});
if (project && project.custom && project.custom.dataSets) {
var dataset = project.custom.dataSets.find(function(dataset) {
return dataset.activityId == activity.activityId;
});

if (dataset) {
activity.externalIds = [{idType: "MONITOR_MINTED_COLLECTION_ID", externalId: dataset.dataSetId}];
db.activity.replaceOne({activityId: activity.activityId}, activity);
audit(activity, activity.activityId, 'au.org.ala.ecodata.Activity', adminUserId);
print(`Updated activity: + ${activity.activityId} + with dataSetId: ${dataset.dataSetId}`);
count ++;
}
else {
print(`Activity: ${activity.activityId} does not have a dataset`);
}
}
}
});

print(`Updated ${count} activities`);
88 changes: 88 additions & 0 deletions scripts/utils/audit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/** Inserts a document into the auditMessage collection */
function audit(entity, entityId, type, userId, projectId, eventType) {
var auditMessage = {
date: ISODate(),
entity: entity,
eventType: eventType || 'Update',
entityType: type,
entityId: entityId,
userId: userId
};
if (entity.projectId || projectId) {
auditMessage.projectId = (entity.projectId || projectId);
}
db.auditMessage.insertOne(auditMessage);
}

/** Updates the name and dates for a supplied report */
function updateReportDetails(reportId, name, fromDate, toDate, userId, submissionDate, description) {
var now = ISODate();
var report = db.report.findOne({reportId:reportId});
report.fromDate = fromDate;
report.toDate = toDate;
report.lastUpdated = now;
report.name = name;
report.description = description || name;
report.submissionDate = submissionDate || toDate;

db.report.replaceOne({_id: report._id}, report);
audit(report, report.reportId, 'au.org.ala.ecodata.Report', userId);

updateActivity(report, userId);
}

/** Updates an activity to match the changes made to a supplied report and audits the change */
function updateActivity(report, userId) {
var activity = db.activity.findOne({activityId:report.activityId});
activity.plannedEndDate = report.toDate;
activity.endDate = report.toDate;
activity.plannedStartDate = report.fromDate;
activity.startDate = report.fromDate;
activity.description = report.name;

activity.lastUpdated = report.lastUpdated;

db.activity.replaceOne({_id:activity._id}, activity);
audit(activity, activity.activityId, 'au.org.ala.ecodata.Activity', userId);
}

function addProjectPermission(userId, projectId, accessLevel, adminUserId) {
addPermission(userId, projectId, accessLevel, 'au.org.ala.ecodata.Project', adminUserId);
}

function addPermission(userId, entityId, accessLevel, entityType, adminUserId) {
var userPermission = {
userId:userId,
entityType:entityType,
entityId:entityId,
accessLevel:accessLevel
};
if (db.userPermission.findOne({userId:userId, entityId:entityId})) {
print("Not adding permission for user: "+userId+" to entity: "+entityId+", permission already exists");
}
else {
print("Adding permission for user: "+userId+" to entity: "+entityId+" of type: "+entityType);
db.userPermission.insert(userPermission);
var id = db.userPermission.findOne({userId:userId, entityId:entityId})._id;
audit(userPermission, id, 'au.org.ala.ecodata.UserPermission', adminUserId, entityId);
}

}


function restoreRemovedPermissions(userId, removalDate, adminUserId) {
let messages = db.auditMessage.find(
{'entity.userId':userId,
userId:'<anon>',
entityType:'au.org.ala.ecodata.UserPermission',
date:{$gt:ISODate(removalDate)},
eventType:"Delete"
});
while (messages.hasNext()) {
let message = messages.next();
let permission = message.entity;

addProjectPermission(userId, permission.entityId, permission.accessLevel, permission.entityType, adminUserId);

}
}
46 changes: 46 additions & 0 deletions src/test/groovy/au/org/ala/ecodata/ParatooServiceSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
UserPermission.findAll().each { it.delete() }
Program.findAll().each { it.delete() }
Site.findAll().each { it.delete() }
Activity.findAll().each { it.delete() }
}

def cleanup() {
Expand Down Expand Up @@ -666,6 +667,41 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
activityForm.externalIds = [new ExternalId(externalId: "guid-4", idType: ExternalId.IdType.MONITOR_PROTOCOL_GUID)]
activityForm.save(failOnError: true, flush: true)

def activity = new Activity(
activityId: UUID.randomUUID().toString(),
type : activityForm.name,
formVersion : activityForm.formVersion,
description : "Activity submitted by monitor",
projectId : "p1",
publicationStatus: PublicationStatus.PUBLISHED,
siteId : "s2",
startDate : new Date(),
endDate : new Date(),
plannedStartDate : new Date(),
plannedEndDate : new Date(),
progress : Activity.FINISHED,
userId : 'user1'
)
activity.externalIds = [new ExternalId(idType: ExternalId.IdType.MONITOR_MINTED_COLLECTION_ID, externalId: 'abc')]
activity.save(failOnError: true, flush: true)

activity = new Activity (
activityId: UUID.randomUUID().toString(),
type : activityForm.name,
formVersion : activityForm.formVersion,
description : "Activity submitted by monitor",
projectId : "p2",
publicationStatus: PublicationStatus.PUBLISHED,
siteId : "s1",
startDate : new Date(),
endDate : new Date(),
plannedStartDate : new Date(),
plannedEndDate : new Date(),
progress : Activity.FINISHED,
userId : 'user1'
)
activity.externalIds = [new ExternalId(idType: ExternalId.IdType.MONITOR_MINTED_COLLECTION_ID, externalId: 'def')]
activity.save(failOnError: true, flush: true)
}

void "capitalizeModelName should convert hyphenated name to capitalised name"() {
Expand Down Expand Up @@ -1682,6 +1718,16 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
"DO NOT ADD" | true
}

void "userCollection should return orgMintedId/dataSetId" (userId, expectedResult) {
expect:
service.userCollections(userId) == expectedResult

where:
userId | expectedResult
"user1" | ['abc', 'def']
"user2" | []
}

private Map getNormalDefinition() {
def input = """
{
Expand Down

0 comments on commit a7c6824

Please sign in to comment.