Skip to content

Commit 324ab8b

Browse files
authored
Release/1.5.2 (#105)
* correct totalRecords count since it could be -1 (when firewhennotzero not set) * correctly handle unsubscribe myannotation with token (#99) * Updated email template, set pageSize=300 for records query * release 1.5.2
1 parent 01cae39 commit 324ab8b

File tree

9 files changed

+69
-15
lines changed

9 files changed

+69
-15
lines changed

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ plugins {
2828
id "com.gorylenko.gradle-git-properties" version "1.4.17"
2929
}
3030

31-
version "1.5.2-SNAPSHOT"
31+
version "1.5.2"
3232
group "au.org.ala"
3333

3434
apply plugin:"eclipse"

grails-app/controllers/au/org/ala/alerts/UnsubscribeController.groovy

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ class UnsubscribeController {
77
static allowedMethods = [index: "GET", unsubscribe: "POST"]
88

99
UserService userService
10+
NotificationService notificationService
11+
QueryService queryService
1012

1113
def index() {
1214
User loggedInUser = userService.getUser()
@@ -37,10 +39,17 @@ class UnsubscribeController {
3739
response.sendError(HttpStatus.SC_FORBIDDEN)
3840
} else {
3941
if (userAndNotifications.notifications) {
42+
// delete notifications and update user
4043
Notification.deleteAll(userAndNotifications.notifications)
4144
userAndNotifications.user.notifications?.removeAll(userAndNotifications.notifications)
4245
userAndNotifications.user.save(flush: true)
4346

47+
// for my annotation, we also need to delete the query and query result
48+
String myAnnotationQueryPath = queryService.constructMyAnnotationQueryPath(userAndNotifications.user.userId)
49+
if (userAndNotifications.notifications.any { it.query.queryPath == myAnnotationQueryPath }) {
50+
notificationService.deleteMyAnnotation(userAndNotifications.user)
51+
}
52+
4453
render view: "unsubscribed"
4554
}
4655
}

grails-app/i18n/messages.properties

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ alert.title=Email alert from {0}
7171
alert.details=View details
7272
alert.manage=Manage your email subscriptions
7373
biocache.view.list=View a list of all the added/changed records
74+
biocache.view.myannotation.list=View the list of records you have annotated
7475
biocache.disable.this=Disable this alert or manage your alerts
7576
biocache.settings.frequency=Your current settings are to receive alert emails {0}.
7677
biocache.occurrences.record.update=Occurrence records update

grails-app/services/au/org/ala/alerts/DiffService.groovy

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class DiffService {
4040
if (current != null && previous != null) {
4141

4242
try {
43-
if (!queryService.isUserSpecific(query)) {
43+
if (!queryService.isMyAnnotation(query)) {
4444
def ids1 = JsonPath.read(current, query.recordJsonPath + "." + query.idJsonPath)
4545
if (!isCollectionOrArray(ids1)) {
4646
ids1 = [ids1]
@@ -135,7 +135,7 @@ class DiffService {
135135

136136
if(!last.startsWith("<") && !previous.startsWith("<")) {
137137
// Don't try and process 401, 301, 500, etc., responses that contain HTML
138-
if (!queryService.isUserSpecific(queryResult.query)) {
138+
if (!queryService.isMyAnnotation(queryResult.query)) {
139139
List<String> ids1 = JsonPath.read(last, queryResult.query.recordJsonPath + "." + queryResult.query.idJsonPath)
140140
List<String> ids2 = JsonPath.read(previous, queryResult.query.recordJsonPath + "." + queryResult.query.idJsonPath)
141141
List<String> diff = ids1.findAll { !ids2.contains(it) }

grails-app/services/au/org/ala/alerts/EmailService.groovy

+3-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class EmailService {
8787
title : query.name,
8888
message : query.updateMessage,
8989
moreInfo : queryResult.queryUrlUIUsed,
90+
listcode : queryService.isMyAnnotation(query) ? "biocache.view.myannotation.list" : "biocache.view.list",
9091
query : query,
9192
stopNotification: grailsApplication.config.security.cas.appServerName + grailsApplication.config.security.cas.contextPath + '/notification/myAlerts',
9293
frequency : frequency,
@@ -137,10 +138,11 @@ class EmailService {
137138
message: query.updateMessage,
138139
query: query,
139140
moreInfo: queryResult.queryUrlUIUsed,
141+
listcode: queryService.isMyAnnotation(query) ? "biocache.view.myannotation.list" : "biocache.view.list",
140142
stopNotification: urlPrefix + '/notification/myAlerts',
141143
records: records,
142144
frequency: messageSource.getMessage('frequency.' + frequency, null, siteLocale),
143-
totalRecords: totalRecords,
145+
totalRecords: (totalRecords >= 0 ? totalRecords : records.size()),
144146
unsubscribeAll: urlPrefix + "/unsubscribe?token=" + userUnsubToken,
145147
unsubscribeOne: urlPrefix + "/unsubscribe?token=" + notificationUnsubToken
146148
])

grails-app/services/au/org/ala/alerts/NotificationService.groovy

+3-3
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ class NotificationService {
273273
}
274274

275275
private def processQueryReturnedJson(Query query, String json) {
276-
if (!queryService.isUserSpecific(query) || !queryService.getUserId(query)) {
276+
if (!queryService.isMyAnnotation(query) || !queryService.getUserId(query)) {
277277
return json
278278
}
279279

@@ -587,8 +587,8 @@ class NotificationService {
587587
}
588588

589589
def deleteMyAnnotation(User user) {
590-
Query myAnnotationQuery = queryService.createMyAnnotationQuery(user?.userId)
591-
Query retrievedQuery = Query.findByBaseUrlAndQueryPath(myAnnotationQuery.baseUrl, myAnnotationQuery.queryPath)
590+
String myAnnotationQueryPath = queryService.constructMyAnnotationQueryPath(user?.userId)
591+
Query retrievedQuery = Query.findByQueryPath(myAnnotationQueryPath)
592592

593593
if (retrievedQuery != null) {
594594
// delete the notification

grails-app/services/au/org/ala/alerts/QueryService.groovy

+9-5
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,20 @@ class QueryService {
3333
}
3434

3535
Boolean checkChangeByDiff(Query query) {
36-
!hasAFireProperty(query) && (query.idJsonPath || isUserSpecific(query))
36+
!hasAFireProperty(query) && (query.idJsonPath || isMyAnnotation(query))
3737
}
3838

3939
Boolean hasAFireProperty(Query query){
4040
query.propertyPaths.any {it.fireWhenChange || it.fireWhenNotZero}
4141
}
4242

43-
Boolean isUserSpecific(Query query) {
43+
Boolean isMyAnnotation(Query query) {
4444
// Currently only 'my annotation' alert is user specific (among all non-custom queries)
4545
query.name.startsWith(messageSource.getMessage("query.myannotations.title", null, siteLocale))
4646
}
4747

4848
String getUserId(Query query) {
49-
if (!isUserSpecific(query)) return null
49+
if (!isMyAnnotation(query)) return null
5050
String queryPath = query.queryPath
5151
queryPath.substring(queryPath.indexOf('assertion_user_id:') + 'assertion_user_id:'.length(), queryPath.indexOf('&dir=desc'))
5252
}
@@ -265,10 +265,14 @@ class QueryService {
265265
name: messageSource.getMessage("query.myannotations.title", null, siteLocale),
266266
updateMessage: messageSource.getMessage("myannotations.update.message", null, siteLocale),
267267
description: messageSource.getMessage("query.myannotations.descr", null, siteLocale),
268-
queryPath: '/occurrences/search?fq=assertion_user_id:' + userId + '&dir=desc&facets=basis_of_record',
269-
queryPathForUI: '/occurrences/search?fq=assertion_user_id:' + userId + '&dir=desc&facets=basis_of_record',
268+
queryPath: constructMyAnnotationQueryPath(userId),
269+
queryPathForUI: '/occurrences/search?fq=assertion_user_id:' + userId + '&dir=desc',
270270
emailTemplate: '/email/biocache',
271271
recordJsonPath: '\$.occurrences[*]',
272272
])
273273
}
274+
275+
String constructMyAnnotationQueryPath(String userId) {
276+
'/occurrences/search?fq=assertion_user_id:' + userId + '&dir=desc&pageSize=300'
277+
}
274278
}

grails-app/views/email/biocache.gsp

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
<p>
88
<g:message code="${message}" default="${message}" args="${[totalRecords]}"/>
99
</p>
10-
<p><a href="${moreInfo}"><g:message code="biocache.view.list" /></a></p>
11-
10+
<p><a href="${moreInfo}"><g:message code="${listcode ? listcode : "biocache.view.list"}"/></a></p>
1211
<style type="text/css">
1312
body { font-family:Arial; }
1413
table { border-collapse: collapse; border: 1px solid #CCC; padding:2px; }

src/test/groovy/au/org/ala/alerts/UnsubscribeControllerSpec.groovy

+40-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import org.apache.http.HttpStatus
66
import spock.lang.Specification
77

88
@TestFor(UnsubscribeController)
9-
@Mock([Notification, User, Query])
9+
@Mock([Notification, User, Query, QueryResult])
1010
class UnsubscribeControllerSpec extends Specification {
1111

1212
def setup() {
1313
controller.userService = Mock(UserService)
14+
controller.queryService = Mock(QueryService)
15+
controller.notificationService = Mock(NotificationService)
1416
}
1517

1618
def "index() should return a HTTP 400 (BAD_REQUEST) if there is no logged in user and no token"() {
@@ -249,6 +251,7 @@ class UnsubscribeControllerSpec extends Specification {
249251
def "unsubscribe() should delete all the user's notifications if the token matches the token for a user with notifications"() {
250252
setup:
251253
controller.userService.getUser() >> null
254+
controller.queryService.createMyAnnotationQuery(_ as String) >> new Query([name: 'emptyquery'])
252255
Query query1 = newQuery("query1")
253256
Query query2 = newQuery("query2")
254257
User user1 = new User(userId: "user1", email: "fred@bla.com")
@@ -282,9 +285,44 @@ class UnsubscribeControllerSpec extends Specification {
282285
Notification.count() == 1
283286
}
284287

288+
def "unsubscribe() should delete my annotaions alert if the token matches the token for a user with notifications"() {
289+
setup:
290+
User user = new User(userId: "userid", email: "fred@bla.com", frequency: new Frequency([name: 'hourly']))
291+
Query query = new Query([
292+
name: 'testquery',
293+
queryPath: '/occurrences/search?fq=assertion_user_id:' + 'userid' + '&dir=desc&facets=basis_of_record',
294+
updateMessage: 'updateMessage',
295+
baseUrl: 'baseUrl',
296+
baseUrlForUI: 'baseUrlForUI',
297+
resourceName: 'resourceName',
298+
queryPathForUI: 'queryPathForUI'
299+
])
300+
301+
controller.userService.getUser() >> null
302+
controller.queryService.constructMyAnnotationQueryPath(_ as String) >> '/occurrences/search?fq=assertion_user_id:' + user.userId + '&dir=desc&facets=basis_of_record'
303+
304+
user.save(failOnError: true, flush: true)
305+
query.save(failOnError: true, flush: true)
306+
Notification notification = new Notification(user: user, query: query)
307+
notification.save(failOnError: true, flush: true)
308+
QueryResult queryResult = new QueryResult([query: query, frequency: user.frequency])
309+
queryResult.save(failOnError: true, flush: true)
310+
311+
when:
312+
params.token = notification.unsubscribeToken
313+
request.method = 'POST'
314+
controller.unsubscribe()
315+
316+
then:
317+
log.info "token = ${params.token}"
318+
1 * controller.notificationService.deleteMyAnnotation(user)
319+
response.status == HttpStatus.SC_OK
320+
}
321+
285322
def "unsubscribe() should delete only 1 notification if the token matches the token for a notification"() {
286323
setup:
287324
controller.userService.getUser() >> null
325+
controller.queryService.createMyAnnotationQuery(_ as String) >> new Query([name: 'emptyquery'])
288326
Query query1 = newQuery("query1")
289327
Query query2 = newQuery("query2")
290328
User user = new User(userId: "user1", email: "fred@bla.com")
@@ -323,6 +361,7 @@ class UnsubscribeControllerSpec extends Specification {
323361
user.addToNotifications(notification2)
324362
user.save(failOnError: true, flush: true)
325363
controller.userService.getUser() >> user
364+
controller.queryService.createMyAnnotationQuery(_ as String) >> new Query([name: 'emptyquery'])
326365

327366
when:
328367
params.token = notification1.unsubscribeToken

0 commit comments

Comments
 (0)