/src/main/resources/com/onresolve/jira/groovy/canned/admin/RenameUser44.groovy
Groovy | 893 lines | 740 code | 104 blank | 49 comment | 126 complexity | 5cc0597cea255fae9e1168a37ab5cf8d MD5 | raw file
- package com.onresolve.jira.groovy.canned.admin
- import com.atlassian.core.ofbiz.util.CoreTransactionUtil
- import com.atlassian.crowd.embedded.api.User
- import com.atlassian.event.api.EventPublisher
- import com.atlassian.jira.ComponentManager
- import com.atlassian.jira.ManagerFactory
- import com.atlassian.jira.bc.JiraServiceContextImpl
- import com.atlassian.jira.event.ClearCacheEvent
- import com.atlassian.jira.imports.project.parser.UserAssociationParser
- import com.atlassian.jira.issue.CustomFieldManager
- import com.atlassian.jira.issue.IssueManager
- import com.atlassian.jira.issue.customfields.CustomFieldType
- import com.atlassian.jira.issue.fields.UserField
- import com.atlassian.jira.issue.index.IssueIndexManager
- import com.atlassian.jira.issue.search.CachingSearchRequestStore
- import com.atlassian.jira.issue.search.SearchRequest
- import com.atlassian.jira.issue.search.SearchRequestManager
- import com.atlassian.jira.issue.search.managers.SearchHandlerManager
- import com.atlassian.jira.issue.security.IssueSecuritySchemeManagerImpl
- import com.atlassian.jira.jql.ClauseHandler
- import com.atlassian.jira.notification.DefaultNotificationSchemeManager
- import com.atlassian.jira.notification.type.SingleUser
- import com.atlassian.jira.permission.DefaultPermissionSchemeManager
- import com.atlassian.jira.security.roles.CachingProjectRoleAndActorStore
- import com.atlassian.jira.security.roles.actor.UserRoleActorFactory
- import com.atlassian.jira.user.util.UserUtil
- import com.atlassian.jira.util.collect.EnclosedIterable
- import com.atlassian.query.Query
- import com.atlassian.query.QueryImpl
- import com.onresolve.jira.groovy.canned.CannedScript
- import org.apache.log4j.Category
- import com.atlassian.jira.util.*
- import com.atlassian.query.clause.*
- import com.atlassian.query.operand.*
- import org.ofbiz.core.entity.*
- public class RenameUser implements CannedScript {
- Category log = Category.getInstance(RenameUser.class)
- ComponentManager componentManager = ComponentManager.getInstance()
- UserUtil userUtil = componentManager.getUserUtil()
- SearchRequestManager searchRequestManager = componentManager.getSearchRequestManager()
- def searchRequestService = componentManager.getSearchRequestService()
- public static final String FIELD_FROM_USER_ID = 'FIELD_FROM_USER_ID'
- public static final String FIELD_TO_USER_ID = 'FIELD_TO_USER_ID'
- public static final String FIELD_MERGE = 'FIELD_MERGE'
- List msgs = []
- String msg
- Set<Long> reindexIssueIds = new HashSet()
- boolean preview = false
- Long nSearchReqsUpdated = 0
- boolean doMerge
- public String getName() {
- "Renames a user ID"
- }
- public String getDescription() {
- "Changes a user's ID without reindexing or restarting"
- }
- List getCategories() {
- ["ADMIN"]
- }
- public Boolean isFinalParamsPage(Map params) {
- true
- }
- public List getParameters(Map params) {
- [
- [
- Name: FIELD_FROM_USER_ID,
- Label: 'From user ID',
- Description: "Rename or merge from who?",
- ],
- [
- Name: FIELD_TO_USER_ID,
- Label: 'To user ID',
- Description: "Rename or merge to who?",
- ],
- [
- Name: FIELD_MERGE,
- Label: 'Merge',
- Type: 'radio',
- Description: "Merge the first user to the second user, rather than rename",
- Values: ["false": "Rename", "true": "Merge"],
- ],
- ]
- }
- ErrorCollection doValidate(Map params, boolean forPreview) {
- ErrorCollection errorCollection = new SimpleErrorCollection()
- String sourceUserId = params[FIELD_FROM_USER_ID] as String
- String targetUserId = params[FIELD_TO_USER_ID] as String
- if (! params[FIELD_MERGE]) {
- errorCollection.addError(FIELD_MERGE, "Please select an option")
- }
- doMerge = Boolean.parseBoolean(params[FIELD_MERGE] as String)
- [FIELD_FROM_USER_ID, FIELD_TO_USER_ID].each {String p ->
- if (! params[p]) {
- errorCollection.addError(p, "Please provide the user ID")
- }
- }
- if (errorCollection.hasAnyErrors()) {
- return errorCollection
- }
- if (! UserUtils.existsUser(sourceUserId as String)) {
- errorCollection.addError(FIELD_FROM_USER_ID, "Cannot find user ID")
- }
- if (sourceUserId == targetUserId) {
- errorCollection.addErrorMessage("From and to user can't be the same")
- }
- boolean targetExists = UserUtils.existsUser(targetUserId as String)
- if (doMerge && ! targetExists) {
- errorCollection.addError(FIELD_TO_USER_ID, "Target user ID must exist already for a merge")
- }
- if (! doMerge && targetExists) {
- errorCollection.addError(FIELD_TO_USER_ID, "Target user ID must not exist already")
- }
- if (sourceUserId == componentManager.getJiraAuthenticationContext().getUser()?.name) {
- errorCollection.addError(FIELD_FROM_USER_ID, "You can't rename the logged in user")
- }
- errorCollection
- }
- Query transformSearchRequest(Query query, String sourceUser, String targetUser) {
- Clause whereClause = query.getWhereClause()
- Clause newWhereClause = whereClause.accept(new RenamingClauseVisitor(sourceUser, targetUser)) as Clause
- // log.debug("original whereClause: " + query.whereClause.toString())
- // log.debug "new where clause: " + newWhereClause.toString()
- Query newQuery = new QueryImpl(newWhereClause)
- newQuery = new QueryImpl(newWhereClause, query.orderByClause, newQuery.queryString)
- newQuery
- }
- Map doScript(Map params) {
- String sourceUser = params[FIELD_FROM_USER_ID] as String
- String targetUser = params[FIELD_TO_USER_ID] as String
- doMerge = Boolean.parseBoolean(params[FIELD_MERGE] as String)
- // make sure they're not logged on??
- if (!preview) {
- msgs << "<b>Completed</b><br>"
- }
- updateGenericValues(sourceUser, targetUser)
- updateAllSearchRequests(sourceUser, targetUser)
- if (!preview) {
- msg = "Completed ${doMerge ? "merge" : "rename"} of $sourceUser to $targetUser"
- log.warn(msg)
- msgs << msg
- }
- params["output"] = "<pre>" + msgs.join("\n") + "<pre>"
- params
- }
- private def reindexIssue(IssueManager issueManager, Long issueId, Category log, IssueIndexManager indexManager) {
- GenericValue issue = issueManager.getIssue(issueId)
- boolean wasIndexing = ImportUtils.isIndexIssues();
- ImportUtils.setIndexIssues(true);
- if ((BuildUtils.getCurrentBuildNumber() as Long) < 614) {
- ManagerFactory.getCacheManager().flush(com.atlassian.jira.issue.cache.CacheManager.ISSUE_CACHE, issue)
- }
- log.debug("Reindex issue ${issue.key}")
- indexManager.reIndex(issue);
- ImportUtils.setIndexIssues(wasIndexing)
- }
- def updateGenericValues(String sourceUser, String targetUser) {
- boolean began = false
- DelegatorInterface gd = (DelegatorInterface) componentManager.getComponentInstanceOfType(DelegatorInterface.class)
- IssueIndexManager indexManager = ComponentManager.getInstance().getIndexManager()
- CachingProjectRoleAndActorStore cachingProjectRoleAndActorStore = ComponentManager.getComponentInstanceOfType(CachingProjectRoleAndActorStore.class) as CachingProjectRoleAndActorStore
- DefaultNotificationSchemeManager notificationSchemeManager = ComponentManager.getComponentInstanceOfType(DefaultNotificationSchemeManager.class) as DefaultNotificationSchemeManager
- DefaultPermissionSchemeManager defaultPermissionSchemeManager = ComponentManager.getComponentInstanceOfType(DefaultPermissionSchemeManager.class) as DefaultPermissionSchemeManager
- IssueSecuritySchemeManagerImpl securitySchemeManager = ComponentManager.getComponentInstanceOfType(IssueSecuritySchemeManagerImpl.class) as IssueSecuritySchemeManagerImpl
- CachingSearchRequestStore cachingSearchRequestStore = ComponentManager.getComponentInstanceOfType(CachingSearchRequestStore.class) as CachingSearchRequestStore
- IssueManager issueManager = componentManager.getIssueManager()
- if (! preview) {
- log.debug("Begin transaction")
- began = CoreTransactionUtil.begin();
- }
- try {
- msg = "Beginning ${doMerge ? "merge" : "rename"} of $sourceUser to $targetUser"
- log.warn(msg)
- msgs << msg
- // Rename the user record itself
- if ((BuildUtils.getCurrentBuildNumber() as Long) < 614) {
- List gvs = gd.findByAnd("OSUser", [name: sourceUser])
- assert gvs.size() == 1
- if (! preview) {
- GenericValue usergv = gvs.first() as GenericValue
- if (doMerge) {
- // todo: delete their associated property records
- usergv.remove()
- }
- else {
- usergv.set("name", targetUser)
- usergv.store()
- }
- }
- // group memberships
- gvs = gd.findByAnd("OSMembership", [userName: sourceUser])
- msg = "Update ${gvs.size()} OSMembership records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- List<GenericValue> targetGvs = gd.findByAnd("OSMembership", [userName: targetUser])
- List<Object> targetGroups = targetGvs*.get("groupName")
- gvs.each {GenericValue gv ->
- if (doMerge && targetGroups.contains (gv.get("groupName"))) {
- gv.remove()
- }
- else {
- gv.set("userName", targetUser)
- gv.store()
- }
- }
- }
- }
- else {
- // todo: only look in jira internal directory
- List gvs = gd.findByAnd("User", [userName: sourceUser])
- assert gvs.size() == 1
- if (! preview) {
- GenericValue usergv = gvs.first() as GenericValue
- if (doMerge) {
- usergv.remove()
- }
- else {
- usergv.set("userName", targetUser)
- usergv.set("lowerUserName", targetUser.toLowerCase())
- usergv.store()
- }
- }
- // group memberships
- gvs = gd.findByAnd("Membership", [childName: sourceUser, directoryId: 1, membershipType: "GROUP_USER"])
- msg = "Update ${gvs.size()} Membership records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- List<GenericValue> targetGvs = gd.findByAnd("Membership", [childName: targetUser, directoryId: 1, membershipType: "GROUP_USER"])
- List<Object> targetGroups = targetGvs*.get("parentName")
- gvs.each {GenericValue gv ->
- if (doMerge && targetGroups.contains (gv.get("parentName"))) {
- gv.remove()
- }
- else {
- gv.set("childName", targetUser)
- gv.set("lowerChildName", targetUser)
- gv.store()
- }
- }
- }
- }
- // trustedapp
- List gvs = gd.findByAnd("TrustedApplication", [createdBy: sourceUser])
- msg = "Update ${gvs.size()} TrustedApplication records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("createdBy", targetUser)
- gv.store()
- }
- }
- // SearchRequest ownership
- // if this is a merge, we may get dupe filter names. Not ideal but handled OK by the UI
- gvs = gd.findByOr("SearchRequest", [user: sourceUser, author: sourceUser])
- msg = "Update ${gvs.size()} SearchRequest records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- if (gv.get("user")) {
- gv.set("user", targetUser)
- }
- if (gv.get("author")) {
- gv.set("author", targetUser)
- }
- cachingSearchRequestStore.removeFromCache(gv.getLong("id"))
- gv.store()
- }
- }
- // ColumnLayout - choose one or tother.
- gvs = gd.findByAnd("ColumnLayout", [username: sourceUser])
- msg = "Update ${gvs.size()} ColumnLayout records"
- List<GenericValue> targetGvs = gd.findByAnd("ColumnLayout", [username: targetUser])
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- if (doMerge && targetGvs.find {it.getLong("searchrequest") == gv.getLong("searchrequest")}) {
- gd.removeRelated("ChildColumnLayoutItem", gv)
- gv.remove()
- }
- else {
- gv.set("username", targetUser)
- gv.store()
- }
- }
- }
- if (!doMerge) {
- gvs = gd.findByAnd("UserHistoryItem", [username: sourceUser])
- msg = "Update ${gvs.size()} UserHistoryItem records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("username", targetUser)
- gv.store()
- }
- }
- }
- gvs = gd.findByAnd("FavouriteAssociations", [username: sourceUser])
- targetGvs = gd.findByAnd("FavouriteAssociations", [username: targetUser])
- msg = "Update ${gvs.size()} FavouriteAssociations records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- List matchFields = ["entityType", "entityId"]
- gvs.each {GenericValue gv ->
- // favourite assocs, only fave if not already faved
- if (doMerge && targetGvs.find {
- it.getFields(matchFields) == gv.getFields(matchFields)
- }) {
- // favcount must be adjusted downwards when both are favouriting
- log.debug("Remove fav association record and decrement favourite count")
- GenericValue sharedEntityGv = gd.findByPrimaryKey(gv.get("entityType") as String, [id: gv.get("entityId")])
- sharedEntityGv.set("favCount", (sharedEntityGv.get("favCount") as Long) - 1)
- sharedEntityGv.store()
- gv.remove()
- }
- else {
- gv.set("username", targetUser)
- gv.store()
- }
- }
- }
- ["PortalPage", "FilterSubscription"].each {String entityName ->
- gvs = gd.findByAnd(entityName, [username: sourceUser])
- msg = "Update ${gvs.size()} $entityName records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("username", targetUser)
- gv.store()
- }
- }
- }
- // note: for versions prior to 4.1 the favouritesStoreCache needs to be flushed
- // Core issue fields
- gvs = gd.findByOr("Issue", [reporter: sourceUser, assignee: sourceUser])
- msg = "Update ${gvs.size()} Issue records"
- log.debug(msg)
- msgs << msg
- gvs.each {GenericValue gv ->
- if (!preview) {
- if (gv.get("reporter") == sourceUser) {
- gv.set("reporter", targetUser)
- }
- if (gv.get("assignee") == sourceUser) {
- gv.set("assignee", targetUser)
- }
- gv.store()
- }
- reindexIssueIds.add(gv.getLong("id"))
- }
- // issue transition history
- gvs = gd.findByOr("Action", [author: sourceUser, updateauthor: sourceUser])
- msg = "Update ${gvs.size()} Action records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- if (gv.get("author") == sourceUser) {
- gv.set("author", targetUser)
- }
- if (gv.get("updateauthor") == sourceUser) {
- gv.set("updateauthor", targetUser)
- }
- gv.store()
- }
- }
- // change groups
- gvs = gd.findByAnd("ChangeGroup", [author: sourceUser])
- msg = "Update ${gvs.size()} ChangeGroup records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("author", targetUser)
- gv.store()
- }
- }
- // Change items
- // todo: custom field history items - problem is they are referenced by name which is not unique
- EntityConditionList conditionList = new EntityConditionList(
- [new EntityConditionList(
- [
- // Stoopid oracle can't do equals on a clob, LIKE shd be OK
- // alternative is to do the filtering in the code
- new EntityExpr("oldvalue", EntityOperator.LIKE, sourceUser),
- new EntityExpr("newvalue", EntityOperator.LIKE, sourceUser),
- ], EntityOperator.OR),
- new EntityConditionList([new EntityExpr("field", EntityOperator.IN, ["reporter", "assignee"])], EntityOperator.AND)
- ], EntityOperator.AND
- )
- gvs = gd.findByCondition("ChangeItem", conditionList, ["id", "field", "oldvalue", "newvalue"], Collections.<String> emptyList())
- msg = "Update ${gvs.size()} ChangeItem records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- if (gv.get("oldvalue") == sourceUser) {
- gv.set("oldvalue", targetUser)
- }
- if (gv.get("newvalue") == sourceUser) {
- gv.set("newvalue", targetUser)
- }
- gv.store()
- }
- }
- // Watchers and voters
- gvs = gd.findByAnd("UserAssociation", getUserAssociationConditionList(sourceUser))
- targetGvs = gd.findByAnd("UserAssociation", getUserAssociationConditionList(targetUser))
- msg = "Update ${gvs.size()} UserAssociation records"
- log.debug(msg)
- msgs << msg
- gvs.each {GenericValue gv ->
- if (gv.get("sinkNodeEntity") == "Issue") {
- reindexIssueIds.add(gv.getLong("sinkNodeId"))
- }
- if (!preview) {
- gd.removeValue(gv)
- if (doMerge && targetGvs.find {
- it.get("sinkNodeId") == gv.get("sinkNodeId") &&
- it.get("sinkNodeEntity") == gv.get("sinkNodeEntity") &&
- it.get("associationType") == gv.get("associationType")
- }) {
- // do nothing as always remove
- log.debug("Removed userassoc record")
- }
- else {
- // gv.store() doesn't work because we're changing the primary key
- gv.set("sourceName", targetUser)
- gd.create(gv)
- }
- }
- }
- // roles
- gvs = gd.findByAnd("ProjectRoleActor", [roletype: UserRoleActorFactory.TYPE, roletypeparameter: sourceUser])
- targetGvs = gd.findByAnd("ProjectRoleActor", [roletype: UserRoleActorFactory.TYPE, roletypeparameter: targetUser])
- msg = "Update ${gvs.size()} ProjectRoleActor records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- List matchFields = ["pid", "projectroleid"]
- if (doMerge && targetGvs.find {
- gv.getFields(matchFields) == it.getFields(matchFields)
- }) {
- log.debug("Remove role record")
- gv.remove()
- }
- else {
- gv.set("roletypeparameter", targetUser)
- gv.store()
- }
- }
- cachingProjectRoleAndActorStore.clearCaches()
- }
- // SharePermissions not required as cannot share with a user
- // worklogs
- gvs = gd.findByOr("Worklog", [author: sourceUser, updateauthor: sourceUser])
- msg = "Update ${gvs.size()} Worklog records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- if (gv.get("author") == sourceUser) {
- gv.set("author", targetUser)
- }
- if (gv.get("updateauthor") == sourceUser) {
- gv.set("updateauthor", targetUser)
- }
- gv.store()
- }
- }
- // project and comp leads
- gvs = gd.findByAnd("Project", [lead: sourceUser])
- msg = "Update ${gvs.size()} Project records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("lead", targetUser)
- gv.store()
- }
- }
- gvs = gd.findByAnd("Component", [lead: sourceUser])
- msg = "Update ${gvs.size()} Component records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("lead", targetUser)
- gv.store()
- }
- }
- // notification schemes
- gvs = gd.findByAnd("Notification", [type: SingleUser.DESC, parameter: sourceUser])
- targetGvs = gd.findByAnd("Notification", [type: SingleUser.DESC, parameter: targetUser])
- msg = "Update ${gvs.size()} Notification records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- if (doMerge && targetGvs.find {
- gv.getFields(["scheme", "eventTypeId", "type"]) == it.getFields(["scheme", "eventTypeId", "type"])
- }) {
- log.debug("Remove Notification record")
- gv.remove()
- }
- else {
- gv.set("parameter", targetUser)
- gv.store()
- }
- }
- notificationSchemeManager.flushProjectSchemes()
- }
- // permission schemes
- gvs = gd.findByAnd("SchemePermissions", [type: "user", parameter: sourceUser])
- targetGvs = gd.findByAnd("SchemePermissions", [type: "user", parameter: targetUser])
- msg = "Update ${gvs.size()} SchemePermissions records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- List matchFields = ['scheme', 'permission', 'type', 'parameter']
- gvs.each {GenericValue gv ->
- if (doMerge && targetGvs.find {
- gv.getFields(matchFields) == it.getFields(matchFields)
- }) {
- log.debug("Remove Notification record")
- gv.remove()
- }
- else {
- gv.set("parameter", targetUser)
- gv.store()
- }
- }
- defaultPermissionSchemeManager.flushProjectSchemes()
- defaultPermissionSchemeManager.flushSchemeEntities()
- }
- // issue security schemes
- gvs = gd.findByAnd("SchemeIssueSecurities", [type: "user", parameter: sourceUser])
- targetGvs = gd.findByAnd("SchemePermissions", [type: "user", parameter: targetUser])
- msg = "Update ${gvs.size()} SchemeIssueSecurities records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- List matchFields = ['scheme', 'security', 'type', 'parameter']
- gvs.each {GenericValue gv ->
- if (doMerge && targetGvs.find {
- gv.getFields(matchFields) == it.getFields(matchFields)
- }) {
- log.debug("Remove Notification record")
- gv.remove()
- }
- else {
- gv.set("parameter", targetUser)
- gv.store()
- }
- }
- securitySchemeManager.flushProjectSchemes()
- }
- // user and multi-user custom fields
- gvs = gd.findByCondition("CustomField",
- new EntityExpr("customfieldtypekey", EntityOperator.IN,
- [
- "com.atlassian.jira.plugin.system.customfieldtypes:userpicker",
- "com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker"
- ])
- ,
- ["id"], Collections.<String> emptyList())
- Long cfValueKount = 0
- gvs.each {GenericValue gv ->
- gv.getRelatedByAnd("ChildCustomFieldValue", [stringvalue: sourceUser]).each {GenericValue cfGv ->
- cfValueKount++
- if (!preview) {
- cfGv.set("stringvalue", targetUser)
- cfGv.store()
- }
- reindexIssueIds.add(cfGv.getLong("issue"))
- }
- }
- msg = "Update $cfValueKount CustomFieldValue records"
- log.debug(msg)
- msgs << msg
- gvs = gd.findByAnd("OSHistoryStep", [caller: sourceUser])
- msg = "Update ${gvs.size()} OSHistoryStep records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("caller", targetUser)
- gv.store()
- }
- }
- // fileattachments
- gvs = gd.findByAnd("FileAttachment", [author: sourceUser])
- msg = "Update ${gvs.size()} FileAttachment records"
- log.debug(msg)
- msgs << msg
- if (!preview) {
- gvs.each {GenericValue gv ->
- gv.set("author", targetUser)
- gv.store()
- }
- }
- // -------------------------------------- Finalise --------------------------------------
- if (! preview) {
- log.debug("Commit transaction")
- CoreTransactionUtil.commit(began);
- // Only for 4.1 and above - clearing the other caches are not necessary above but kept there if
- // I decide to backport this
- log.debug("Publish clear cache event")
- ComponentManager.getComponentInstanceOfType(EventPublisher.class).publish(ClearCacheEvent.INSTANCE);
- // reindex issues
- reindexIssueIds.each {Long issueId ->
- reindexIssue(issueManager, issueId, log, indexManager);
- }
- User user = userUtil.getUser(targetUser)
- // user.getAccessProvider().flushCaches()
- // user.getProfileProvider().flushCaches()
- }
- msg = "Reindex ${reindexIssueIds.size()} issues"
- log.debug(msg)
- msgs << msg
- }
- catch (Exception e) {
- log.error("Problem renaming user, rolling back")
- CoreTransactionUtil.rollback(began)
- throw e
- }
- finally {
- // not sure if we need anything here
- }
- }
- private List<EntityExpr> getUserAssociationConditionList(String userId) {
- List userAssocCList = [
- new EntityExpr("sourceName", EntityOperator.EQUALS, userId),
- new EntityExpr("associationType", EntityOperator.IN,
- [UserAssociationParser.ASSOCIATION_TYPE_WATCH_ISSUE, UserAssociationParser.ASSOCIATION_TYPE_VOTE_ISSUE]),
- ]
- return userAssocCList
- }
- def updateSingleRequest(SearchRequest sr, String sourceUser, String targetUser) {
- Query query = sr.getQuery()
- Query newQuery
- // A query may have no where clause and select everything... if so .accept dies
- if (query.getWhereClause()) {
- newQuery = transformSearchRequest(query, sourceUser, targetUser)
- }
- else {
- newQuery = query
- }
- if (query.whereClause.toString() != newQuery.whereClause.toString()) {
- // this is stupid but setting a queryString seems to blow away the whereClause, so we do this twice
- nSearchReqsUpdated++
- log.debug("Update sr name: " + sr.name)
- // log.debug("queryString: " + newQuery.queryString)
- // log.debug("newQuery: $newQuery")
- sr.setQuery(newQuery)
- JiraServiceContextImpl ctx = new JiraServiceContextImpl(userUtil.getUser(sr.ownerUserName))
- searchRequestService.validateFilterForUpdate(ctx, sr)
- if (ctx.errorCollection.hasAnyErrors()) {
- log.error("errors: " + ctx.getErrorCollection())
- }
- else {
- if (! preview) {
- searchRequestService.updateFilter(ctx, sr)
- }
- }
- }
- else {
- log.debug("No need to update name: " + sr.name)
- }
- }
- private def updateAllSearchRequests(String sourceUser, String targetUser) {
- EnclosedIterable<SearchRequest> srs = searchRequestManager.getAll()
- srs.foreach(new Consumer<SearchRequest>() {
- void consume(SearchRequest sr) {
- updateSingleRequest(sr, sourceUser, targetUser)
- }
- })
- msg = "Update parameters for $nSearchReqsUpdated search requests"
- log.debug(msg)
- msgs << msg
- }
- String getDescription(Map params, boolean forPreview) {
- preview = true
- Map out = doScript(params)
- out["output"]
- }
- public String getHelpUrl() {
- "https://studio.plugins.atlassian.com/wiki/display/GRV/Built-In+Scripts#Built-InScripts-RenameaUserID"
- }
- }
- private class RenamingClauseVisitor implements ClauseVisitor {
- Category log = Category.getInstance(RenamingClauseVisitor.class)
- SearchHandlerManager searchHandlerManager = ComponentManager.getComponentInstanceOfType(SearchHandlerManager.class) as SearchHandlerManager
- ComponentManager componentManager = ComponentManager.getInstance()
- CustomFieldManager customFieldManager = componentManager.getCustomFieldManager()
- String sourceUser
- String targetUser
- RenamingClauseVisitor(String sourceUser, String targetUser) {
- this.sourceUser = sourceUser
- this.targetUser = targetUser
- }
- Object visit(AndClause andClause) {
- Collection<Clause> newClauses = transformSubClauses(andClause)
- new AndClause(newClauses)
- }
- Object visit(NotClause notClause) {
- new NotClause(notClause.getSubClause().accept(new RenamingClauseVisitor(sourceUser, targetUser)) as Clause)
- }
- Object visit(OrClause orClause) {
- Collection<Clause> newClauses = transformSubClauses(orClause)
- new OrClause(newClauses)
- }
- private Collection<Clause> transformSubClauses(Clause mainClause) {
- Collection<Clause> newClauses = []
- mainClause.getClauses().each {Clause clause ->
- newClauses.add(clause.accept(new RenamingClauseVisitor(sourceUser, targetUser)) as Clause)
- }
- return newClauses
- }
- Object visit(TerminalClause clause) {
- final Collection<ClauseHandler> handlers = searchHandlerManager.getClauseHandler(clause.getName());
- Collection<String> fieldIds = searchHandlerManager.getFieldIds(clause.getName())
- // If there are multiple handers, eg field has multiple duplicate names, don't deal with it
- // ie multiple fields with the same name visible to this user
- if (fieldIds?.size() != 1) {
- return clause
- }
- String fieldId = fieldIds.toList().first()
- boolean isUserField = false
- if (fieldId.startsWith("customfield_")) {
- CustomFieldType cfType = customFieldManager.getCustomFieldObject(fieldId).getCustomFieldType()
- if (cfType instanceof UserField) {
- isUserField = true
- }
- }
- if (["reporter", "assignee"].contains(fieldId) || isUserField) {
- Operand operand = clause.getOperand()
- Operand newOp = operand.accept(new RenamingOperandVisitor(sourceUser, targetUser)) as Operand
- TerminalClauseImpl newTermClause = new TerminalClauseImpl(clause.name, clause.getOperator(), newOp)
- return newTermClause
- }
- clause
- }
- Object visit(WasClause wasClause) {
- // wasClause in 4.3 not handled at the moment
- wasClause
- }
- Object visit(ChangedClause changedClause) {
- // wasClause in 4.3 not handled at the moment
- changedClause
- }
- }
- private class RenamingOperandVisitor implements OperandVisitor {
- Category log = Category.getInstance(RenamingOperandVisitor.class)
- String sourceUser
- String targetUser
- RenamingOperandVisitor(String sourceUser, String targetUser) {
- this.sourceUser = sourceUser
- this.targetUser = targetUser
- }
- Object visit(EmptyOperand empty) {
- empty
- }
- Object visit(FunctionOperand function) {
- function
- }
- Object visit(MultiValueOperand multiValue) {
- List<Operand> newOps = multiValue.getValues().collectAll {Operand operand ->
- if (operand instanceof SingleValueOperand && operand.getStringValue() == sourceUser) {
- return new SingleValueOperand(targetUser)
- }
- operand
- }
- new MultiValueOperand(newOps)
- }
- Object visit(SingleValueOperand singleValueOperand) {
- if (singleValueOperand.getStringValue() == sourceUser) {
- return new SingleValueOperand(targetUser)
- }
- singleValueOperand
- }
- }