IssueManager.updateIssue() does not update Portfolio fields if user does not have edit permission

I am using IssueManager.updateIssue() method to update date fields on an issue. The documentation below states that this method does not check user permissions.

https://docs.atlassian.com/software/jira/docs/api/7.6.1/com/atlassian/jira/issue/IssueManager.html#updateIssue-com.atlassian.jira.user.ApplicationUser-com.atlassian.jira.issue.MutableIssue-com.atlassian.jira.issue.UpdateIssueRequest-

Indeed this method can update an issue even the given user does not have Edit permission.

The thing is, if the updated field is one of Target Start or Target End fields (introduced by Jira Portfolio) and the user does not have Edit permission, I get an IllegalArgumentException while trying to update these fields.

Are these fields running their own permission checks or is this a bug?

Below is the stacktrace of the exception:

Jira Version : 8.2.3
Portfolio Version : 3.10.0

Stack Trace :

2019-10-16 14:20:11,965 http-nio-8060-exec-17 DEBUG ceren 860x2226x1 49yytq 0:0:0:0:0:0:0:1 /rest/tempo-planning/1/allocation/20 [t.c.o.p.a.services.issue.IssueServiceImpl] Allocation Updated - issueId 12400 JIS-302, planUser ceren, updater ceren, startTime 2019-10-04, endTime 2019-10-23, dailyCommitmentInSeconds 3856, includeNonWorkingDays false
2019-10-16 14:20:11,968 http-nio-8060-exec-17 DEBUG ceren 860x2226x1 49yytq 0:0:0:0:0:0:0:1 /rest/tempo-planning/1/allocation/20 [t.c.o.p.autoplan.tempo.EforPlanTempoListener] Completed CreateOrUpdateIssueBasedOnAllocation.
2019-10-16 14:20:11,968 http-nio-8060-exec-17 ERROR ceren 860x2226x1 49yytq 0:0:0:0:0:0:0:1 /rest/tempo-planning/1/allocation/20 [c.a.event.internal.AsynchronousAbleEventDispatcher] There was an exception thrown trying to dispatch event [AllocationUpdatedEventAllocationDtoImpl{id=20, parent=null, planItemId=12400, planItemType=ISSUE, assigneeKey=ceren, assigneeType=USER, description=BugTest-1 UpdateFiedl
, secondsPerDay=3856, shouldIncludeNonWorkingDays=false, creatorKey=ceren, updaterKey=ceren, startDate=2019-10-04, endDate=2019-10-23, recurrenceEndDate=2019-10-23, rule=NEVER}] from the invoker [SingleParameterMethodListenerInvoker{method=public void tr.com.obss.plugin.autoplan.tempo.impl.EforPlanTempoListenerImpl.onAllocationUpdatedEvent(com.tempoplugin.planner.api.event.AllocationUpdatedEvent), listener=tr.com.obss.plugin.autoplan.tempo.impl.EforPlanTempoListenerImpl@654a7be7}]
java.lang.RuntimeException: Listener: tr.com.obss.plugin.autoplan.tempo.impl.EforPlanTempoListenerImpl event: com.tempoplugin.planner.api.event.AllocationUpdatedEvent
at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:50)
at com.atlassian.event.internal.AsynchronousAbleEventDispatcher.lambda$null$0(AsynchronousAbleEventDispatcher.java:37)
at com.atlassian.event.internal.AsynchronousAbleEventDispatcher.dispatch(AsynchronousAbleEventDispatcher.java:85)
at com.atlassian.event.internal.EventPublisherImpl.invokeListeners(EventPublisherImpl.java:200)
at com.atlassian.event.internal.EventPublisherImpl.publish(EventPublisherImpl.java:115)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
at com.sun.proxy.$Proxy331.publish(Unknown Source)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy2399.publish(Unknown Source)
at com.tempoplugin.platform.jira.event.JiraEventPublisher.publish(JiraEventPublisher.java:15)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy4001.publish(Unknown Source)
at com.tempoplugin.jira.plan.core.impl.AllocationServiceImpl.update(AllocationServiceImpl.java:382)
at com.tempoplugin.jira.plan.core.impl.AllocationServiceImpl.updateAllocation(AllocationServiceImpl.java:306)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.activeobjects.tx.TransactionalProxy.invoke(TransactionalProxy.java:60)
at com.atlassian.activeobjects.tx.TransactionalProxy.access$000(TransactionalProxy.java:18)
at com.atlassian.activeobjects.tx.TransactionalProxy$1.doInTransaction(TransactionalProxy.java:49)
at com.atlassian.sal.core.transaction.HostContextTransactionTemplate$1.doInTransaction(HostContextTransactionTemplate.java:21)
at com.atlassian.jira.DefaultHostContextAccessor.doInTransaction(DefaultHostContextAccessor.java:50)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
at com.sun.proxy.$Proxy262.doInTransaction(Unknown Source)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:131)
at com.sun.proxy.$Proxy262.doInTransaction(Unknown Source)
at com.atlassian.sal.core.transaction.HostContextTransactionTemplate.execute(HostContextTransactionTemplate.java:18)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy1080.execute(Unknown Source)
at com.atlassian.activeobjects.internal.SalTransactionManager.inTransaction(SalTransactionManager.java:42)
at com.atlassian.activeobjects.internal.AbstractLoggingTransactionManager.doInTransaction(AbstractLoggingTransactionManager.java:16)
at com.atlassian.activeobjects.internal.EntityManagedActiveObjects.executeInTransaction(EntityManagedActiveObjects.java:204)
at com.atlassian.activeobjects.osgi.TenantAwareActiveObjects.executeInTransaction(TenantAwareActiveObjects.java:349)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy3913.executeInTransaction(Unknown Source)
at com.atlassian.activeobjects.tx.TransactionalProxy.executeInTransaction(TransactionalProxy.java:46)
at com.atlassian.activeobjects.tx.TransactionalProxy.invokeInTransaction(TransactionalProxy.java:39)
at com.atlassian.activeobjects.tx.TransactionalProxy.invoke(TransactionalProxy.java:31)
at com.sun.proxy.$Proxy4094.updateAllocation(Unknown Source)
at com.tempoplugin.jira.plan.core.rest.AllocationResource.updateAllocation(AllocationResource.java:316)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
… 19 filtered
at com.atlassian.plugins.rest.module.RestDelegatingServletFilter$JerseyOsgiServletContainer.doFilter(RestDelegatingServletFilter.java:159)
… 1 filtered
at com.atlassian.plugins.rest.module.RestDelegatingServletFilter.doFilter(RestDelegatingServletFilter.java:69)
… 32 filtered
at com.atlassian.servicedesk.internal.web.ExternalCustomerLockoutFilter.doFilter(ExternalCustomerLockoutFilter.java:55)
… 13 filtered
at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21)
… 57 filtered
at com.atlassian.jira.security.JiraSecurityFilter.lambda$doFilter$0(JiraSecurityFilter.java:66)
… 1 filtered
at com.atlassian.jira.security.JiraSecurityFilter.doFilter(JiraSecurityFilter.java:64)
… 16 filtered
at com.atlassian.plugins.rest.module.servlet.RestSeraphFilter.doFilter(RestSeraphFilter.java:37)
… 19 filtered
at com.atlassian.jira.servermetrics.CorrelationIdPopulatorFilter.doFilter(CorrelationIdPopulatorFilter.java:30)
… 5 filtered
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.lambda$invokeFilterChain$0(CustomerContextSettingFilter.java:183)
at com.atlassian.servicedesk.internal.api.util.context.ReentrantThreadLocalBasedCodeContext.rteInvoke(ReentrantThreadLocalBasedCodeContext.java:136)
at com.atlassian.servicedesk.internal.api.util.context.ReentrantThreadLocalBasedCodeContext.runOutOfContext(ReentrantThreadLocalBasedCodeContext.java:89)
at com.atlassian.servicedesk.internal.utils.context.CustomerContextServiceImpl.runOutOfCustomerContext(CustomerContextServiceImpl.java:47)
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.outOfCustomerContext(CustomerContextSettingFilter.java:174)
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.doFilterImpl(CustomerContextSettingFilter.java:126)
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.doFilter(CustomerContextSettingFilter.java:115)
… 4 filtered
at com.atlassian.jwt.internal.servlet.JwtAuthFilter.doFilter(JwtAuthFilter.java:37)
… 8 filtered
at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21)
… 4 filtered
at com.atlassian.web.servlet.plugin.LocationCleanerFilter.doFilter(LocationCleanerFilter.java:36)
… 26 filtered
at com.atlassian.jira.servermetrics.MetricsCollectorFilter.doFilter(MetricsCollectorFilter.java:25)
… 25 filtered
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:127)
at com.atlassian.jira.entity.property.BaseEntityPropertyService.setProperty(BaseEntityPropertyService.java:96)
at com.atlassian.jira.entity.property.DelegatingEntityPropertyService.setProperty(DelegatingEntityPropertyService.java:41)
at sun.reflect.GeneratedMethodAccessor1412.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
at com.sun.proxy.$Proxy601.setProperty(Unknown Source)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:131)
at com.sun.proxy.$Proxy601.setProperty(Unknown Source)
at com.atlassian.rm.common.bridges.jira.issue.properties.IssuePropertyServiceBridge80.setProperty(IssuePropertyServiceBridge80.java:56)
at com.atlassian.rm.common.env.issues.JiraIssuePropertyService.setProperty(JiraIssuePropertyService.java:263)
at com.atlassian.rm.common.env.issues.JiraIssuePropertyService.set(JiraIssuePropertyService.java:104)
at com.atlassian.rm.jpo.customfields.common.IssuePropertyCustomFieldValuePersister.updateValues(IssuePropertyCustomFieldValuePersister.java:84)
at com.atlassian.jira.issue.customfields.impl.AbstractSingleFieldType.updateValue(AbstractSingleFieldType.java:151)
at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:426)
at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:396)
at com.atlassian.jira.issue.managers.DefaultIssueManager.updateFieldValues(DefaultIssueManager.java:723)
at com.atlassian.jira.issue.managers.DefaultIssueManager.updateIssue(DefaultIssueManager.java:676)
at com.atlassian.jira.issue.managers.RequestCachingIssueManager.updateIssue(RequestCachingIssueManager.java:220)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
at com.sun.proxy.$Proxy389.updateIssue(Unknown Source)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:131)
at com.sun.proxy.$Proxy389.updateIssue(Unknown Source)
at tr.com.obss.plugin.autoplan.services.issue.IssueServiceImpl.persistIssueUpdates(IssueServiceImpl.java:182)
at tr.com.obss.plugin.autoplan.services.issue.IssueServiceImpl.updateIssueFieldsAccordingToPlanData(IssueServiceImpl.java:134)
at tr.com.obss.plugin.autoplan.tempo.impl.EforPlanTempoListenerImpl.CreateOrUpdateIssueBasedOnAllocation(EforPlanTempoListenerImpl.java:275)
at tr.com.obss.plugin.autoplan.tempo.impl.EforPlanTempoListenerImpl.onAllocationUpdatedEvent(EforPlanTempoListenerImpl.java:226)
… 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:40)
… 376 more
2019-10-16 14:21:23,883 http-nio-8060-exec-1 INFO ceren 861x2240x1 49yytq 0:0:0:0:0:0:0:1 /browse/JIS-302 [c.a.jira.index.MonitoringIndexWriter] [lucene-stats] flush stats: snapshotCount=8, totalCount=66, periodSec=1681, flushIntervalMillis=210133, indexDirectory=/var/atlassian/application-data/jira-8.2.3/caches/indexesV1/issues, indexWriterId=com.atlassian.jira.index.MonitoringIndexWriter@65beb368, indexDirectoryId=MMapDirectory@/var/atlassian/application-data/jira-8.2.3/caches/indexesV1/issues lockFactory=org.apache.lucene.store.NativeFSLockFactory@7ac1dcb2

I’m also running into this issue, but only if I run this operation within a new thread strangely. Have you figured this out?