PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/test/resources/examples/RenameUserDoNotUse.groovy

https://bitbucket.org/aschuma/scriptrunner-public-2.0.9
Groovy | 545 lines | 443 code | 60 blank | 42 comment | 45 complexity | d17f41629b040075e6979a8639019bdc MD5 | raw file
  1. package examples
  2. import com.atlassian.core.ofbiz.association.AssociationManager
  3. import com.atlassian.core.ofbiz.util.CoreTransactionUtil
  4. import com.atlassian.event.api.EventPublisher
  5. import com.atlassian.jira.ComponentManager
  6. import com.atlassian.jira.ManagerFactory
  7. import com.atlassian.jira.bc.filter.SearchRequestService
  8. import com.atlassian.jira.bc.portal.PortalPageService
  9. import com.atlassian.jira.event.ClearCacheEvent
  10. import com.atlassian.jira.favourites.FavouritesManager
  11. import com.atlassian.jira.imports.project.parser.UserAssociationParser
  12. import com.atlassian.jira.issue.IssueManager
  13. import com.atlassian.jira.issue.cache.CacheManager
  14. import com.atlassian.jira.issue.index.IssueIndexManager
  15. import com.atlassian.jira.issue.search.CachingSearchRequestStore
  16. import com.atlassian.jira.issue.search.SearchRequestManager
  17. import com.atlassian.jira.issue.search.SearchRequestStore
  18. import com.atlassian.jira.issue.security.IssueSecuritySchemeManagerImpl
  19. import com.atlassian.jira.notification.DefaultNotificationSchemeManager
  20. import com.atlassian.jira.notification.type.SingleUser
  21. import com.atlassian.jira.permission.DefaultPermissionSchemeManager
  22. import com.atlassian.jira.portal.CachingPortalPageStore
  23. import com.atlassian.jira.portal.PortalPageManager
  24. import com.atlassian.jira.security.roles.CachingProjectRoleAndActorStore
  25. import com.atlassian.jira.security.roles.actor.UserRoleActorFactory
  26. import com.atlassian.jira.sharing.ShareManager
  27. import com.atlassian.jira.util.ImportUtils
  28. import com.opensymphony.user.UserManager
  29. import org.apache.log4j.Category
  30. import org.ofbiz.core.entity.*
  31. import com.opensymphony.user.EntityNotFoundException
  32. import com.atlassian.jira.util.collect.EnclosedIterable
  33. import com.atlassian.jira.issue.search.SearchRequest
  34. import com.atlassian.jira.util.Consumer
  35. import com.atlassian.query.clause.ClauseVisitor
  36. import com.atlassian.query.clause.AndClause
  37. import com.atlassian.query.clause.NotClause
  38. import com.atlassian.query.clause.OrClause
  39. import com.atlassian.query.clause.TerminalClause
  40. import com.atlassian.query.clause.Clause
  41. import com.atlassian.jira.jql.builder.JqlQueryBuilder
  42. import com.atlassian.jira.jql.parser.JqlQueryParser
  43. import com.atlassian.query.operand.Operand
  44. import com.atlassian.query.operand.OperandVisitor
  45. import com.atlassian.query.operand.EmptyOperand
  46. import com.atlassian.query.operand.FunctionOperand
  47. import com.atlassian.query.operand.MultiValueOperand
  48. import com.atlassian.query.operand.SingleValueOperand
  49. import com.atlassian.query.clause.TerminalClauseImpl
  50. import com.atlassian.query.Query
  51. import com.atlassian.query.QueryImpl
  52. import com.atlassian.jira.bc.JiraServiceContextImpl
  53. Category log = Category.getInstance("com.onresolve.jira.groovy.Scratch")
  54. ComponentManager componentManager = ComponentManager.getInstance()
  55. UserManager userManager = UserManager.getInstance()
  56. FavouritesManager favouritesManager = ComponentManager.getComponentInstanceOfType(FavouritesManager.class) as FavouritesManager
  57. SearchRequestStore searchRequestStore = ComponentManager.getComponentInstanceOfType(SearchRequestStore.class) as SearchRequestStore
  58. CachingSearchRequestStore cachingSearchRequestStore = ComponentManager.getComponentInstanceOfType(CachingSearchRequestStore.class) as CachingSearchRequestStore
  59. CachingPortalPageStore cachingPortalPageStore = ComponentManager.getComponentInstanceOfType(CachingPortalPageStore.class) as CachingPortalPageStore
  60. ShareManager shareManager = ComponentManager.getComponentInstanceOfType(ShareManager.class) as ShareManager
  61. SearchRequestManager searchRequestManager = componentManager.getSearchRequestManager()
  62. SearchRequestService searchRequestService = componentManager.getSearchRequestService()
  63. IssueManager issueManager = componentManager.getIssueManager()
  64. AssociationManager associationManager = ComponentManager.getComponentInstanceOfType(AssociationManager.class) as AssociationManager
  65. CachingProjectRoleAndActorStore cachingProjectRoleAndActorStore = ComponentManager.getComponentInstanceOfType(CachingProjectRoleAndActorStore.class) as CachingProjectRoleAndActorStore
  66. DefaultNotificationSchemeManager notificationSchemeManager = ComponentManager.getComponentInstanceOfType(DefaultNotificationSchemeManager.class) as DefaultNotificationSchemeManager
  67. DefaultPermissionSchemeManager defaultPermissionSchemeManager = ComponentManager.getComponentInstanceOfType(DefaultPermissionSchemeManager.class) as DefaultPermissionSchemeManager
  68. IssueSecuritySchemeManagerImpl securitySchemeManager = ComponentManager.getComponentInstanceOfType(IssueSecuritySchemeManagerImpl.class) as IssueSecuritySchemeManagerImpl
  69. Set<Long> reindexIssueIds = new HashSet()
  70. String sourceUser = 'rchapma4'
  71. String targetUser = 'rchapma5'
  72. DelegatorInterface gd = (DelegatorInterface) componentManager.getComponentInstanceOfType(DelegatorInterface.class)
  73. IssueIndexManager indexManager = ComponentManager.getInstance().getIndexManager()
  74. private def reindexIssue(IssueManager issueManager, Long issueId, Category log, IssueIndexManager indexManager) {
  75. GenericValue issue = issueManager.getIssue(issueId)
  76. boolean wasIndexing = ImportUtils.isIndexIssues();
  77. ImportUtils.setIndexIssues(true);
  78. ManagerFactory.getCacheManager().flush(CacheManager.ISSUE_CACHE, issue)
  79. log.debug("Reindex issue ${issue.key}")
  80. indexManager.reIndex(issue);
  81. ImportUtils.setIndexIssues(wasIndexing)
  82. }
  83. boolean preview = false
  84. List msgs = []
  85. String msg
  86. boolean began = false
  87. private def getLog() {
  88. return log
  89. }
  90. EnclosedIterable<SearchRequest> srs = searchRequestManager.getAll()
  91. srs.foreach(new Consumer<SearchRequest>() {
  92. void consume(SearchRequest sr) {
  93. if (sr.name != "ReporterIsRenamedUser") {
  94. return
  95. }
  96. log.debug("visiting")
  97. Query query = sr.getQuery()
  98. log.debug query
  99. Clause whereClause = query.getWhereClause()
  100. Clause newWhereClause = whereClause.accept(new ClauseVisitor() {
  101. Object visit(AndClause andClause) {
  102. println("visit")
  103. getLog().debug("AndClause")
  104. andClause
  105. }
  106. Object visit(NotClause notClause) {
  107. getLog().debug("NotClause")
  108. notClause
  109. }
  110. Object visit(OrClause orClause) {
  111. getLog().debug("OrClause")
  112. orClause
  113. }
  114. Object visit(TerminalClause clause) {
  115. // println("visit TerminalClause")
  116. getLog().debug "clause.getName(): " + clause.getName()
  117. if (["reporter", "assignee"].contains (clause.getName())) {
  118. Operand operand = clause.getOperand()
  119. println operand.getDisplayString()
  120. Operand newOp = operand.accept(new OperandVisitor() {
  121. Object visit(EmptyOperand empty) {
  122. empty
  123. }
  124. Object visit(FunctionOperand function) {
  125. function
  126. }
  127. Object visit(MultiValueOperand multiValue) {
  128. getLog().debug "multiValue: $multiValue"
  129. multiValue
  130. }
  131. Object visit(SingleValueOperand singleValueOperand) {
  132. getLog().debug "singleValueOperand: $singleValueOperand"
  133. getLog().debug singleValueOperand.getStringValue()
  134. getLog().debug "Update admin to anuser"
  135. new SingleValueOperand("anuser")
  136. }
  137. }) as Operand
  138. getLog().debug "newOp: $newOp"
  139. TerminalClauseImpl newTermClause = new TerminalClauseImpl(clause.name, clause.getOperator(), newOp)
  140. getLog().debug("newTermClause: " + newTermClause)
  141. return newTermClause
  142. }
  143. println clause.getOperator().getDisplayString()
  144. clause
  145. }
  146. }) as Clause
  147. log.debug "total where clause: " + newWhereClause
  148. query.whereClause
  149. if (query.whereClause.toString() != newWhereClause.toString()) {
  150. // this is stupid but setting a queryString seems to blow away the whereClause, so we do this twice
  151. log.debug("Update sr name: " + sr.name)
  152. /*
  153. Query newQuery = new QueryImpl(newWhereClause)
  154. newQuery = new QueryImpl(newWhereClause, query.orderByClause, newQuery.queryString)
  155. log.debug("newQuery: $newQuery")
  156. sr.setQuery(newQuery)
  157. JiraServiceContextImpl ctx = new JiraServiceContextImpl(userManager.getUser(sr.ownerUserName))
  158. searchRequestService.validateFilterForUpdate(ctx, sr)
  159. log.debug("errors: " + ctx.getErrorCollection())
  160. searchRequestService.updateFilter(ctx, sr)
  161. log.debug("errors: " + ctx.getErrorCollection())
  162. */
  163. }
  164. else {
  165. log.debug("No need to update name: " + sr.name)
  166. }
  167. }
  168. })
  169. return
  170. if (! preview) {
  171. log.debug("Begin transaction")
  172. began = CoreTransactionUtil.begin();
  173. }
  174. try {
  175. try {
  176. userManager.getUser("def")
  177. sourceUser = "def"
  178. targetUser = "abc"
  179. }
  180. catch (EntityNotFoundException e) {
  181. try {
  182. log.debug "no user def"
  183. userManager.getUser("abc")
  184. sourceUser = "abc"
  185. targetUser = "def"
  186. }
  187. catch (EntityNotFoundException ef) {
  188. log.error("No abc or def")
  189. return
  190. }
  191. }
  192. msg = "Beginning rename of $sourceUser to $targetUser"
  193. log.warn(msg)
  194. msgs << msg
  195. //User user = UserUtils.createUser("abc", "x", "abc@blah.com", "Mr ABC", ["jira-users"])
  196. //return
  197. // Rename the user record itself
  198. List gvs = gd.findByAnd("OSUser", [name: sourceUser])
  199. assert gvs.size() == 1
  200. if (! preview) {
  201. GenericValue usergv = gvs.first() as GenericValue
  202. usergv.set("name", targetUser)
  203. usergv.store()
  204. }
  205. // group memberships
  206. gvs = gd.findByAnd("OSMembership", [userName: sourceUser])
  207. msg = "Update ${gvs.size()} OSMembership records"
  208. log.debug(msg)
  209. msgs << msg
  210. if (!preview) {
  211. gvs.each {GenericValue gv ->
  212. gv.set("userName", targetUser)
  213. gv.store()
  214. }
  215. }
  216. // SearchRequest ownership
  217. gvs = gd.findByOr("SearchRequest", [user: sourceUser, author: sourceUser])
  218. msg = "Update ${gvs.size()} SearchRequest records"
  219. log.debug(msg)
  220. msgs << msg
  221. if (!preview) {
  222. gvs.each {GenericValue gv ->
  223. if (gv.get("user")) {
  224. gv.set("user", targetUser)
  225. }
  226. if (gv.get("author")) {
  227. gv.set("author", targetUser)
  228. }
  229. cachingSearchRequestStore.removeFromCache(gv.getLong("id"))
  230. gv.store()
  231. }
  232. }
  233. ["PortalPage", "ColumnLayout", "UserHistoryItem", "FilterSubscription", "FavouriteAssociations"].each {String entityName ->
  234. gvs = gd.findByAnd(entityName, [username: sourceUser])
  235. msg = "Update ${gvs.size()} $entityName records"
  236. log.debug(msg)
  237. msgs << msg
  238. if (!preview) {
  239. gvs.each {GenericValue gv ->
  240. gv.set("username", targetUser)
  241. gv.store()
  242. }
  243. }
  244. }
  245. // note: for versions prior to 4.1 the favouritesStoreCache needs to be flushed
  246. // Core issue fields
  247. gvs = gd.findByOr("Issue", [reporter: sourceUser, assignee: sourceUser])
  248. msg = "Update ${gvs.size()} Issue records"
  249. log.debug(msg)
  250. msgs << msg
  251. gvs.each {GenericValue gv ->
  252. if (!preview) {
  253. if (gv.get("reporter") == sourceUser) {
  254. gv.set("reporter", targetUser)
  255. }
  256. if (gv.get("assignee") == sourceUser) {
  257. gv.set("assignee", targetUser)
  258. }
  259. gv.store()
  260. }
  261. reindexIssueIds.add(gv.getLong("id"))
  262. }
  263. // issue transition history
  264. gvs = gd.findByOr("Action", [author: sourceUser, updateauthor: sourceUser])
  265. msg = "Update ${gvs.size()} Action records"
  266. log.debug(msg)
  267. msgs << msg
  268. if (!preview) {
  269. gvs.each {GenericValue gv ->
  270. if (gv.get("author") == sourceUser) {
  271. gv.set("author", targetUser)
  272. }
  273. if (gv.get("updateauthor") == sourceUser) {
  274. gv.set("updateauthor", targetUser)
  275. }
  276. gv.store()
  277. }
  278. }
  279. // change groups
  280. gvs = gd.findByAnd("ChangeGroup", [author: sourceUser])
  281. msg = "Update ${gvs.size()} ChangeGroup records"
  282. log.debug(msg)
  283. msgs << msg
  284. if (!preview) {
  285. gvs.each {GenericValue gv ->
  286. gv.set("author", targetUser)
  287. gv.store()
  288. }
  289. }
  290. // Change items
  291. EntityConditionList conditionList = new EntityConditionList(
  292. [new EntityConditionList(
  293. [
  294. new EntityExpr("oldvalue", EntityOperator.EQUALS, sourceUser),
  295. new EntityExpr("newvalue", EntityOperator.EQUALS, sourceUser),
  296. ], EntityOperator.OR),
  297. new EntityConditionList([new EntityExpr("field", EntityOperator.IN, ["reporter", "assignee"])], EntityOperator.AND)
  298. ], EntityOperator.AND
  299. )
  300. gvs = gd.findByCondition("ChangeItem", conditionList, ["id", "field", "oldvalue", "newvalue"], Collections.<String> emptyList())
  301. msg = "Update ${gvs.size()} ChangeItem records"
  302. log.debug(msg)
  303. msgs << msg
  304. if (!preview) {
  305. gvs.each {GenericValue gv ->
  306. if (gv.get("oldvalue") == sourceUser) {
  307. gv.set("oldvalue", targetUser)
  308. }
  309. if (gv.get("newvalue") == sourceUser) {
  310. gv.set("newvalue", targetUser)
  311. }
  312. gv.store()
  313. }
  314. }
  315. // Watchers and voters
  316. List userAssocCList = [
  317. new EntityExpr("sourceName", EntityOperator.EQUALS, sourceUser),
  318. new EntityExpr("associationType", EntityOperator.IN,
  319. [UserAssociationParser.ASSOCIATION_TYPE_WATCH_ISSUE, UserAssociationParser.ASSOCIATION_TYPE_VOTE_ISSUE]),
  320. ]
  321. gvs = gd.findByAnd("UserAssociation", userAssocCList)
  322. msg = "Update ${gvs.size()} UserAssociation records"
  323. log.debug(msg)
  324. msgs << msg
  325. if (!preview) {
  326. gvs.each {GenericValue gv ->
  327. gd.removeValue(gv)
  328. gv.set("sourceName", targetUser)
  329. gd.create(gv)
  330. // gv.store() doesn't work because we're changing the primary key
  331. }
  332. }
  333. // roles
  334. gvs = gd.findByAnd("ProjectRoleActor", [roletype: UserRoleActorFactory.TYPE, roletypeparameter: sourceUser])
  335. msg = "Update ${gvs.size()} ProjectRoleActor records"
  336. log.debug(msg)
  337. msgs << msg
  338. if (!preview) {
  339. gvs.each {GenericValue gv ->
  340. gv.set("roletypeparameter", targetUser)
  341. gv.store()
  342. }
  343. cachingProjectRoleAndActorStore.clearCaches()
  344. }
  345. // SharePermissions not required as cannot share with a user
  346. // worklogs
  347. gvs = gd.findByOr("Worklog", [author: sourceUser, updateauthor: sourceUser])
  348. msg = "Update ${gvs.size()} Worklog records"
  349. log.debug(msg)
  350. msgs << msg
  351. if (!preview) {
  352. gvs.each {GenericValue gv ->
  353. if (gv.get("author") == sourceUser) {
  354. gv.set("author", targetUser)
  355. }
  356. if (gv.get("updateauthor") == sourceUser) {
  357. gv.set("updateauthor", targetUser)
  358. }
  359. gv.store()
  360. }
  361. }
  362. // project and comp leads
  363. gvs = gd.findByAnd("Project", [lead: sourceUser])
  364. msg = "Update ${gvs.size()} Project records"
  365. log.debug(msg)
  366. msgs << msg
  367. if (!preview) {
  368. gvs.each {GenericValue gv ->
  369. gv.set("lead", targetUser)
  370. gv.store()
  371. }
  372. }
  373. gvs = gd.findByAnd("Component", [lead: sourceUser])
  374. msg = "Update ${gvs.size()} Component records"
  375. log.debug(msg)
  376. msgs << msg
  377. if (!preview) {
  378. gvs.each {GenericValue gv ->
  379. gv.set("lead", targetUser)
  380. gv.store()
  381. }
  382. }
  383. // notification schemes
  384. gvs = gd.findByAnd("Notification", [type: SingleUser.DESC, parameter: sourceUser])
  385. msg = "Update ${gvs.size()} Notification records"
  386. log.debug(msg)
  387. msgs << msg
  388. if (!preview) {
  389. gvs.each {GenericValue gv ->
  390. gv.set("parameter", targetUser)
  391. gv.store()
  392. }
  393. notificationSchemeManager.flushProjectSchemes()
  394. }
  395. // permission schemes
  396. gvs = gd.findByAnd("SchemePermissions", [type: "user", parameter: sourceUser])
  397. msg = "Update ${gvs.size()} SchemePermissions records"
  398. log.debug(msg)
  399. msgs << msg
  400. if (!preview) {
  401. gvs.each {GenericValue gv ->
  402. gv.set("parameter", targetUser)
  403. gv.store()
  404. }
  405. defaultPermissionSchemeManager.flushProjectSchemes()
  406. defaultPermissionSchemeManager.flushSchemeEntities()
  407. }
  408. // issue security schemes
  409. gvs = gd.findByAnd("SchemeIssueSecurities", [type: "user", parameter: sourceUser])
  410. msg = "Update ${gvs.size()} SchemeIssueSecurities records"
  411. log.debug(msg)
  412. msgs << msg
  413. if (!preview) {
  414. gvs.each {GenericValue gv ->
  415. gv.set("parameter", targetUser)
  416. gv.store()
  417. }
  418. securitySchemeManager.flushProjectSchemes()
  419. }
  420. // user and multi-user custom fields
  421. gvs = gd.findByCondition("CustomField",
  422. new EntityExpr("customfieldtypekey", EntityOperator.IN,
  423. [
  424. "com.atlassian.jira.plugin.system.customfieldtypes:userpicker",
  425. "com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker"
  426. ])
  427. ,
  428. ["id"], Collections.<String> emptyList())
  429. Long cfValueKount = 0
  430. gvs.each {GenericValue gv ->
  431. gv.getRelatedByAnd("ChildCustomFieldValue", [stringvalue: sourceUser]).each {GenericValue cfGv ->
  432. cfValueKount++
  433. if (!preview) {
  434. cfGv.set("stringvalue", targetUser)
  435. cfGv.store()
  436. }
  437. reindexIssueIds.add(cfGv.getLong("issue"))
  438. }
  439. }
  440. msg = "Update ${gvs.size()} CustomFieldValue records" // not strictly true
  441. log.debug(msg)
  442. msgs << msg
  443. // possibly todo: update search parameters that refer to user custom fields
  444. // make sure they're not logged on?
  445. // todo: OS_CURRENTSTEP owner, caller, OS_HISTORYSTEP, jiraworkflows
  446. // fileattachments
  447. gvs = gd.findByAnd("FileAttachment", [author: sourceUser])
  448. msg = "Update ${gvs.size()} FileAttachment records"
  449. log.debug(msg)
  450. msgs << msg
  451. if (!preview) {
  452. gvs.each {GenericValue gv ->
  453. gv.set("author", targetUser)
  454. gv.store()
  455. }
  456. }
  457. // -------------------------------------- Finalise --------------------------------------
  458. if (! preview) {
  459. log.debug("Commit transaction")
  460. CoreTransactionUtil.commit(began);
  461. // Only for 4.1 and above - clearing the other caches are not necessary above but kept there if
  462. // I decide to backport this
  463. log.debug("Publish clear cache event")
  464. ComponentManager.getComponentInstanceOfType(EventPublisher.class).publish(ClearCacheEvent.INSTANCE);
  465. // reindex issues
  466. reindexIssueIds.each {Long issueId ->
  467. reindexIssue(issueManager, issueId, log, indexManager);
  468. }
  469. UserManager.getInstance().flushCaches()
  470. user = userManager.getUser(targetUser)
  471. user.getAccessProvider().flushCaches()
  472. user.getProfileProvider().flushCaches()
  473. }
  474. msg = "Reindex ${reindexIssueIds.size()} issues"
  475. log.debug(msg)
  476. msgs << msg
  477. }
  478. catch (Exception e) {
  479. log.error("Problem renaming user, rolling back")
  480. CoreTransactionUtil.rollback(began)
  481. }
  482. finally {
  483. // not sure if we need anything here
  484. }
  485. msgs.join("\n")