Skip to content

Commit

Permalink
Rebase with develop
Browse files Browse the repository at this point in the history
  • Loading branch information
yasima-csiro committed Dec 19, 2022
1 parent 4a6416d commit 644e19c
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import au.org.ala.users.RoleRecord
import au.org.ala.users.UserPropertyRecord
import au.org.ala.users.UserRecord
import au.org.ala.users.UserRoleRecord
import au.org.ala.ws.security.JwtProperties
import au.org.ala.ws.tokens.TokenService
import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProvider
import com.amazonaws.services.cognitoidp.model.AddCustomAttributesRequest
import com.amazonaws.services.cognitoidp.model.AdminCreateUserRequest
import com.amazonaws.services.cognitoidp.model.AdminDisableUserRequest
import com.amazonaws.services.cognitoidp.model.AdminEnableUserRequest
Expand All @@ -20,24 +22,29 @@ import com.amazonaws.services.cognitoidp.model.AdminUpdateUserAttributesRequest
import com.amazonaws.services.cognitoidp.model.AssociateSoftwareTokenRequest
import com.amazonaws.services.cognitoidp.model.AttributeType
import com.amazonaws.services.cognitoidp.model.ConfirmForgotPasswordRequest
import com.amazonaws.services.cognitoidp.model.DescribeUserPoolRequest
import com.amazonaws.services.cognitoidp.model.GetUserRequest
import com.amazonaws.services.cognitoidp.model.GetUserResult
import com.amazonaws.services.cognitoidp.model.ListGroupsRequest
import com.amazonaws.services.cognitoidp.model.ListGroupsResult
import com.amazonaws.services.cognitoidp.model.ListUsersInGroupRequest
import com.amazonaws.services.cognitoidp.model.ListUsersRequest
import com.amazonaws.services.cognitoidp.model.ListUsersResult
import com.amazonaws.services.cognitoidp.model.SchemaAttributeType
import com.amazonaws.services.cognitoidp.model.UpdateUserAttributesRequest
import com.amazonaws.services.cognitoidp.model.UpdateUserAttributesResult
import com.amazonaws.services.cognitoidp.model.SoftwareTokenMfaSettingsType
import com.amazonaws.services.cognitoidp.model.UserNotFoundException
import com.amazonaws.services.cognitoidp.model.UserType
import com.nimbusds.oauth2.sdk.token.AccessToken
import com.amazonaws.services.cognitoidp.model.VerifySoftwareTokenRequest
import grails.converters.JSON
import grails.web.servlet.mvc.GrailsParameterMap
import groovy.util.logging.Slf4j
import org.apache.commons.codec.digest.HmacAlgorithms
import org.apache.commons.codec.digest.HmacUtils
import org.apache.commons.lang3.NotImplementedException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value

import java.util.stream.Stream
Expand All @@ -55,6 +62,8 @@ class CognitoUserService implements IUserService {

AWSCognitoIdentityProvider cognitoIdp
String poolId
@Autowired
JwtProperties jwtProperties

@Value('${attributes.affiliations.enabled:false}')
boolean affiliationsEnabled = false
Expand Down Expand Up @@ -210,7 +219,7 @@ class CognitoUserService implements IUserService {
activated: userType.userStatus == "CONFIRMED", locked: !userType.enabled,
firstName: attributes['given_name'], lastName: attributes['family_name'],
email: attributes['email'], userName: userType.username,
userRoles: attributes['custom:roles']?.split(','), userProperties: userProperties)
userRoles: attributes['custom:role']?.split(','), userProperties: userProperties)
}
.toList()
}
Expand Down Expand Up @@ -325,34 +334,49 @@ class CognitoUserService implements IUserService {
@Override
UserRecord getUserById(String userId) {

def userResponse
def userAttributes

if (userId == null || userId == "") {
// Problem. This might mean an expired cookie, or it might mean that this service is not in the authorised system list
log.debug("Attempt to get current user returned null. This might indicating that this machine is not the authorised system list")
return null
}

try {
AdminGetUserResult userResponse = cognitoIdp.adminGetUser(new AdminGetUserRequest().withUsername(userId).withUserPoolId(poolId))
if (userId.isLong()) {
ListUsersRequest request = new ListUsersRequest()
.withUserPoolId(poolId)
.withFilter("name=\"${userId}\"")
ListUsersResult response = cognitoIdp.listUsers(request)
userResponse = response.users.first()
userAttributes = userResponse.attributes
}

Map<String, String> attributes = userResponse.userAttributes.collectEntries { [ (it.name): it.value ] }
Collection<UserPropertyRecord> userProperties = userResponse.userAttributes
.findAll {!mainAttrs.contains(it.name) }
.collect {
new UserPropertyRecord(name: it.name, value: it.value)
}
userProperties.add(new UserPropertyRecord(name: "enableMFA", value: userResponse.getUserMFASettingList()?.size() > 0))
else {
userResponse = cognitoIdp.adminGetUser(new AdminGetUserRequest().withUsername(userId).withUserPoolId(poolId))
userAttributes = userResponse.userAttributes
}

Map<String, String> attributes = userAttributes.collectEntries { [ (it.name): it.value ] }
Collection<UserPropertyRecord> userProperties = userAttributes
.findAll {!mainAttrs.contains(it.name) }
.collect {
new UserPropertyRecord(name: it.name, value: it.value)
}
userProperties.add(new UserPropertyRecord(name: "enableMFA", value: userResponse.getUserMFASettingList()?.size() > 0))

UserRecord user = new UserRecord(
userId: userResponse.username,
dateCreated: userResponse.userCreateDate, lastUpdated: userResponse.userLastModifiedDate,
activated: userResponse.userStatus == "CONFIRMED", locked: !userResponse.enabled,
firstName: attributes['given_name'], lastName: attributes['family_name'],
email: attributes['email'], userName: userResponse.username,
userRoles: attributes['custom:roles']?.split(','), userProperties: userProperties
)

return user
UserRecord user = new UserRecord(
userId: userResponse.username,
dateCreated: userResponse.userCreateDate, lastUpdated: userResponse.userLastModifiedDate,
activated: userResponse.userStatus == "CONFIRMED", locked: !userResponse.enabled,
firstName: attributes['given_name'], lastName: attributes['family_name'],
email: attributes['email'], userName: userResponse.username,
userRoles: attributes['custom:role']?.split(','), userProperties: userProperties
)

return user
}
catch (UserNotFoundException e) {
return null
Expand Down Expand Up @@ -415,7 +439,12 @@ class CognitoUserService implements IUserService {

@Override
Map getUsersCounts(Locale locale) {
return null
Map jsonMap = [:]
DescribeUserPoolRequest request = new DescribeUserPoolRequest().withUserPoolId(poolId)
def response = cognitoIdp.describeUserPool(request)
jsonMap.totalUsers = response.userPool.estimatedNumberOfUsers
log.debug "jsonMap = ${jsonMap as JSON}"
jsonMap
}

@Override
Expand Down Expand Up @@ -505,11 +534,6 @@ class CognitoUserService implements IUserService {
throw new NotImplementedException()
}

@Override
UserRecord findByUserNameOrEmail(String username) {
throw new NotImplementedException()
}

@Override
List<String[]> listNamesAndEmails() {
throw new NotImplementedException()
Expand Down Expand Up @@ -628,4 +652,141 @@ class CognitoUserService implements IUserService {
}
}

@Override
UserRecord findByUserNameOrEmail(String userName) {
return listUsers(userName, null, 1)?[0]
}

@Override
def findUsersByRole(String roleName, List numberIds, List userIds, String pageOrToken) {
ListUsersInGroupRequest request = new ListUsersInGroupRequest().withUserPoolId(poolId).withLimit(10)
if(pageOrToken) {
request.nextToken = pageOrToken
}
request.groupName = roleName.split(jwtProperties.getRolePrefix())[1].toLowerCase()
//TODO: filter using userid and email
//following CustomQueryParameter is not working
//request.putCustomQueryParameter("name", "43954")
def response = cognitoIdp.listUsersInGroup(request)
def users = response.users.stream()

def results = users.map { userType ->

Map<String, String> attributes = userType.attributes.collectEntries { [ (it.name): it.value ] }
Collection<UserPropertyRecord> userProperties = userType.attributes
.findAll {!mainAttrs.contains(it.name) }
.collect {
new UserPropertyRecord(name: it.name, value: it.value)
}

new UserRecord(
userId: userType.username,
dateCreated: userType.userCreateDate, lastUpdated: userType.userLastModifiedDate,
activated: userType.userStatus == "CONFIRMED", locked: !userType.enabled,
firstName: attributes['given_name'], lastName: attributes['family_name'],
email: attributes['email'], userName: userType.username,
userRoles: attributes['custom:role']?.split(','), userProperties: userProperties)
}.toList()

return [results: results, nextToken: response.nextToken]
}

def getUserDetailsFromIdList(List idList){

List<UserType> users = []

ListUsersRequest request = new ListUsersRequest()
.withUserPoolId(poolId)
.withLimit(1)

idList.forEach{
if(it instanceof Number) {
request.withFilter("name = \"${it.toString()}\"")
}
else{
request.withFilter("username = \"${it.toString()}\"")
}
def response = cognitoIdp.listUsers(request)
users.addAll(response.users)
}

return users.stream().map { userType ->

Map<String, String> attributes = userType.attributes.collectEntries { [ (it.name): it.value ] }
Collection<UserPropertyRecord> userProperties = userType.attributes
.findAll {!mainAttrs.contains(it.name) }
.collect {
new UserPropertyRecord(name: it.name, value: it.value)
}

new UserRecord(
userId: attributes['name'] ?: userType.username,
dateCreated: userType.userCreateDate, lastUpdated: userType.userLastModifiedDate,
activated: userType.userStatus == "CONFIRMED", locked: !userType.enabled,
firstName: attributes['given_name'], lastName: attributes['family_name'],
email: attributes['email'], userName: userType.username,
userRoles: attributes['custom:role']?.split(','), userProperties: userProperties)
}.toList()
}

def searchByUsernameOrEmail(String q, int max){
return [results: listUsers(q, null, max)]
}

def saveCustomUserProperty(UserRecord user, String name, String value) {

DescribeUserPoolRequest request = new DescribeUserPoolRequest().withUserPoolId(poolId)
def response = cognitoIdp.describeUserPool(request)
if (response.userPool.schemaAttributes.find{it.name =='custom:' + name} == null) {

AddCustomAttributesRequest addAttrRequest = new AddCustomAttributesRequest().withUserPoolId(poolId)

List<SchemaAttributeType> attList = new ArrayList<>()
attList.add(new SchemaAttributeType().withAttributeDataType("String")
.withMutable(true).withName(name))

addAttrRequest.customAttributes = attList
def addAttResponse = cognitoIdp.addCustomAttributes(addAttrRequest)
if (addAttResponse.sdkHttpMetadata.httpStatusCode == 200) {

def updateUserResponse = addCustomUserProperty(user, name, value)

if (updateUserResponse.sdkHttpMetadata.httpStatusCode == 200) {
return [property: name, value: value]
} else {
return []
}
} else {
return []
}
}
else{
def updateUserResponse = addCustomUserProperty(user, name, value)

if (updateUserResponse.sdkHttpMetadata.httpStatusCode == 200) {
return [property: name, value: value]
} else {
return []
}
}
}

def addCustomUserProperty(UserRecord user, String name, String value){
Collection<AttributeType> userAttributes = new ArrayList<>()

userAttributes.add(new AttributeType().withName('custom:' + name).withValue(value))

AdminUpdateUserAttributesRequest updateUserRequest =
new AdminUpdateUserAttributesRequest()
.withUserPoolId(poolId)
.withUsername(user.userName)
.withUserAttributes(userAttributes)

return cognitoIdp.adminUpdateUserAttributes(updateUserRequest)
}

def getCustomUserProperty(UserRecord user, String name){
return user.userProperties.findAll{it.name == 'custom:'+ name}.collect{ [property:"$name",value: it.value ] }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import au.org.ala.userdetails.EmailService
import au.org.ala.userdetails.IUserService
import au.org.ala.userdetails.LocationService
import au.org.ala.userdetails.PasswordService
import au.org.ala.userdetails.ProfileService
import au.org.ala.userdetails.ResultStreamer
import au.org.ala.users.RoleRecord
import au.org.ala.users.UserPropertyRecord
Expand Down Expand Up @@ -613,7 +614,7 @@ class GormUserService implements IUserService {
}

@Override
User findByUserNameOrEmail(String username) {
UserRecord findByUserNameOrEmail(String username) {
return User.findByUserNameOrEmail(username, username)
}

Expand Down Expand Up @@ -735,11 +736,6 @@ class GormUserService implements IUserService {
return false
}

@Override
User findByUserNameOrEmail(String userName) {
return User.findByUserNameOrEmail(userName, userName)
}

@Override
def findUsersByRole(String roleName, List numberIds, List userIds, String pageOrToken) {
ScrollableResults results = null
Expand Down Expand Up @@ -795,12 +791,12 @@ class GormUserService implements IUserService {
return [results: results]
}

def saveCustomUserProperty(User user, String name, String value){
def saveCustomUserProperty(UserRecord user, String name, String value){
UserProperty property = profileService.saveUserProperty(user, name, value)
return property.hasErrors() ? null: property
}

def getCustomUserProperty(User user, String name){
def getCustomUserProperty(UserRecord user, String name){
return profileService.getUserProperty(user, name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,14 @@ interface IUserService {
boolean verifyUserCode(String userCode)

void enableMfa(String userId, boolean enable)

def findUsersByRole(String roleName, List numberIds, List userIds, String pageOrToken)

def getUserDetailsFromIdList(List idList)

def searchByUsernameOrEmail(String q, int max)

def saveCustomUserProperty(UserRecord user, String name, String value)

def getCustomUserProperty(UserRecord user, String name)
}

0 comments on commit 644e19c

Please sign in to comment.