Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/maven/fixes/8.3' into maven/rele…
Browse files Browse the repository at this point in the history
…ase/8.3
  • Loading branch information
metaventis-build committed May 7, 2024
2 parents 6ae3ff6 + 0c1d3c5 commit 94681f6
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.edu_sharing.service.lifecycle;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.ContentStore;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.*;
Expand Down Expand Up @@ -35,6 +36,8 @@ public abstract class OrganisationDeleteProtocolService {

String organisation;

private static String STORE_LOCATION = "jobsProtocolCache";

protected OrganisationDeleteProtocolService(String organisation){
this.organisation = organisation;
this.tempFile = createProtocolTempFile(organisation);
Expand All @@ -47,7 +50,21 @@ protected OrganisationDeleteProtocolService(String organisation){
public abstract void cleanUp();

private File createProtocolTempFile(String organisation){
return TempFileProvider.createTempFile(organisation, getProtcolFormatSuffix());
return TempFileProvider.createTempFile(organisation, getProtcolFormatSuffix(),getCacheStore());
}

private File getRootLocation() {
ApplicationContext applicationContext = AlfAppContextGate.getApplicationContext();
ContentStore store = (ContentStore) applicationContext.getBean("fileContentStore");
return new File(store.getRootLocation()).getParentFile();
}

private File getCacheStore(){
File cacheStore = new File(getRootLocation(), STORE_LOCATION);
if (! cacheStore.exists()) {
cacheStore.mkdir();
}
return cacheStore;
}

public void writeProtocolToAlfrescoNode(String mimeType) {
Expand Down Expand Up @@ -114,10 +131,10 @@ public ContentReader getContentReader(){
}
}

public void protocolError(String orga, String user, String errorMessage) {
public void protocolError(String orga, String authority, String errorMessage) {
OrganisationDeleteProtocol protEntry = new OrganisationDeleteProtocol();
protEntry.event = OrganisationDeleteProtocol.EVENTS.ERROR.name();
protEntry.authority = user;
protEntry.authority = authority;
protEntry.collections = 0;
protEntry.date = new Date();
protEntry.docs = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
import org.edu_sharing.alfresco.service.OrganisationService;
import org.edu_sharing.alfrescocontext.gate.AlfAppContextGate;
import org.edu_sharing.repository.client.tools.CCConstants;
import org.edu_sharing.service.authentication.ScopeUserHomeServiceFactory;
import org.edu_sharing.service.authentication.ScopeUserHomeServiceImpl;
import org.edu_sharing.service.collection.CollectionServiceConfig;
import org.edu_sharing.service.collection.CollectionServiceFactory;
import org.edu_sharing.spring.ApplicationContextFactory;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationContext;

Expand Down Expand Up @@ -51,6 +56,8 @@ public class OrganisationLifecycleService {

String organisation;

CollectionServiceConfig collectionServiceConfig = (CollectionServiceConfig) ApplicationContextFactory.getApplicationContext().getBean("collectionServiceConfig");

public OrganisationLifecycleService(String organisation){
this.organisation = organisation;
protocolService = new OrganisationDeleteProtocolServiceCSV(organisation);
Expand Down Expand Up @@ -84,6 +91,10 @@ private void deleteOrganisationWithContext(String orga, String authorityName) {
for (String user : users) {
try {
PersonDeleteResult personDeleteResult = deleteUser(authorityName, user);
if (!checkNodes(authorityName, user, CCConstants.CCM_TYPE_IO,null)) return;
if (!checkNodes(authorityName, user, CCConstants.CCM_TYPE_IO,CCConstants.CCM_VALUE_SCOPE_SAFE)) return;
if (!checkNodes(authorityName, user, CCConstants.CCM_TYPE_MAP,null)) return;
if (!checkNodes(authorityName, user, CCConstants.CCM_TYPE_MAP,CCConstants.CCM_VALUE_SCOPE_SAFE)) return;
protocolService.protocolPerson(orga, personDeleteResult);
} catch (RuntimeException e) {
logger.error(e.getMessage(),e);
Expand All @@ -92,10 +103,25 @@ private void deleteOrganisationWithContext(String orga, String authorityName) {
return;
}catch(Throwable e){
logger.error(e.getMessage(),e);
protocolService.protocolError(orga, user, e.getMessage());
return;
}
}

/**
* check if still users exist, also in subgroups (which is not edu-sharing default)
*/
users = authorityService.getContainedAuthorities(AuthorityType.USER, authorityName, false);
if(users != null && users.size() > 0){
String userFailed = users.stream().collect(Collectors.joining(","));
String message = "the following users could not be deleted:" +userFailed;
logger.error(message);
protocolService.protocolError(orga,orga,message);
return;
}



//delete safe org and subgroups
String authorityNameSafe = authorityName + "_safe";
deleteOrganisationGroup(orga, authorityNameSafe);
Expand All @@ -105,6 +131,51 @@ private void deleteOrganisationWithContext(String orga, String authorityName) {
deleteOrganisationGroup(orga, authorityName);
}

private boolean checkNodes(String authorityName, String user, String type, String scope) {
List<NodeRef> allNodeRefs = personLifecycleService.getAllNodeRefs(user, type, scope);
if(allNodeRefs != null && allNodeRefs.size() > 0){
if(CCConstants.CCM_TYPE_MAP.equals(type)) {

//ignore folders of shared area, which will not be deleted by personlifecycleservice, but removed when org is deleted
Map<QName, Serializable> orgProps = organisationService.getOrganisation(organisationService.getCleanName(authorityName + ((scope != null) ? "_" + scope : "")));
NodeRef orgHomeFolderRef = (NodeRef) orgProps.get(QName.createQName(OrganisationService.CCM_PROP_EDUGROUP_EDU_HOMEDIR));
String orgHomeFolderPath = nodeService.getPath(orgHomeFolderRef).toPrefixString(serviceRegistry.getNamespaceService());
allNodeRefs = allNodeRefs.stream().filter(nodeRef -> !nodeService.getPath(nodeRef)
.toPrefixString(serviceRegistry.getNamespaceService())
.contains(orgHomeFolderPath))
.collect(Collectors.toList());

//ignore collection path folders, that need to stay there cause it can be that another user saved an collection there
if(allNodeRefs.size() > 0){
allNodeRefs = allNodeRefs.stream().filter(nodeRef ->
!(
!nodeService.hasAspect(nodeRef,QName.createQName(CCConstants.CCM_ASPECT_COLLECTION))
&& nodeService.getPath(nodeRef).toPrefixString(serviceRegistry.getNamespaceService()).contains(collectionServiceConfig.getPath())
)
).collect(Collectors.toList());
}

//ignore intermediate folders for safe home
if(allNodeRefs.size() > 0 && CCConstants.CCM_VALUE_SCOPE_SAFE.equals(scope)){
NodeRef safeHomerFolderRoot = ((ScopeUserHomeServiceImpl) ScopeUserHomeServiceFactory.getScopeUserHomeService()).getRootNodeRef(scope);
allNodeRefs = allNodeRefs.stream()
.filter(nodeRef -> !safeHomerFolderRoot.equals(nodeService.getPrimaryParent(nodeRef).getParentRef()))
.collect(Collectors.toList());
}
}

if(allNodeRefs.size() > 0) {
String message = "the following nodes(type=" + type + ") for " + user + " scope:" + scope + " could not be deleted:" + allNodeRefs.stream()
.map(r -> r.toString())
.collect(Collectors.joining(","));
logger.error(message);
protocolService.protocolError(authorityName, user, message);
return false;
}
}
return true;
}

protected void deleteOrganisationGroup(String orga, String authorityName){
if(authorityService.authorityExists(authorityName)) {
//delete subgroups
Expand Down Expand Up @@ -134,39 +205,52 @@ protected void deleteSubGroups(String orga, String authorityName){
Set<String> containedAuthorities = authorityService.getContainedAuthorities(AuthorityType.GROUP, authorityName, false);
List<String> result = new ArrayList<>();
for(String authority : containedAuthorities){

checkAuthorityOnlyExistsInOneOrg(authorityName,authority);

authorityService.deleteAuthority(authority);
result.add(authority);
}
String scope = null;
if(authorityName.endsWith("_safe")) scope = CCConstants.CCM_VALUE_SCOPE_SAFE;
protocolService.protocolSubGroups(orga,result,scope);

Set<String> containedAuthoritiesRemained = authorityService.getContainedAuthorities(AuthorityType.GROUP, authorityName, false);
if(containedAuthoritiesRemained != null && containedAuthoritiesRemained.size() > 0){
throw new RuntimeException("the following subgroups of "+ authorityName + " could not be deleted:"
+ String.join(",", containedAuthoritiesRemained));
}
}

protected PersonDeleteResult deleteUser(String orgAuthorityName, String userName) {
logger.info("deleting user:" + userName);

checkAuthorityOnlyExistsInOneOrg(orgAuthorityName, userName);


NodeRef nodeRef = personService.getPerson(userName);
nodeService.setProperty(nodeRef, QName.createQName(CCConstants.CM_PROP_PERSON_ESPERSONSTATUS), PersonLifecycleService.PersonStatus.todelete.name());

return personLifecycleService.deletePersons(Arrays.asList(userName), getPersonDeleteOptions()).results.get(0);
}

private void checkAuthorityOnlyExistsInOneOrg(String orgAuthorityName, String authority) {
//check user exists only in organisation orgAuthorityName
Set<String> containedAuthorities = authorityService.getContainingAuthorities(AuthorityType.GROUP, userName, false);
Set<String> containedAuthorities = authorityService.getContainingAuthorities(AuthorityType.GROUP, authority, false);
List<String> orgMemberships = containedAuthorities.stream()
.filter(g -> g.startsWith("GROUP_ORG_"))
.collect(Collectors.toList());
if(!orgMemberships.contains(orgAuthorityName)){
throw new RuntimeException("user " + userName + " is not member of organisation " + orgAuthorityName);
throw new RuntimeException("authority " + authority + " is not member of organisation " + orgAuthorityName);
}

String orgAuthorityNameSafe = orgAuthorityName + "_" + CCConstants.CCM_VALUE_SCOPE_SAFE;
orgMemberships = orgMemberships.stream()
.filter(a -> (!a.equals(orgAuthorityName) && !a.equals(orgAuthorityNameSafe)))
.collect(Collectors.toList());
if(orgMemberships.size() > 0){
throw new RuntimeException("user " + userName + " is member of more than one organisation");
throw new RuntimeException("authority " + authority + " is member of more than one organisation");
}


NodeRef nodeRef = personService.getPerson(userName);
nodeService.setProperty(nodeRef, QName.createQName(CCConstants.CM_PROP_PERSON_ESPERSONSTATUS), PersonLifecycleService.PersonStatus.todelete.name());

return personLifecycleService.deletePersons(Arrays.asList(userName), getPersonDeleteOptions()).results.get(0);
}

private static @NotNull PersonDeleteOptions getPersonDeleteOptions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ public class OrganisationLifecycleServiceTestSetup {

int numberOfPersons = 10;

int numberOfHomeDocs = 1200;
int numberOfHomeDocs = 12;

//+ 3 (dokuments,images,shared)
int numberOfHomeFolders = 1200;
int numberOfHomeFolders = 9;

int numberOfSharedDocs = 100;
int numberOfSharedFolders = 40;
int numberOfSharedDocs = 10;
int numberOfSharedFolders = 4;

int numberOfCollections = 30;
int numberOfCollectionRefs = 79;
int numberOfCollections = 3;
int numberOfCollectionRefs = 7;

List<NodeRef> persons = new ArrayList<>();
String orgAuthorityName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private void deletePersons(int skipCount) {
public PersonReport deletePersons(List<String> usernames, PersonDeleteOptions options) {
List<PersonDeleteResult> results=new ArrayList<>();
for(String user : usernames) {
NodeRef personNodeRef = personService.getPerson(user);
NodeRef personNodeRef = personService.getPerson(user,false);
results.add(deletePerson(personNodeRef,options));
}
PersonReport report=new PersonReport();
Expand Down Expand Up @@ -833,7 +833,7 @@ private void deleteNode(NodeRef nodeRef) {
}

public void removeContributer(NodeRef nodeRef, String username){
NodeRef personNodeRef = personService.getPerson(username);
NodeRef personNodeRef = personService.getPerson(username,false);
String firstName = (String)nodeService.getProperty(personNodeRef, QName.createQName(CCConstants.CM_PROP_PERSON_FIRSTNAME));
String lastName = (String)nodeService.getProperty(personNodeRef, QName.createQName(CCConstants.CM_PROP_PERSON_LASTNAME));

Expand Down

0 comments on commit 94681f6

Please sign in to comment.