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

Add mailing list and cognito affiliation report #176

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions userdetails-cognito/grails-app/conf/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ environments:
cas:
appServerName: "https://auth.ala.org.au"

attributes:
affiliations:
enabled: true
attribute-name: 'custom:affiliation'

cognito:
mapping:
email: 'email'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class CognitoUserService implements IUserService<UserRecord, UserPropertyRecord,

EmailService emailService
TokenService tokenService
LocationService locationService

AWSCognitoIdentityProvider cognitoIdp
String poolId
Expand Down Expand Up @@ -461,7 +462,54 @@ class CognitoUserService implements IUserService<UserRecord, UserPropertyRecord,

@Override
List<String[]> countByProfileAttribute(String s, Date date, Locale locale) {
return null
def token
def counts = [:]
def results = cognitoIdp.listUsers(new ListUsersRequest().withUserPoolId(poolId))

while (results) {
def users = results.getUsers()
token = results.getPaginationToken()

users.each {
def value = it.attributes.find { it.name == "custom.$s" }?.value
counts[value ?: ''] = ((counts[value ?: '']) ?: 0)++
}

results = token ? cognitoIdp.listUsers(new ListUsersRequest().withUserPoolId(poolId).withPaginationToken(token)) : null
}
def affiliations = locationService.affiliationSurvey(locale)

return counts.collect { [affiliations[it.key] ?: it.key, it.value.toString()].toArray(new String[0]) }
}

@Override
List<String[]> emailList(Date startDate, Date endDate) {
// Initialize list to hold all filtered users across paginated calls
def users = new ArrayList<UserType>()

// Pagination logic
def token = null
while (true) {
def response
if (token) {
response = cognitoIdp.listUsers(new ListUsersRequest().withUserPoolId(poolId).withPaginationToken(token))
} else {
response = cognitoIdp.listUsers(new ListUsersRequest().withUserPoolId(poolId))
}

// Filter users based on creation or last modified date and add to filtered_users list
users.addAll(response.getUsers().findAll {
(it.userCreateDate.after(startDate) && it.userCreateDate.before(endDate)) ||
(it.userLastModifiedDate.after(startDate) && it.userLastModifiedDate.before(endDate))
})

token = response.paginationToken
if (!token) {
break
}
}

return users.collect { [it.attributes.find { it.name == 'email' }.value, it.userCreateDate, it.userLastModifiedDate].toArray(new String[0]) }
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,30 @@ class GormUserService implements IUserService<User, UserProperty, Role, UserRole
}
}

@Override
List<String[]> emailList(Date startDate, Date endDate) {
def results = User.withCriteria {
or {
and {
gt 'dateCreated' startDate
lt 'dateCreated' endDate
}
and {
gt 'lastUpdated' startDate
lt 'lastUpdated' endDate
}
}
projections {
property 'email'
property 'dateCreated'
property 'lastUpdated'
}
}
return results.collect {
[it[0], it[1], it[2]].toArray(new String[0])
}
}

@Override
Collection<Role> listRoles() {
Role.list()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.opencsv.CSVWriterBuilder
import com.opencsv.RFC4180ParserBuilder
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.multipart.MultipartHttpServletRequest

Expand All @@ -33,6 +34,9 @@ class AdminController {
def profileService
def authorisedSystemService

@Value('${attributes.affiliations.attribute-name:affiliation}')
String affiliationAttribute = 'affiliation'

@Autowired
@Qualifier('userService')
IUserService userService
Expand Down Expand Up @@ -153,13 +157,28 @@ class AdminController {
}

def surveyResults() {
def results = userService.countByProfileAttribute('affiliation', null, request.locale)
def results = userService.countByProfileAttribute(affiliationAttribute, null, request.locale)
respondWithCsv(results, "user-survey-${new Date()}.csv")
}

def emailListForm() {

}

def emailList() {
def startDate = params.date('start_date')
def endDate = params.date('end_date')
def results = userService.emailList(startDate, endDate)
respondWithCsv(results, "email-list-$startDate-to-${endDate}.csv")
}

private def respondWithCsv(List<String[]> results, String filename) {
def csvWriter = new CSVWriterBuilder(response.writer)
.withParser(new RFC4180ParserBuilder().build())
.build()
response.status = 200
response.contentType = 'text/csv'
response.setHeader('Content-Disposition', "attachment; filename=user-survey-${new Date()}.csv")
response.setHeader('Content-Disposition', "attachment; filename=$filename")
csvWriter.writeAll(results)
csvWriter.flush()
}
Expand Down
49 changes: 49 additions & 0 deletions userdetails-plugin/grails-app/views/admin/emailListForm.gsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
%{--
- Copyright (C) 2023 Atlas of Living Australia
- All Rights Reserved.
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
--}%
<!doctype html>
<html>
<head>
<meta name="layout" content="${grailsApplication.config.getProperty('skin.layout')}"/>
<meta name="section" content="home"/>
<g:set var="title">Export Users to CSV</g:set>
<title>${title} | ${grailsApplication.config.getProperty('skin.orgNameLong')}</title>
<asset:stylesheet src="userdetails.css" />
</head>
<body>
<g:if test="${flash.message}">
<div class="alert alert-danger">
${flash.message}
</div>
</g:if>

<div class="row">
<div class="col-md-12" id="page-body" role="main">
<g:form name="emailList" action="emailList" method="get" class="form-horizontal">
<div class="form-group">
<label for="start_date">Start Date</label>
<input type="date" class="form-control" id="start_date" >
%{-- <g:datePicker name="start_date" value="${new Date()}"/>--}%
</div>
<div class="form-group">
<label for="end_date">End Date</label>
<input type="date" class="form-control" id="end_date" >
%{-- <g:datePicker name="end_date" value="${new Date()}"/>--}%
</div>
<button type="submit" class="btn btn-default">Submit</button>
</g:form>
</div>
</div>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ interface IUserService<U extends IUser<? extends Serializable>, P extends IUserP

List<String[]> countByProfileAttribute(String s, Date date, Locale locale)

List<String[]> emailList(Date startDate, Date endDate)

/***
* This method can be used to get users by username
* The following paging params are always supported:
Expand Down