Details
-
Bug
-
Resolution: Fixed
-
Medium
-
Severity 3 - Minor
-
Description
Issue Summary
Copying a page with restrictions using the Copy single page (POST /wiki/rest/api/content/{id}/copy) REST API endpoint fails (returning status code 500 - Internal Server Error) when specifying a target page to overwrite and copying the restrictions.
Everything seems to be working fine if you either copy to a new page or you don't copy the page restrictions.
Steps to Reproduce
- Create a new page with restrictions
- Use the Copy page REST API endpoint to create a new copy of the page (specifying the parent). See that this works fine:
curl -u <EMAIL-ADDRESS>:<API-TOKEN> -X POST -H "Content-Type: application/json" -d '\{"destination":{"type":"parent_page","value":"{parent_id}"}, "copyPermissions":"true", "pageTitle":"copy name"}' 'https://NAME.atlassian.net/wiki/rest/api/content/\{id}/copy'
- Edit the page
- Copy the page again using the same REST API endpoint, but now try to replace an existing page (e.g. the copy we just created in step #2):
curl -u <EMAIL-ADDRESS>:<API-TOKEN> {{-X POST -H "Content-Type: application/json" -d '\{"destination":{"type":"existing_page","value":"{copy_id}"}, "copyPermissions":"true", "pageTitle":"copy name"}' }}{{'https://NAME.atlassian.net/wiki/rest/api/content/\{id}/copy'
Expected Results
The destination page is successfully overwritten with a copy of the source page
Actual Results
The REST API call fails returning status code 500:
{"statusCode":500,"message":"java.lang.NullPointerException: null"}
The below exception is thrown in the logs:
2021-11-03 18:24:59.166 WARN com.atlassian.confluence.rest.api.model.ExceptionConverter Could not map exception type java.lang.NullPointerException to a specific REST status. Defaulting to InternalServerError stack: java.lang.NullPointerException: com.atlassian.confluence.core.persistence.hibernate.HibernateObjectDao.updateModificationData(HibernateObjectDao.java:197) com.atlassian.confluence.core.persistence.hibernate.HibernateObjectDao.save(HibernateObjectDao.java:184) com.atlassian.confluence.core.DefaultInternalContentPermissionManager.doAddContentPermission(DefaultInternalContentPermissionManager.java:56) com.atlassian.confluence.core.MonitoringInternalContentPermissionManager.lambda$doAddContentPermission$0(MonitoringInternalContentPermissionManager.java:28) com.atlassian.confluence.core.MonitoringInternalContentPermissionManager.withTiming(MonitoringInternalContentPermissionManager.java:48) com.atlassian.confluence.core.MonitoringInternalContentPermissionManager.doAddContentPermission(MonitoringInternalContentPermissionManager.java:28) com.atlassian.confluence.core.DefaultContentPermissionManager.addContentPermission(DefaultContentPermissionManager.java:294) com.atlassian.confluence.core.AuthzContentPermissionManager.addContentPermission(AuthzContentPermissionManager.java:48) com.atlassian.confluence.core.MonitoringContentPermissionManager.lambda$addContentPermission$4(MonitoringContentPermissionManager.java:109) com.atlassian.confluence.core.MonitoringContentPermissionManager.withTiming(MonitoringContentPermissionManager.java:192) com.atlassian.confluence.core.MonitoringContentPermissionManager.addContentPermission(MonitoringContentPermissionManager.java:109) com.atlassian.confluence.core.SuperAdminContentPermissionManager.addContentPermission(SuperAdminContentPermissionManager.java:164) java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.base/java.lang.reflect.Method.invoke(Method.java:566) org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) com.sun.proxy.$Proxy87.addContentPermission(Unknown Source) com.atlassian.confluence.core.AppAccessContentPermissionManager.addContentPermission(AppAccessContentPermissionManager.java:158) com.atlassian.confluence.pages.persistence.dao.bulk.copy.DefaultPageCopyService.copyContentPermissionSet(DefaultPageCopyService.java:758) com.atlassian.confluence.pages.persistence.dao.bulk.copy.DefaultPageCopyService.lambda$copyOtherEntities$14(DefaultPageCopyService.java:629) com.atlassian.confluence.pages.persistence.dao.bulk.copy.DefaultPageCopyService.safeAction(DefaultPageCopyService.java:499) com.atlassian.confluence.pages.persistence.dao.bulk.copy.DefaultPageCopyService.copyOtherEntities(DefaultPageCopyService.java:611) com.atlassian.confluence.pages.persistence.dao.bulk.copy.DefaultPageCopyService.saveAsNewVersion(DefaultPageCopyService.java:876) com.atlassian.confluence.pages.persistence.dao.bulk.copy.DefaultPageCopyService.copyPage(DefaultPageCopyService.java:545) com.atlassian.confluence.pages.persistence.dao.bulk.copy.DefaultPageCopyService.copyAsVersionToExistingPage(DefaultPageCopyService.java:300)
Workaround
Either copy to a new page or remove "copyPermissions":"true" from the request body.