sorry
in xwiki-contrib-confluence\confluence-xml\src\main\java\org\xwiki\contrib\confluence\filter\input\ConfluenceXMLPackage.java I’ve added some code in order to process the Contentpermissions
in xwiki-contrib-confluence\confluence-xml\src\main\java\org\xwiki\contrib\confluence\filter\internal\input\ConfluenceInputFilterStream.java I added some code to “readInternal” to convert all those confluence stuff into xWiki-Objects
private void readInternal(Object filter, ConfluenceFilter proxyFilter) throws FilterException
{
// Prepare package
try {
this.confluencePackage.read(this.properties.getSource());
} catch (Exception e) {
throw new FilterException("Failed to read package", e);
}
Map<Long, List<Long>> pages = this.confluencePackage.getPages();
if (this.properties.isUsersEnabled()) {
Collection<Long> users = this.confluencePackage.getInternalUsers();
// TODO get users in new format (this.confluencePackage.getAllUsers())
Collection<Long> groups = this.confluencePackage.getGroups();
this.progress.pushLevelProgress(users.size() + groups.size() + pages.size()
+ pages.entrySet().stream().mapToInt(e -> e.getValue().size()).sum(), this);
sendUsers(users, groups, proxyFilter);
} else {
this.progress.pushLevelProgress(
pages.size() + pages.entrySet().stream().mapToInt(e -> e.getValue().size()).sum(), this);
}
// Generate documents events
for (Map.Entry<Long, List<Long>> entry : pages.entrySet()) {
long spaceId = entry.getKey();
ConfluenceProperties spaceProperties;
try {
spaceProperties = this.confluencePackage.getSpaceProperties(spaceId);
} catch (ConfigurationException e) {
throw new FilterException("Failed to get space properties", e);
}
String spaceKey = toEntityName(ConfluenceXMLPackage.getSpaceKey(spaceProperties));
FilterEventParameters spaceParameters = new FilterEventParameters();
// **@baerthlein Start**
Collection<Long> spacePermissions = this.confluencePackage.getSpacePermissions(spaceId);
//if (this.properties.isUsersEnabled())
// create groups and users in order to assign spacepermissions later on
try {
**sendSpacePermissionUsersAndGroups(spaceId, spacePermissions, proxyFilter);**
}
catch (FilterException e) {
logger.error("Problem creating groups and users from confluence space permissions (space-Id: "+spaceId+")", e);
}
// > WikiSpace
proxyFilter.beginWikiSpace(spaceKey, spaceParameters);
// Main page
StringBuilder script = new StringBuilder();
Long descriptionId = spaceProperties.getLong(ConfluenceXMLPackage.KEY_SPACE_DESCRIPTION, null);
if (descriptionId != null) {
this.progress.startStep(this);
if (this.properties.isIncluded(descriptionId)) {
**readPage(descriptionId, spaceKey, filter, proxyFilter, script);**
}
this.progress.endStep(this);
}
// Other pages
for (long pageId : entry.getValue()) {
this.progress.startStep(this);
if (this.properties.isIncluded(pageId)) {
**readPage(pageId, spaceKey, filter, proxyFilter, script);**
}
this.progress.endStep(this);
}
**// workaround building velocity script**
if (script.length() > 0){
script.insert(0, "{{velocity}}\n").append("{{/velocity}}\n");
String filename = this.environment.getTemporaryDirectory().toPath() + "/pagerestriction-script-"+spaceKey+".vm";
FileOutputStream fileStream = null;
try {
fileStream = new FileOutputStream(filename);
fileStream.write(script.toString().getBytes());
fileStream.flush();
fileStream.close();
this.logger.info("Created pagerestriction-script: " + filename);
} catch (FileNotFoundException e) {
logger.error("File not found error writing pagerestriction-script: " + filename, e);
} catch (IOException e) {
logger.error("IO-error writing pagerestriction-script: " + filename, e);
}
}
try {
// Problems with NPE seems that I'm unable to manipulate a simple xObject???
//sendSpacePermissions(proxyFilter, spaceId, spacePermissions);
// seems there is no xxx.WebPreferences Document so a NPE is thrown
// create a new xxx.WebPreferences
// > WikiDocument
**String webPreferences = "WebPreferences";** // in the context of parent node of this space //spaceKey + ".WebPreferences"; // eg. TESTARGESPACE02.WebPreferences
// FilterEventParameters documentParameters = new FilterEventParameters();
proxyFilter.beginWikiDocument(webPreferences, FilterEventParameters.EMPTY /*documentParameters*/);
// now it should be possible to persist global permissions into this WebPreferences-document
createSpacePermissionsImportScript(spaceId, spaceKey, spacePermissions, proxyFilter);
// < WikiDocument
proxyFilter.endWikiDocument(webPreferences, FilterEventParameters.EMPTY /*documentParameters*/);
}
catch (FilterException e) {
logger.error("Error creating spacepermissions-script (space-Id: "+spaceId+") ", e);
}
// < WikiSpace
proxyFilter.endWikiSpace(spaceKey, spaceParameters);
}
this.progress.popLevelProgress(this);
// Cleanup
try {
this.confluencePackage.close();
} catch (IOException e) {
throw new FilterException("Failed to close package", e);
}
}
trying to convert confluence space permissions (there may be falsy code for checking things are existing aso)
/**
* Extracts all groups and users from the confluence spacepermissions and if not existing creates them
* @param spaceId Id of the space containing the permissions
* @param spacePermissions Collection of spacePermissions (properties)
* @param proxyFilter Filter doing the input output convertion
* @throws FilterException if Exception occurs logs them
*/
private void sendSpacePermissionUsersAndGroups(long spaceId, Collection<Long> spacePermissions, ConfluenceFilter proxyFilter)
throws FilterException {
List<String> uniqueUsernames = new ArrayList<>();
List<String> uniqueGroupnames = new ArrayList<>();
for (Long spacePermissionId : spacePermissions) {
this.progress.startStep(this);
ConfluenceProperties spacePermissionProperties;
try {
spacePermissionProperties = this.confluencePackage.getSpacePermissionProperties(spaceId, spacePermissionId);
} catch (ConfigurationException e) {
throw new FilterException("Failed to get space-permission properties for space-Id: "+ spaceId +" and permission-Id: "+spacePermissionId, e);
}
// Seems that 1 Permission is always assign to 1 group our 1 user
String groupName = spacePermissionProperties.getString(ConfluenceXMLPackage.SPACEPERMISSION_GROUP, "");
String useSubject = spacePermissionProperties.getString(ConfluenceXMLPackage.SPACEPERMISSION_USER, "");
String anonymous = spacePermissionProperties.getString(ConfluenceXMLPackage.SPACEPERMISSION_ANONYMOUS, "");
if (StringUtils.isNoneEmpty(groupName)){
if (uniqueGroupnames.contains(groupName))
continue;
if (isExistingGroup(groupName)){
uniqueGroupnames.add(groupName);
continue;
}
sendSpacePermissionGroups(proxyFilter, uniqueGroupnames, groupName);
uniqueGroupnames.add(groupName);
logger.info("Created group: " + groupName + " from spacerpermissions.");
}
else if (StringUtils.isNoneEmpty(useSubject)) {
try {
ConfluenceProperties userImplProperties = this.confluencePackage.getUserImplProperties(useSubject);
String lowerName = userImplProperties.getString(ConfluenceXMLPackage.USERIMPL_LOWERNAME, "");
String xWikiUsername = lowerName;
if (this.properties.isConvertToXWiki()) {
if (lowerName.equals("admin")) {
xWikiUsername = "Admin";
}
}
if (uniqueUsernames.contains(lowerName))
continue;
if (isExistingUser(xWikiUsername)){
uniqueUsernames.add(lowerName);
continue;
}
sendSpacePermissionUsers(proxyFilter, userImplProperties, lowerName);
uniqueUsernames.add(lowerName);
logger.info("Created user: " + lowerName + " from spacerpermissions.");
}
catch (ConfigurationException e) {
throw new FilterException("Failed to get UserImpl properties for user-key: "+ useSubject, e);
}
}
// Anonymous won't be migrated
else if (StringUtils.isNoneEmpty(anonymous)) {
continue;
}
this.progress.endStep(this);
}
}
the creationg of groups and users - I’m not sure if it would be sufficient if I create only the permissions or it there also have to be groups and users as well (anyhow, could reuse this code for a later user-sync script…)
/**
* Creates groups if it does not exists
* @param proxyFilter Filter doing input/output convertion
* @param uniqueGroupnames Collection checking for unique groupnames (beeing extracted from the confluence space permissions)
* @param groupname current groupname
* @return true = group exists, false = group does not exist
* @throws FilterException Convertion Error
*/
private boolean sendSpacePermissionGroups(ConfluenceFilter proxyFilter, List<String> uniqueGroupnames, String groupname) throws FilterException {
// only create unique, not existing groups
if (uniqueGroupnames.contains(groupname) ||
StringUtils.isEmpty(groupname) ||
documentAccessBridge.exists(XWiki.SYSTEM_SPACE + "." + groupname)) {// check if group / document / pagereference exists
this.progress.endStep(this);
return true;
}
uniqueGroupnames.add(groupname);
FilterEventParameters groupParameters = new FilterEventParameters();
// > Group
proxyFilter.beginGroupContainer(groupname, groupParameters);
// < Group
proxyFilter.endGroupContainer(groupname, groupParameters);
return false;
}
create user
/**
* Creates user if not existing
*
* @param proxyFilter Filter doing the iput / output convertion
* @param userImplProperties Internal confluence user-Id (GDPR obfuscated)
* @param lowerName lower username
* @throws FilterException convertion error
*/
private void sendSpacePermissionUsers(ConfluenceFilter proxyFilter, ConfluenceProperties userImplProperties, String lowerName) throws FilterException {
String email = userImplProperties.getString(ConfluenceXMLPackage.USERIMPL_EMAIL, "");
FilterEventParameters userParameters = new FilterEventParameters();
userParameters.put(UserFilter.PARAMETER_FIRSTNAME, lowerName);
userParameters.put(UserFilter.PARAMETER_LASTNAME, lowerName);
userParameters.put(UserFilter.PARAMETER_EMAIL, email);
userParameters.put(UserFilter.PARAMETER_ACTIVE,true); // all users should be activated per default
// TODO: no idea how to import/convert the password, probably salted with the Confluence instance id
// > User
proxyFilter.beginUser(lowerName, userParameters);
// < User
proxyFilter.endUser(lowerName, userParameters);
}
for the pagerestrictions i’ve used some ugly code wihtout refactoring, anyhow it comes done to probably this snippets
/**
* Reads the confluence pagepermissions and assignes "view" or "edit" (= view, edit, comment, delete) to users and
* groups like set in the space-export (if users or groups do not exist, they won't be created - xWiki permissions
* will work as soon as the users and groups have been created).
* <strong>The xWiki-Permissions are set via the document's XWiki.XWikiRights class and are visible in the edit object mode,
* they won't shine up in the page-permissions for some reasons (perhaps index problem)?</strong>
*
* @param pageProperties Currents Pageproperties
* @param proxyFilter valid confluence filter
* @param script the internally created Velocity script
* @throws FilterException Error during reading or setting pageproperties / document
*/
private void readPageRestrictions(ConfluenceProperties pageProperties, ConfluenceFilter proxyFilter, StringBuilder script) throws FilterException {
String objectName = getObjectName(pageProperties); // eg. ITInfo.WebHome
Map<String, String> userPermissions = new HashMap<>();
Map<String, String> groupPermissions = new HashMap<>();
// confluence content permission set - should be max size = 2 (1x view + 1x edit)
for (Object commentIdStringObject : pageProperties.getList(ConfluenceXMLPackage.CONTENT_PERMISSION_SETS)) {
long contentPermissionSetId = Long.parseLong((String) commentIdStringObject);
ConfluenceProperties contentPermissionSetProps;
try {
contentPermissionSetProps = this.confluencePackage.getObjectProperties(contentPermissionSetId);
} catch (ConfigurationException e) {
throw new FilterException("Failed to get contentpermissionsets properties for: " +contentPermissionSetId, e);
}
// within every view- or edit-set there are the permissions stored and assigned to user and groups
// each permission is assigned to only 1 user or 1 group
final List<Object> contentPermissions = contentPermissionSetProps.getList(ConfluenceXMLPackage.CONTENT_PERMISSIONS);
for (Object permissionIdStringObject : contentPermissions) {
long permissionId = Long.parseLong((String) permissionIdStringObject);
try {
final ConfluenceProperties contentPermissionProperty = this.confluencePackage.getObjectProperties(permissionId);
final String userSubject = contentPermissionProperty.getString("userSubject");
String username = "";
if (StringUtils.isNoneEmpty(userSubject)) {
final ConfluenceProperties userImplProperties;
// look up ConfluenceUserImpl in order to get username aso
try {
userImplProperties = this.confluencePackage.getUserImplProperties(userSubject);
}
catch (ConfigurationException e) {
throw new FilterException("Failed to get UserImpl properties for user-key: "+ userSubject, e);
}
username = userImplProperties.getString(ConfluenceXMLPackage.USERIMPL_LOWERNAME, "");
// admin should be skipped as we can't restrict an admin...?
if (this.properties.isConvertToXWiki()) {
if (username.equals("admin")) {
username = "Admin";
}
}
}
final String groupName = contentPermissionProperty.getString("groupName");
final String type = contentPermissionProperty.getString("type"); // view, edit etc
// confluence stores view and edit-permissions additionally, means user x can have view and edit-permissions
// edit-permission implies view-permission. In order to a view OR a edit permission (NOT both) we want to
// replace a view-permission if an edit permission exists for the same user or group
replaceViewByEditPermission(userPermissions, username, type);
replaceViewByEditPermission(groupPermissions, groupName, type);
} catch (ConfigurationException e) {
logger.error("Failed getting content permissions for: " + permissionId, e);
}
}
}
// persist the collected data into xObjects / XWikiRights
StringBuilder body = new StringBuilder();
writePageResrticitions(proxyFilter, objectName, userPermissions, true, body);
writePageResrticitions(proxyFilter, objectName, groupPermissions, false, body);
if (body.length() > 0)
script.append("#set ($mydoc = $xwiki.getDocument(\"").append(objectName).append("\"))\n").append(body); // document-ref eg. TESTARGESPACE02.Testseite 3
}
/**
* if user or a group has Edit-Permission replace the View-Permission
* @param permissions collection containing user or group (key = user or group-name, value = permissiontype)
* @param userOrGroup name of the user or the group
* @param permissionType Edit or View
*/
private void replaceViewByEditPermission(Map<String, String> permissions, String userOrGroup, String permissionType) {
if (StringUtils.isNoneEmpty(userOrGroup)){
String value = permissions.get(userOrGroup);
if (value == null)
permissions.put(userOrGroup, permissionType);
else if (value.equals("View") && permissionType.equals("Edit"))
permissions.replace(userOrGroup, permissionType);
}
}
main part - we don’t need the velocity workaround, but I let it still there for some legacy reason (and lazyness)
private void writePageResrticitions(ConfluenceFilter proxyFilter, String objectName, Map<String, String> userPermissions, boolean isUsercollection, StringBuilder body) throws FilterException {
for (Map.Entry<String, String> entry : userPermissions.entrySet()) {
// Permission object
FilterEventParameters restrictionsParameters = new FilterEventParameters();
restrictionsParameters.put(WikiObjectFilter.PARAMETER_CLASS_REFERENCE, XWiki.SYSTEM_SPACE + ".XWikiRights");
proxyFilter.beginWikiObject(objectName, restrictionsParameters);
// permissions object property
String levels = this.convertConfluencePageRestrictions2xWikiPermission(entry.getValue());
proxyFilter.onWikiObjectProperty("levels", levels, new FilterEventParameters());
if (isUsercollection)
proxyFilter.onWikiObjectProperty("users", XWiki.SYSTEM_SPACE + "." + entry.getKey(), new FilterEventParameters());
else
proxyFilter.onWikiObjectProperty("groups", XWiki.SYSTEM_SPACE + "." + entry.getKey(), new FilterEventParameters());
proxyFilter.onWikiObjectProperty("allow", 1, new FilterEventParameters());
// persist wiki object
proxyFilter.endWikiObject(objectName, restrictionsParameters);
// generating Velocity Script as currently the Pagerestrictiong are getting overwritten by the "Nested Page Migrator" Plugin
// always create a new Object so the existing (rights) Objects don't get overwritten
body.append("#set ($rightsObject = $mydoc.newObject(\""+ XWiki.SYSTEM_SPACE + ".XWikiRights"+"\"))\n");
if (isUsercollection)
body.append("#set ($result = $rightsObject.set(\"users\", \""+ XWiki.SYSTEM_SPACE + "." + entry.getKey() +"\"))\n");
else
body.append("#set ($result = $rightsObject.set(\"groups\", \""+ XWiki.SYSTEM_SPACE + "." + entry.getKey() +"\"))\n");
body.append("#set ($result = $rightsObject.set(\"levels\", \""+levels+"\"))\n");
body.append("#set ($result = $rightsObject.set(\"allow\", 1))\n");
body.append("$mydoc.save()\n");
}
}
private String convertConfluencePageRestrictions2xWikiPermission(String pageRestriction){
// xWiki Permissions
// view - ability to view pages
// comment - ability to write page comments
// edit - ability to edit page content
// script - control programmatically exactly what users are allowed to do
// delete - ability to delete pages
// admin - ability to administer pages or the wiki
// Confluence Page Restrictions
// edit
// view
String xWikipermission = "";
if (pageRestriction.equals("View")) {
xWikipermission = "view";
}
else if(pageRestriction.equals("Edit")) {
xWikipermission = "view,edit,comment,delete";
}
return xWikipermission;
}
hopefully this is the wright code I’m looking at since there is a little bit of confusion on my hard disk now - but the code seems to work (as reading over it), also the lastedit should tell the truth about the source I found
Regards,
Stefan.