Uploaded image for project: 'Confluence Data Center'
  1. Confluence Data Center
  2. CONFSERVER-80107

Space import from Cloud to onPrem violates the unique constraint on user_mapping.lower_username

    XMLWordPrintable

Details

    Description

      Issue Summary

      When a Space is imported from Cloud to Server, the import logic compares user "lowerName" from Space XML with "lower_email_address" from cwd_user. When it finds more than one record for that email adress with different "lower_user_name" it marks it as Ambigous. Then it tries to create to create a new record on user_mapping. In case already exist a user on user_mapping using theat email as username it will fail.

      Steps to Reproduce

      1. In Confluence server have multiple users (different "lower_user_name") on cwd_user but same "lower_email_address", and one of them has "lower_user_name" equals to user "lowerName" from Space XML:
        user_name lower_user_name lower_email_address external ID Directory ID
        admin admin user@example.com 937c9532-f12f-437b-a8fd-7e9e0e8d8e69 294913
        example example user@example.com 86782f67-5bc1-4818-9326-a9bc63eeccb3 8126465
        user@example.com user@example.com user@example.com 458af6bc-40ae-49ae-9dff-7528d854836e 8126466
      2. user_mapping table has a record with a username equals to user "lowerName" from Space XML:
        user_key username lower_username
        402880847157f278017157f699530000 user@example.com user@example.com
      3. Import a Space from Cloud where one of the users "lowerName" is equals to a "lower_email_address" and "lower_user_name" on cwd_user and already have a record on user_mapping:
        Cloud's XML export
        <object class="ConfluenceUserImpl" package="com.atlassian.confluence.user">
        <id name="key"><![CDATA[8a7f808564e27fae0164d4db118d0064]]></id>
        <property name="name"><![CDATA[user@example.com]]></property>
        <property name="lowerName"><![CDATA[user@example.com]]></property>
        <property name="atlassianAccountId"><![CDATA[5a0bbaa80e8b4605b373d809]]></property>
        </object>
        

      Expected Results

      Confluence should recognise that the imported user already exist on cwd_user using "lower_user_name" to avoid mark it as Ambigous, and use the user_mapping record to reference the content.

      Actual Results

      During the import, will mark user as Ambiguous, the error below can be seen in the atlassian-confluence.log:

      2022-09-30 19:22:19,778 WARN [Long running task: Importing data] [importexport.xmlimport.persister.ConfluenceUserPersister] persist Ambiguous result while trying to match user by email address. An Unknown User will be created for email [user@example.com] entry.
       -- url: /admin/restore-local-file.action | referer: https://REDACTED/admin/backup.action | traceId: 18379ec1e4340077 | userName: admin@example.com | action: restore-local-file
      

      Confluence will try to add a new row (user) into user_mapping which will eventually result into violation of the unique constraint on user_mapping.lower_username, as record already exists:

      2022-10-01 16:23:36,162 ERROR [Long running task: Importing data] [confluence.importexport.xmlimport.BackupImporter] importEntities Cannot import the entities: 
       -- url: /admin/restore.action | referer: https://REDACTED/admin/backup.action | traceId: ab6a55fcf1679389 | userName: redacted@example.com | action: restore
      com.atlassian.confluence.importexport.ImportExportException: Unable to complete import: Error while importing backup: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
      	at com.atlassian.confluence.importexport.xmlimport.DefaultXmlImporter.doImportInternal(DefaultXmlImporter.java:68)
      	...
      	at java.base/java.lang.Thread.run(Unknown Source)
      Caused by: org.xml.sax.SAXException: Error while importing backup: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
      org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
      	at com.atlassian.confluence.importexport.xmlimport.parser.BackupParser.endElement(BackupParser.java:47)
      	...
      	... 41 more
      Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
      	at org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:212)
      	...
      	... 93 more
      Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot insert duplicate key row in object 'dbo.user_mapping' with unique index 'user_mapping_unq_lwr_username'. The duplicate key value is (redacted@example.com).
      	at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:262)
      	at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1624)
      	at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:594)
      	at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:524)
      	at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7194)
      	at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2979)
      	at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:248)
      	at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:223)
      	at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:473)
      	at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:1502)
      	at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
      	... 107 more
      

      Workaround

      1. Identify the user record that is in User, temporaly change the email addresses of the of other records. It can be done by UI if users are from Internal User Directory or by LDAP.
      2. Import Spaces again
      3. Change emails address back

      Attachments

        Issue Links

          Activity

            People

              f8dbc9c9ac45 Anshul Chokhani
              d572fd45fe13 Marcio Ribeiro
              Votes:
              3 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

                Created:
                Updated: