Uploaded image for project: 'Dev - Nexus Repo'
  1. Dev - Nexus Repo
  2. NEXUS-15147

Multiple edits of user roles fails with: ConcurrentModificationException: User-role mapping

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 3.6.1, 3.6.2, 3.7.1
    • Fix Version/s: 3.8.0
    • Component/s: LDAP
    • Labels:
    • Story Points:
      2

      Description

      When adding multiple roles to an LDAP user in multiple steps, the second role will fail to save and the UI shows an error like: "Warning: user-role mapping 'USERID' updated in the meantime" 

      Steps to reproduce.

      1. Setup LDAP
      2. Search for (via Source: LDAP, and search box) and Select an LDAP user. 
      3. Add a role from the "Available" list to the "Granted" list. Click Save.
      4. Add a second role from the "Available" list to the "Granted" list. Click Save. Boom! The warning above is shown, and the change is not saved, nor will retries save the change.

      Example:

      After saving first role:

       

      Failed save of second role:

      Support.zip from reproduce case:

      [^support-20171207-145031-1.zip]

      Stack trace:

      2017-12-07 14:45:07,638-0500 ERROR [qtp2112162151-206] admin org.sonatype.nexus.extdirect.internal.ExtDirectServlet - Failed to invoke action method: coreui_User.updateRoleMappings, java-method: org.sonatype.nexus.coreui.UserComponent.updateRoleMappings
      java.util.ConcurrentModificationException: User-role mapping 'elva.kanter' updated in the meantime
      at org.sonatype.nexus.internal.security.model.OrientSecurityConfigurationSource$OrientSecurityConfiguration.concurrentlyModified(OrientSecurityConfigurationSource.java:178)
      at org.sonatype.nexus.internal.security.model.OrientSecurityConfigurationSource$OrientSecurityConfiguration.lambda$18(OrientSecurityConfigurationSource.java:448)
      at org.sonatype.nexus.orient.transaction.OrientOperations.lambda$2(OrientOperations.java:63)
      at org.sonatype.nexus.transaction.OperationPoint.lambda$0(OperationPoint.java:53)
      at org.sonatype.nexus.transaction.OperationPoint.proceed(OperationPoint.java:64)
      at org.sonatype.nexus.transaction.TransactionalWrapper.proceedWithTransaction(TransactionalWrapper.java:56)
      at org.sonatype.nexus.transaction.Operations.transactional(Operations.java:200)
      at org.sonatype.nexus.transaction.Operations.run(Operations.java:155)
      at org.sonatype.nexus.orient.transaction.OrientOperations.run(OrientOperations.java:63)
      at org.sonatype.nexus.internal.security.model.OrientSecurityConfigurationSource$OrientSecurityConfiguration.updateUserRoleMapping(OrientSecurityConfigurationSource.java:442)
      at org.sonatype.nexus.security.internal.SecurityConfigurationManagerImpl.updateUserRoleMapping(SecurityConfigurationManagerImpl.java:258)
      at org.sonatype.nexus.security.internal.UserManagerImpl.setUsersRoles(UserManagerImpl.java:323)
      at org.sonatype.nexus.security.internal.DefaultSecuritySystem.setUsersRoles(DefaultSecuritySystem.java:311)
      at org.sonatype.nexus.security.SecuritySystem$setUsersRoles$2.call(Unknown Source)
      at org.sonatype.nexus.coreui.UserComponent.updateRoleMappings(UserComponent.groovy:209)
      at com.palominolabs.metrics.guice.ExceptionMeteredInterceptor.invoke(ExceptionMeteredInterceptor.java:49)
      at com.palominolabs.metrics.guice.TimedInterceptor.invoke(TimedInterceptor.java:47)
      at org.sonatype.nexus.validation.internal.ValidationInterceptor.invoke(ValidationInterceptor.java:53)
      at org.apache.shiro.guice.aop.AopAllianceMethodInvocationAdapter.proceed(AopAllianceMethodInvocationAdapter.java:49)
      at org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor.invoke(AuthorizingAnnotationMethodInterceptor.java:68)
      at org.apache.shiro.guice.aop.AopAllianceMethodInterceptorAdapter.invoke(AopAllianceMethodInterceptorAdapter.java:36)
      at org.apache.shiro.guice.aop.AopAllianceMethodInvocationAdapter.proceed(AopAllianceMethodInvocationAdapter.java:49)
      at org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor.invoke(AuthorizingAnnotationMethodInterceptor.java:68)
      at org.apache.shiro.guice.aop.AopAllianceMethodInterceptorAdapter.invoke(AopAllianceMethodInterceptorAdapter.java:36)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at com.softwarementors.extjs.djn.router.dispatcher.DispatcherBase.invokeJavaMethod(DispatcherBase.java:142)
      at com.softwarementors.extjs.djn.router.dispatcher.DispatcherBase.invokeMethod(DispatcherBase.java:133)
      at org.sonatype.nexus.extdirect.internal.ExtDirectServlet$3.invokeMethod(ExtDirectServlet.java:233)
      at com.softwarementors.extjs.djn.router.dispatcher.DispatcherBase.dispatch(DispatcherBase.java:63)
      at com.softwarementors.extjs.djn.router.processor.standard.StandardRequestProcessorBase.dispatchStandardMethod(StandardRequestProcessorBase.java:73)
      at com.softwarementors.extjs.djn.router.processor.standard.json.JsonRequestProcessor.processIndividualRequest(JsonRequestProcessor.java:502)
      at com.softwarementors.extjs.djn.router.processor.standard.json.JsonRequestProcessor.processIndividualRequestsInThisThread(JsonRequestProcessor.java:150)
      at com.softwarementors.extjs.djn.router.processor.standard.json.JsonRequestProcessor.process(JsonRequestProcessor.java:133)
      at com.softwarementors.extjs.djn.router.RequestRouter.processJsonRequest(RequestRouter.java:83)
      at com.softwarementors.extjs.djn.servlet.DirectJNgineServlet.processRequest(DirectJNgineServlet.java:617)
      at com.softwarementors.extjs.djn.servlet.DirectJNgineServlet.doPost(DirectJNgineServlet.java:580)
      at org.sonatype.nexus.extdirect.internal.ExtDirectServlet.doPost(ExtDirectServlet.java:138)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
      at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:286)
      at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:276)
      at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:181)
      at com.google.inject.servlet.DynamicServletPipeline.service(DynamicServletPipeline.java:71)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)
      at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:112)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
      at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
      at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
      at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
      at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
      at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
      at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
      at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
      at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
      at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
      at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
      at org.sonatype.nexus.security.SecurityFilter.executeChain(SecurityFilter.java:85)
      at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
      at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
      at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
      at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
      at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
      at org.sonatype.nexus.security.SecurityFilter.doFilterInternal(SecurityFilter.java:101)
      at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
      at com.sonatype.nexus.licensing.internal.LicensingRedirectFilter.doFilter(LicensingRedirectFilter.java:108)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
      at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:97)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
      at org.sonatype.nexus.internal.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:68)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
      at org.sonatype.nexus.internal.web.EnvironmentFilter.doFilter(EnvironmentFilter.java:102)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
      at org.sonatype.nexus.internal.web.HeaderPatternFilter.doFilter(HeaderPatternFilter.java:98)
      at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
      at com.google.inject.servlet.DynamicFilterPipeline.dispatch(DynamicFilterPipeline.java:104)
      at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:135)
      at org.sonatype.nexus.bootstrap.osgi.DelegatingFilter.doFilter(DelegatingFilter.java:73)
      at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1751)
      at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:582)
      at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
      at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
      at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
      at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
      at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512)
      at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
      at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
      at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
      at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
      at com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:175)
      at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
      at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
      at org.eclipse.jetty.server.Server.handle(Server.java:534)
      at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
      at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
      at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283)
      at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108)
      at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
      at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
      at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
      at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
      at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
      at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
      at java.lang.Thread.run(Thread.java:748)
      

      Short term workaround for affected versions

      A short term workaround should allow you to make role assignment changes if you can't immediately upgrade:

      1. Make a note of all the currently assigned Roles for the user. Remove all assigned roles, click 'Save'. The user should have no roles at this point.
      2. Add all Roles you want for the user, click 'Save'. There should be no errors.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              jbryan Jeremy Bryan
              Reporter:
              slosey Scott Losey
              Last Updated By:
              Peter Lynch
              Team:
              Nexus - Core
              Votes:
              1 Vote for this issue
              Watchers:
              11 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Date of First Response:

                  tigCommentSecurity.panel-title