diff --git a/celements-model/src/main/java/com/celements/model/classes/ClassDefinition.java b/celements-model/src/main/java/com/celements/model/classes/ClassDefinition.java index 994b0be2a..d912567a4 100644 --- a/celements-model/src/main/java/com/celements/model/classes/ClassDefinition.java +++ b/celements-model/src/main/java/com/celements/model/classes/ClassDefinition.java @@ -11,12 +11,11 @@ import org.xwiki.model.reference.WikiReference; import com.celements.model.classes.fields.ClassField; -import com.google.common.collect.ImmutableList; @ComponentRole public interface ClassDefinition extends ClassIdentity { - ImmutableList LANG_FIELD_NAMES = ImmutableList.of("lang", "language"); + List LANG_FIELD_NAMES = List.of("lang", "language"); String CFG_SRC_KEY = "celements.classdefinition.blacklist"; diff --git a/celements-model/src/main/java/com/celements/model/classes/fields/AbstractClassField.java b/celements-model/src/main/java/com/celements/model/classes/fields/AbstractClassField.java index 6b0a17f26..48b3de0b0 100644 --- a/celements-model/src/main/java/com/celements/model/classes/fields/AbstractClassField.java +++ b/celements-model/src/main/java/com/celements/model/classes/fields/AbstractClassField.java @@ -17,7 +17,6 @@ import com.celements.model.classes.ClassDefinition; import com.google.common.base.Strings; -import com.xpn.xwiki.objects.PropertyInterface; import com.xpn.xwiki.objects.classes.PropertyClass; /** @@ -124,7 +123,7 @@ public String getValidationMessage() { } @Override - public PropertyInterface getXField() { + public PropertyClass getXField() { PropertyClass element = getPropertyClass(); element.setName(name); if (prettyName != null) { diff --git a/celements-model/src/main/java/com/celements/model/classes/fields/ClassField.java b/celements-model/src/main/java/com/celements/model/classes/fields/ClassField.java index c65c57513..f2d64a799 100644 --- a/celements-model/src/main/java/com/celements/model/classes/fields/ClassField.java +++ b/celements-model/src/main/java/com/celements/model/classes/fields/ClassField.java @@ -5,7 +5,7 @@ import org.xwiki.model.reference.ClassReference; import com.celements.model.classes.ClassDefinition; -import com.xpn.xwiki.objects.PropertyInterface; +import com.xpn.xwiki.objects.classes.PropertyClass; public interface ClassField { @@ -26,7 +26,7 @@ public interface ClassField { Class getType(); @NotNull - PropertyInterface getXField(); + PropertyClass getXField(); @NotNull String serialize(); diff --git a/celements-model/src/main/java/com/celements/model/classes/fields/PlainClassField.java b/celements-model/src/main/java/com/celements/model/classes/fields/PlainClassField.java index fc3d9829f..65e5e2096 100644 --- a/celements-model/src/main/java/com/celements/model/classes/fields/PlainClassField.java +++ b/celements-model/src/main/java/com/celements/model/classes/fields/PlainClassField.java @@ -8,7 +8,7 @@ import com.celements.model.classes.ClassDefinition; import com.celements.model.object.ObjectFetcher; -import com.xpn.xwiki.objects.PropertyInterface; +import com.xpn.xwiki.objects.classes.PropertyClass; /** * A plain {@link ClassField} without the necessity of a backing {@link ClassDefinition}. @@ -49,7 +49,7 @@ public Class getType() { } @Override - public PropertyInterface getXField() { + public PropertyClass getXField() { throw new UnsupportedOperationException("PlainClassField not generateable"); } diff --git a/celements-model/src/test/java/com/celements/convert/bean/XDocBeanLoaderTest.java b/celements-model/src/test/java/com/celements/convert/bean/XDocBeanLoaderTest.java index e573f8078..3aa0d7482 100644 --- a/celements-model/src/test/java/com/celements/convert/bean/XDocBeanLoaderTest.java +++ b/celements-model/src/test/java/com/celements/convert/bean/XDocBeanLoaderTest.java @@ -2,11 +2,11 @@ import static com.celements.common.test.CelementsTestUtils.*; import static com.celements.model.classes.TestClassDefinition.*; -import static org.easymock.EasyMock.*; import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collections; +import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; @@ -44,10 +44,8 @@ public void prepareTest() throws Exception { private BaseClass expectClass(ClassDefinition classDef, WikiReference wikiRef) throws XWikiException { BaseClass bClass = expectNewBaseObject(classDef.getDocRef(wikiRef)); - for (ClassField field : classDef.getFields()) { - expect(bClass.get(field.getName())).andReturn(field.getXField()).anyTimes(); - } - return bClass; + return expectPropertyClasses(bClass, classDef.getFields().stream() + .collect(Collectors.toMap(ClassField::getName, ClassField::getXField))); } @Test @@ -95,7 +93,7 @@ public void test_noFields() throws Exception { @Test public void test_noObj() throws Exception { replayDefault(); - new ExceptionAsserter(BeanLoadException.class) { + new ExceptionAsserter<>(BeanLoadException.class) { @Override protected void execute() throws BeanLoadException { @@ -110,7 +108,7 @@ protected void execute() throws BeanLoadException { public void test_notInitialized() throws Exception { loader = Utils.getComponent(XDocBeanLoader.class); replayDefault(); - new ExceptionAsserter(IllegalStateException.class) { + new ExceptionAsserter<>(IllegalStateException.class) { @Override protected void execute() throws IllegalStateException, BeanLoadException { diff --git a/celements-model/src/test/java/com/celements/marshalling/BeanXDocMarshallerTest.java b/celements-model/src/test/java/com/celements/marshalling/BeanXDocMarshallerTest.java index cab8906c1..5bb1dfbec 100644 --- a/celements-model/src/test/java/com/celements/marshalling/BeanXDocMarshallerTest.java +++ b/celements-model/src/test/java/com/celements/marshalling/BeanXDocMarshallerTest.java @@ -5,6 +5,8 @@ import static org.easymock.EasyMock.*; import static org.junit.Assert.*; +import java.util.stream.Collectors; + import org.junit.Before; import org.junit.Test; import org.xwiki.model.EntityType; @@ -40,10 +42,8 @@ public void prepareTest() throws Exception { private BaseClass expectClass(ClassDefinition classDef, WikiReference wikiRef) throws XWikiException { BaseClass bClass = expectNewBaseObject(classDef.getDocRef(wikiRef)); - for (ClassField field : classDef.getFields()) { - expect(bClass.get(field.getName())).andReturn(field.getXField()).anyTimes(); - } - return bClass; + return expectPropertyClasses(bClass, classDef.getFields().stream() + .collect(Collectors.toMap(ClassField::getName, ClassField::getXField))); } @Test diff --git a/celements-model/src/test/java/com/celements/model/field/XObjectFieldAccessorTest.java b/celements-model/src/test/java/com/celements/model/field/XObjectFieldAccessorTest.java index 240e8351b..e06b630eb 100644 --- a/celements-model/src/test/java/com/celements/model/field/XObjectFieldAccessorTest.java +++ b/celements-model/src/test/java/com/celements/model/field/XObjectFieldAccessorTest.java @@ -1,13 +1,15 @@ package com.celements.model.field; import static com.celements.common.test.CelementsTestUtils.*; -import static org.easymock.EasyMock.*; import static org.junit.Assert.*; +import java.util.stream.Collectors; + import org.junit.Before; import org.junit.Test; import org.xwiki.model.reference.ClassReference; import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.WikiReference; import com.celements.common.test.AbstractComponentTest; import com.celements.common.test.ExceptionAsserter; @@ -32,15 +34,14 @@ public void prepareTest() throws Exception { accessor = (XObjectFieldAccessor) Utils.getComponent(FieldAccessor.class, XObjectFieldAccessor.NAME); testClassDef = Utils.getComponent(ClassDefinition.class, TestClassDefinition.NAME); - expectClass(testClassDef); + expectClass(testClassDef, getXContext().getWikiRef()); } - private static BaseClass expectClass(ClassDefinition classDef) throws XWikiException { - BaseClass bClass = expectNewBaseObject(classDef.getDocRef()); - for (ClassField field : classDef.getFields()) { - expect(bClass.get(field.getName())).andReturn(field.getXField()).anyTimes(); - } - return bClass; + private BaseClass expectClass(ClassDefinition classDef, WikiReference wikiRef) + throws XWikiException { + BaseClass bClass = expectNewBaseObject(classDef.getDocRef(wikiRef)); + return expectPropertyClasses(bClass, classDef.getFields().stream() + .collect(Collectors.toMap(ClassField::getName, ClassField::getXField))); } @Test @@ -90,14 +91,14 @@ public void test_FieldAccessException_invalidXClass() { final ClassField field = TestClassDefinition.FIELD_MY_STRING; final BaseObject obj = new BaseObject(); obj.setXClassReference(new ClassReference("space", "class")); - new ExceptionAsserter(FieldAccessException.class) { + new ExceptionAsserter<>(FieldAccessException.class) { @Override protected void execute() throws FieldAccessException { accessor.get(obj, field); } }.evaluate(); - new ExceptionAsserter(FieldAccessException.class) { + new ExceptionAsserter<>(FieldAccessException.class) { @Override protected void execute() throws FieldAccessException { @@ -111,14 +112,14 @@ public void test_FieldAccessException_pseudoClass() { final ClassField field = XWikiDocumentClass.FIELD_CONTENT; final BaseObject obj = new BaseObject(); obj.setXClassReference(new ClassReference("space", "class")); - new ExceptionAsserter(FieldAccessException.class) { + new ExceptionAsserter<>(FieldAccessException.class) { @Override protected void execute() throws FieldAccessException { accessor.get(obj, field); } }.evaluate(); - new ExceptionAsserter(FieldAccessException.class) { + new ExceptionAsserter<>(FieldAccessException.class) { @Override protected void execute() throws FieldAccessException { @@ -132,7 +133,7 @@ public void test_FieldAccessException_setValue_xObjFields() { final BaseObject obj = new BaseObject(); final ClassReference classRef = testClassDef.getClassReference(); obj.setXClassReference(classRef); - new ExceptionAsserter(FieldAccessException.class) { + new ExceptionAsserter<>(FieldAccessException.class) { @Override protected void execute() throws FieldAccessException { @@ -140,7 +141,7 @@ protected void execute() throws FieldAccessException { } }.evaluate(); final DocumentReference docRef = new DocumentReference("wiki", "space", "doc"); - new ExceptionAsserter(FieldAccessException.class) { + new ExceptionAsserter<>(FieldAccessException.class) { @Override protected void execute() throws FieldAccessException { @@ -148,7 +149,7 @@ protected void execute() throws FieldAccessException { } }.evaluate(); final Integer number = 5; - new ExceptionAsserter(FieldAccessException.class) { + new ExceptionAsserter<>(FieldAccessException.class) { @Override protected void execute() throws FieldAccessException { diff --git a/celements-wiki-api/src/main/java/com/celements/wiki/WikiDescriptor.java b/celements-wiki-api/src/main/java/com/celements/wiki/WikiDescriptor.java new file mode 100644 index 000000000..4790c8cca --- /dev/null +++ b/celements-wiki-api/src/main/java/com/celements/wiki/WikiDescriptor.java @@ -0,0 +1,39 @@ +package com.celements.wiki; + +import java.net.URI; + +import org.xwiki.model.reference.WikiReference; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public record WikiDescriptor( + WikiReference wiki, + String prettyName, + String server, + Visibility visibility, + State state, + String language, + Boolean secure, + Boolean oicd, + URI uri) { + + @JsonIgnore + public WikiReference wiki() { + return wiki; + } + + @JsonProperty("wiki") + public String wikiName() { + return (wiki != null) ? wiki.getName() : null; + } + + public enum Visibility { + PUBLIC, PRIVATE + } + + public enum State { + ACTIVE, INACTIVE, LOCKED + } + +} diff --git a/celements-wiki-api/src/main/java/com/celements/wiki/WikiDescriptorService.java b/celements-wiki-api/src/main/java/com/celements/wiki/WikiDescriptorService.java index 6c82c864e..313b56058 100644 --- a/celements-wiki-api/src/main/java/com/celements/wiki/WikiDescriptorService.java +++ b/celements-wiki-api/src/main/java/com/celements/wiki/WikiDescriptorService.java @@ -1,15 +1,29 @@ package com.celements.wiki; +import java.util.List; + +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.WikiReference; +import com.celements.wiki.exception.WikiDescriptorException; +import com.celements.wiki.exception.WikiMissingException; + public interface WikiDescriptorService { @NotNull DocumentReference getDescriptorDocRef(@NotNull WikiReference wikiRef); + @NotNull + List getDescriptors(@NotNull WikiReference wikiRef) throws WikiMissingException; + + void createDescriptor(@NotNull WikiReference wikiRef, @NotEmpty String host) + throws WikiDescriptorException; + + void deleteDescriptors(@NotNull WikiReference wikiRef) throws WikiDescriptorException; + boolean isOicdEnabled(@NotNull WikiReference wikiRef); } diff --git a/celements-wiki-api/src/main/java/com/celements/wiki/exception/WikiDescriptorException.java b/celements-wiki-api/src/main/java/com/celements/wiki/exception/WikiDescriptorException.java new file mode 100644 index 000000000..23ac25bd5 --- /dev/null +++ b/celements-wiki-api/src/main/java/com/celements/wiki/exception/WikiDescriptorException.java @@ -0,0 +1,13 @@ +package com.celements.wiki.exception; + +import org.xwiki.model.reference.WikiReference; + +public class WikiDescriptorException extends WikiException { + + private static final long serialVersionUID = 1L; + + public WikiDescriptorException(WikiReference wikiRef, Throwable cause) { + super(wikiRef, cause); + } + +} diff --git a/celements-wiki-manager/component/pom.xml b/celements-wiki-manager/component/pom.xml index 036606a99..d0bb77aa1 100644 --- a/celements-wiki-manager/component/pom.xml +++ b/celements-wiki-manager/component/pom.xml @@ -39,6 +39,11 @@ celements-servlet provided + + com.celements + celements-spring-security + provided + com.celements celements-wiki-api diff --git a/celements-wiki-manager/component/src/main/java/com/celements/wiki/DefaultWikiCreator.java b/celements-wiki-manager/component/src/main/java/com/celements/wiki/DefaultWikiCreator.java index 57b423e48..e2e245ccf 100644 --- a/celements-wiki-manager/component/src/main/java/com/celements/wiki/DefaultWikiCreator.java +++ b/celements-wiki-manager/component/src/main/java/com/celements/wiki/DefaultWikiCreator.java @@ -5,7 +5,6 @@ import static java.util.Objects.*; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import javax.inject.Inject; import javax.inject.Named; @@ -128,7 +127,7 @@ void notifyWikiCreatingEvent(WikiReference wikiRef) { XWikiUser userPrev = ectx.set(XWIKI_USER, new XWikiUser(SUPERADMIN_FQN, true)); try { eventPublisher.publishEvent(new WikiCreatingEvent(wikiRef)); - wikiUpdater.getFuture(wikiRef).ifPresent(CompletableFuture::join); + wikiUpdater.awaitCompletion(wikiRef); } finally { ectx.set(XWIKI_USER, userPrev); } diff --git a/celements-wiki-manager/component/src/main/java/com/celements/wiki/QueryWikiService.java b/celements-wiki-manager/component/src/main/java/com/celements/wiki/QueryWikiService.java index 783cf7a9d..7312df9c6 100644 --- a/celements-wiki-manager/component/src/main/java/com/celements/wiki/QueryWikiService.java +++ b/celements-wiki-manager/component/src/main/java/com/celements/wiki/QueryWikiService.java @@ -159,7 +159,7 @@ private WikiReference convertMainWiki(WikiReference wikiRef) { return wikiRef; } - private Optional toUri(Integer secure, String host) { + public Optional toUri(Integer secure, String host) { try { return Optional.of(UriComponentsBuilder.newInstance() .scheme(Optional.ofNullable(secure) diff --git a/celements-wiki-manager/component/src/main/java/com/celements/wiki/WikiDescriptorUpdater.java b/celements-wiki-manager/component/src/main/java/com/celements/wiki/WikiDescriptorUpdater.java index c90c15d82..68ea2d8b0 100644 --- a/celements-wiki-manager/component/src/main/java/com/celements/wiki/WikiDescriptorUpdater.java +++ b/celements-wiki-manager/component/src/main/java/com/celements/wiki/WikiDescriptorUpdater.java @@ -1,6 +1,5 @@ package com.celements.wiki; -import static com.celements.wiki.classes.XWikiServerClass.*; import static com.xpn.xwiki.XWikiConstant.*; import java.net.URI; @@ -15,20 +14,12 @@ import org.springframework.stereotype.Component; import org.xwiki.model.reference.WikiReference; -import com.celements.model.access.IModelAccessFacade; -import com.celements.model.access.exception.DocumentDeleteException; -import com.celements.model.access.exception.DocumentSaveException; -import com.celements.model.object.xwiki.XWikiObjectEditor; import com.celements.model.util.ModelUtils; -import com.celements.wiki.classes.XWikiServerClass; -import com.celements.wiki.classes.XWikiServerClass.State; -import com.celements.wiki.classes.XWikiServerClass.Visibility; import com.celements.wiki.event.WikiCreatingEvent; import com.celements.wiki.event.WikiDeletedEvent; import com.celements.wiki.event.WikiEvent; +import com.celements.wiki.exception.WikiDescriptorException; import com.xpn.xwiki.XWikiConfigSource; -import com.xpn.xwiki.doc.XWikiDocument; -import com.xpn.xwiki.objects.BaseObject; /** * Creates/deletes wiki descriptors in main wiki on creation/deletion events. @@ -39,20 +30,17 @@ public class WikiDescriptorUpdater implements ApplicationListener, Or private static final Logger LOGGER = LoggerFactory.getLogger(WikiDescriptorUpdater.class); private final ModelUtils modelUtils; - private final IModelAccessFacade modelAccess; private final WikiService wikiService; - private final XWikiConfigSource xwikiCfg; private final WikiDescriptorService descriptorService; + private final XWikiConfigSource xwikiCfg; @Inject public WikiDescriptorUpdater( ModelUtils modelUtils, - IModelAccessFacade modelAccess, WikiService wikiService, WikiDescriptorService descriptorService, XWikiConfigSource xwikiCfg) { this.modelUtils = modelUtils; - this.modelAccess = modelAccess; this.wikiService = wikiService; this.descriptorService = descriptorService; this.xwikiCfg = xwikiCfg; @@ -66,55 +54,33 @@ public int getOrder() { @Override public void onApplicationEvent(WikiEvent wikiEvent) { if (wikiEvent instanceof WikiCreatingEvent) { - createWikiDescriptor(wikiEvent.getWiki()); + createDescriptors(wikiEvent.getWiki()); } else if (wikiEvent instanceof WikiDeletedEvent) { - deleteWikiDescriptor(wikiEvent.getWiki()); + deleteDescriptors(wikiEvent.getWiki()); } else { LOGGER.debug("unsupported event [{}]", wikiEvent); } } - private void createWikiDescriptor(WikiReference wikiRef) { - XWikiDocument cfgDoc = modelAccess - .getOrCreateDocument(descriptorService.getDescriptorDocRef(wikiRef)); - var editor = XWikiObjectEditor.on(cfgDoc).filter(XWikiServerClass.CLASS_REF); - if (editor.fetch().exists()) { - LOGGER.debug("skip wiki descriptor creation for [{}], already exists", wikiRef.getName()); - return; - } + private void createDescriptors(WikiReference wikiRef) { var host = determineHost(); - if (modelUtils.isMainWiki(wikiRef)) { - createWikiDescriptor(editor, wikiRef.getName(), host); - } - createWikiDescriptor(editor, wikiRef.getName(), wikiRef.getName() + "." + host); - cfgDoc.setContent("#includeForm('XWiki.XWikiServerClassSheet')"); try { - modelAccess.saveDocument(cfgDoc, "WikiDescriptorUpdater"); - LOGGER.info("created wiki descriptor for [{}]", wikiRef.getName()); - } catch (DocumentSaveException dse) { - LOGGER.error("failed to create wiki descriptor for [{}]", wikiRef, dse); + var hostPrefix = wikiRef.getName(); + if (modelUtils.isMainWiki(wikiRef)) { + descriptorService.createDescriptor(wikiRef, host); + hostPrefix = xwikiCfg.getMainWikiName(); // prefix 'main' and not 'xwiki' + } + descriptorService.createDescriptor(wikiRef, hostPrefix + "." + host); + } catch (WikiDescriptorException exc) { + LOGGER.error("failed to create wiki descriptors for [{}]", wikiRef, exc); } } - private BaseObject createWikiDescriptor(XWikiObjectEditor editor, String name, String host) { - return editor - .filter(FIELD_PRETTY_NAME, name) - .filter(FIELD_SERVER, host) - .filter(FIELD_SECURE, isSecure()) - .filter(FIELD_VISIBILITY, Visibility.PUBLIC) - .filter(FIELD_STATE, State.ACTIVE) - .filter(FIELD_LANGUAGE, "en") - .filter(FIELD_HOMEPAGE, "Content.WebHome") - .filter(FIELD_IS_TEMPLATE, false) - .filter(FIELD_OICD_ACTIVE, false) - .createFirst(); - } - - private void deleteWikiDescriptor(WikiReference wikiRef) { + private void deleteDescriptors(WikiReference wikiRef) { try { - modelAccess.deleteDocument(descriptorService.getDescriptorDocRef(wikiRef), true); - } catch (DocumentDeleteException dde) { - LOGGER.error("failed to delete wiki descriptor for [{}]", wikiRef, dde); + descriptorService.deleteDescriptors(wikiRef); + } catch (WikiDescriptorException exc) { + LOGGER.error("failed to delete wiki descriptors for [{}]", wikiRef, exc); } } @@ -130,8 +96,4 @@ private String determineHost() { .orElse("localhost"); } - private boolean isSecure() { - return xwikiCfg.getProperty("xwiki.url.protocol", "").equalsIgnoreCase("https"); - } - } diff --git a/celements-wiki-manager/component/src/main/java/com/celements/wiki/XWikiServerDescriptorService.java b/celements-wiki-manager/component/src/main/java/com/celements/wiki/XWikiServerDescriptorService.java index 214f83ceb..60953f005 100644 --- a/celements-wiki-manager/component/src/main/java/com/celements/wiki/XWikiServerDescriptorService.java +++ b/celements-wiki-manager/component/src/main/java/com/celements/wiki/XWikiServerDescriptorService.java @@ -1,10 +1,10 @@ package com.celements.wiki; -import static com.celements.logging.LogUtils.*; +import static com.celements.wiki.classes.XWikiServerClass.*; import static com.google.common.base.Preconditions.*; import static com.xpn.xwiki.XWikiConstant.*; -import java.util.Optional; +import java.util.List; import javax.inject.Inject; import javax.validation.constraints.NotNull; @@ -17,13 +17,21 @@ import org.xwiki.model.reference.WikiReference; import com.celements.model.access.IModelAccessFacade; +import com.celements.model.access.exception.DocumentDeleteException; import com.celements.model.access.exception.DocumentNotExistsException; +import com.celements.model.access.exception.DocumentSaveException; +import com.celements.model.classes.fields.ClassField; +import com.celements.model.object.xwiki.XWikiObjectEditor; import com.celements.model.object.xwiki.XWikiObjectFetcher; import com.celements.model.reference.RefBuilder; import com.celements.model.util.ModelUtils; -import com.celements.wiki.classes.XWikiServerClass; +import com.celements.wiki.WikiDescriptor.State; +import com.celements.wiki.WikiDescriptor.Visibility; +import com.celements.wiki.exception.WikiDescriptorException; import com.celements.wiki.exception.WikiMissingException; +import com.xpn.xwiki.XWikiConfigSource; import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.objects.BaseObject; @Service public class XWikiServerDescriptorService implements WikiDescriptorService { @@ -34,56 +42,131 @@ public class XWikiServerDescriptorService implements WikiDescriptorService { private final ModelUtils modelUtils; private final IModelAccessFacade modelAccess; + private final QueryWikiService wikiService; + private final XWikiConfigSource xwikiCfg; @Inject public XWikiServerDescriptorService( ModelUtils modelUtils, - IModelAccessFacade modelAccess) { + IModelAccessFacade modelAccess, + QueryWikiService wikiService, + XWikiConfigSource xwikiCfg) { this.modelUtils = modelUtils; this.modelAccess = modelAccess; + this.wikiService = wikiService; + this.xwikiCfg = xwikiCfg; } @Override - @NotNull public DocumentReference getDescriptorDocRef(@NotNull WikiReference wikiRef) { WikiReference normWikiRef = modelUtils.normalizeWikiRef(wikiRef); checkNotNull(normWikiRef); return RefBuilder.create() .with(modelUtils.getMainWikiRef()) .space(XWIKI_SPACE) - .doc(DOC_NAME_PREFIX - + StringUtils.capitalize(normWikiRef.getName())) + .doc(DOC_NAME_PREFIX + StringUtils.capitalize(normWikiRef.getName())) .build(DocumentReference.class); } + private XWikiDocument getDescriptorDoc(WikiReference wikiRef) throws WikiMissingException { + try { + return modelAccess.getDocument(getDescriptorDocRef(wikiRef)); + } catch (DocumentNotExistsException exc) { + throw new WikiMissingException(wikiRef, exc); + } + } + + @Override + public List getDescriptors(@NotNull WikiReference wikiRef) + throws WikiMissingException { + try { + XWikiDocument descriptorDoc = getDescriptorDoc(wikiRef); + return XWikiObjectFetcher.on(descriptorDoc).filter(CLASS_REF).stream() + .map(obj -> XWikiObjectFetcher.on(descriptorDoc).filter(obj)) + .map(fetcher -> toDescriptor(wikiRef, fetcher)) + .toList(); + } catch (IllegalArgumentException exc) { + throw new WikiMissingException(wikiRef, exc); + } + } + + private WikiDescriptor toDescriptor(WikiReference wikiRef, XWikiObjectFetcher fetcher) { + var server = first(fetcher, FIELD_SERVER); + var secure = Boolean.TRUE.equals(first(fetcher, FIELD_SECURE)); + return new WikiDescriptor( + wikiRef, + first(fetcher, FIELD_PRETTY_NAME), + server, + first(fetcher, FIELD_VISIBILITY), + first(fetcher, FIELD_STATE), + first(fetcher, FIELD_LANGUAGE), + secure, + first(fetcher, FIELD_OICD_ACTIVE), + wikiService.toUri(secure ? 1 : 0, server).orElse(null)); + } + + private T first(XWikiObjectFetcher fetcher, ClassField field) { + return fetcher.fetchField(field).findFirst().orElse(null); + } + @Override public boolean isOicdEnabled(@NotNull WikiReference wikiRef) { - return getWikiConfigOptional(wikiRef) - .flatMap(fetcher -> fetcher.fetchField(XWikiServerClass.FIELD_OICD_ACTIVE) - .findFirst()) - .orElse(false); + try { + return getDescriptors(wikiRef).stream() + .anyMatch(descriptor -> Boolean.TRUE.equals(descriptor.oicd())); + } catch (WikiMissingException exc) { + return false; + } } - @NotNull - private Optional getWikiConfigOptional(@NotNull WikiReference wikiRef) { + @Override + public void createDescriptor(WikiReference wikiRef, String host) throws WikiDescriptorException { + XWikiDocument descriptorDoc = modelAccess.getOrCreateDocument(getDescriptorDocRef(wikiRef)); + var hasDescriptor = XWikiObjectFetcher.on(descriptorDoc) + .filter(CLASS_REF) + .filter(FIELD_SERVER, host) + .exists(); + if (hasDescriptor) { + LOGGER.debug("skip wiki descriptor creation for [{}], [{}], already exists", + wikiRef.getName(), host); + return; + } + addServerObj(descriptorDoc, wikiRef, host); + descriptorDoc.setContent("#includeForm('XWiki.XWikiServerClassSheet')"); try { - return Optional.of(getWikiConfig(wikiRef)); - } catch (WikiMissingException exp) { - LOGGER.warn("no wiki found for {}", wikiRef, exp); + modelAccess.saveDocument(descriptorDoc, "createDescriptor " + host); + } catch (DocumentSaveException e) { + throw new WikiDescriptorException(wikiRef, e); } - return Optional.empty(); + LOGGER.info("created wiki descriptor for [{}]", wikiRef.getName()); } - @NotNull - private XWikiObjectFetcher getWikiConfig(@NotNull WikiReference wikiRef) - throws WikiMissingException { + @Override + public void deleteDescriptors(@NotNull WikiReference wikiRef) throws WikiDescriptorException { try { - XWikiDocument cfgDoc = modelAccess.getDocument(getDescriptorDocRef(wikiRef)); - LOGGER.debug("return object-fetcher for {}", defer(cfgDoc::getDocRef)); - return XWikiObjectFetcher.on(cfgDoc).filter(XWikiServerClass.CLASS_REF); - } catch (DocumentNotExistsException exp) { - throw new WikiMissingException(wikiRef, exp); + modelAccess.deleteDocument(getDescriptorDocRef(wikiRef), true); + } catch (DocumentDeleteException e) { + throw new WikiDescriptorException(wikiRef, e); } } + public BaseObject addServerObj(XWikiDocument doc, WikiReference wikiRef, String host) { + return XWikiObjectEditor.on(doc) + .filter(CLASS_REF) + .filter(FIELD_PRETTY_NAME, wikiRef.getName()) + .filter(FIELD_SERVER, host) + .filter(FIELD_SECURE, isSecure()) + .filter(FIELD_VISIBILITY, Visibility.PUBLIC) + .filter(FIELD_STATE, State.ACTIVE) + .filter(FIELD_LANGUAGE, "en") + .filter(FIELD_HOMEPAGE, "Content.WebHome") + .filter(FIELD_IS_TEMPLATE, false) + .filter(FIELD_OICD_ACTIVE, false) + .createFirst(); + } + + private boolean isSecure() { + return xwikiCfg.getProperty("xwiki.url.protocol", "").equalsIgnoreCase("https"); + } + } diff --git a/celements-wiki-manager/component/src/main/java/com/celements/wiki/api/WikiController.java b/celements-wiki-manager/component/src/main/java/com/celements/wiki/api/WikiController.java new file mode 100644 index 000000000..53a4849a7 --- /dev/null +++ b/celements-wiki-manager/component/src/main/java/com/celements/wiki/api/WikiController.java @@ -0,0 +1,108 @@ +package com.celements.wiki.api; + +import static com.celements.common.lambda.LambdaExceptionUtil.*; +import static org.springframework.http.HttpStatus.*; + +import java.util.Collection; +import java.util.List; + +import javax.inject.Inject; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; +import org.xwiki.model.reference.WikiReference; + +import com.celements.auth.user.User; +import com.celements.rights.access.IRightsAccessFacadeRole; +import com.celements.spring.security.AuthenticatedBaseController; +import com.celements.wiki.WikiCacheRefresher; +import com.celements.wiki.WikiCreator; +import com.celements.wiki.WikiDescriptor; +import com.celements.wiki.WikiDescriptorService; +import com.celements.wiki.WikiService; +import com.celements.wiki.exception.WikiCreationException; +import com.celements.wiki.exception.WikiExistsException; +import com.celements.wiki.exception.WikiMissingException; + +@RestController +@RequestMapping("/v1/wikis") +public class WikiController extends AuthenticatedBaseController { + + private final WikiService wikiService; + private final WikiDescriptorService descriptorService; + private final WikiCreator wikiCreator; + private final WikiCacheRefresher wikiCacheRefresher; + private final IRightsAccessFacadeRole rightsAccess; + + @Inject + public WikiController( + WikiService wikiService, + WikiDescriptorService descriptorService, + WikiCreator wikiCreator, + WikiCacheRefresher wikiCacheRefresher, + IRightsAccessFacadeRole rightsAccess) { + this.wikiService = wikiService; + this.descriptorService = descriptorService; + this.wikiCreator = wikiCreator; + this.wikiCacheRefresher = wikiCacheRefresher; + this.rightsAccess = rightsAccess; + } + + @GetMapping + public List getWikis() throws WikiMissingException { + requireSuperAdmin(); + return wikiService.streamAllWikis() + .map(rethrowFunction(descriptorService::getDescriptors)) + .flatMap(Collection::stream) + .toList(); + } + + @GetMapping("/{name}") + public List getWiki(@PathVariable String name) throws WikiMissingException { + requireSuperAdmin(); + var wikiRef = new WikiReference(name); + return descriptorService.getDescriptors(wikiRef); + } + + @PostMapping("/{name}") + public ResponseEntity> createWiki(@PathVariable String name) + throws WikiCreationException, WikiMissingException { + requireSuperAdmin(); + var wikiRef = new WikiReference(name); + wikiCreator.createWiki(wikiRef); + wikiCacheRefresher.refresh(); + return ResponseEntity.status(HttpStatus.CREATED) + .body(descriptorService.getDescriptors(wikiRef)); + } + + private User requireSuperAdmin() { + User user = checkAuth().orElseThrow(() -> new ResponseStatusException(HttpStatus.UNAUTHORIZED)); + if (!rightsAccess.isSuperAdmin(user)) { + throw new ResponseStatusException(HttpStatus.FORBIDDEN); + } + return user; + } + + @ExceptionHandler(WikiMissingException.class) + public ResponseEntity handleException(WikiMissingException e) { + return toErrorResponse(NOT_FOUND, e); + } + + @ExceptionHandler(WikiExistsException.class) + public ResponseEntity handleException(WikiExistsException e) { + return toErrorResponse(CONFLICT, e); + } + + @ExceptionHandler(WikiCreationException.class) + public ResponseEntity handleException(WikiCreationException e) { + return toErrorResponse(INTERNAL_SERVER_ERROR, e); + } + +} diff --git a/celements-wiki-manager/component/src/main/java/com/celements/wiki/classes/XWikiServerClass.java b/celements-wiki-manager/component/src/main/java/com/celements/wiki/classes/XWikiServerClass.java index 05056b3ef..3efc541f5 100644 --- a/celements-wiki-manager/component/src/main/java/com/celements/wiki/classes/XWikiServerClass.java +++ b/celements-wiki-manager/component/src/main/java/com/celements/wiki/classes/XWikiServerClass.java @@ -18,6 +18,8 @@ import com.celements.model.classes.fields.list.ListOfUsersField; import com.celements.model.classes.fields.list.single.EnumSingleListField; import com.celements.model.classes.fields.list.single.StringSingleListField; +import com.celements.wiki.WikiDescriptor.State; +import com.celements.wiki.WikiDescriptor.Visibility; import com.celements.web.classes.oldcore.IOldCoreClassDef; import com.xpn.xwiki.XWikiConstant; import com.xpn.xwiki.user.api.XWikiUser; @@ -32,14 +34,6 @@ public class XWikiServerClass extends AbstractClassDefinition implements ClassDe public static final String CLASS_DEF_HINT = CLASS_FN; public static final ClassReference CLASS_REF = new ClassReference(CLASS_SPACE, CLASS_NAME); - public enum Visibility { - PUBLIC, PRIVATE - } - - public enum State { - ACTIVE, INACTIVE, LOCKED - } - public static final ClassField FIELD_PRETTY_NAME = new StringField.Builder( CLASS_REF, "wikiprettyname") .prettyName("Wiki pretty name") diff --git a/celements-wiki-manager/component/src/test/java/com/celements/wiki/DefaultWikiCreatorTest.java b/celements-wiki-manager/component/src/test/java/com/celements/wiki/DefaultWikiCreatorTest.java index 1c5851e5a..2a087c2b0 100644 --- a/celements-wiki-manager/component/src/test/java/com/celements/wiki/DefaultWikiCreatorTest.java +++ b/celements-wiki-manager/component/src/test/java/com/celements/wiki/DefaultWikiCreatorTest.java @@ -144,7 +144,8 @@ private void expectWikiCreationEvents(WikiReference wikiRef, XWikiUser previousU assertEquals(wikiRef.getName(), xcontext.getDatabase()); return null; }).once(); - expect(wikiUpdater.getFuture(wikiRef)).andReturn(Optional.empty()).once(); + wikiUpdater.awaitCompletion(wikiRef); + expectLastCall().once(); eventPublisher.publishEvent(isA(WikiCreatedEvent.class)); expectLastCall().andAnswer(() -> { WikiCreatedEvent event = (WikiCreatedEvent) getCurrentArguments()[0]; diff --git a/celements-wiki-manager/component/src/test/java/com/celements/wiki/XWikiServerDescriptorServiceTest.java b/celements-wiki-manager/component/src/test/java/com/celements/wiki/XWikiServerDescriptorServiceTest.java index 082248a1f..f4ccac4cd 100644 --- a/celements-wiki-manager/component/src/test/java/com/celements/wiki/XWikiServerDescriptorServiceTest.java +++ b/celements-wiki-manager/component/src/test/java/com/celements/wiki/XWikiServerDescriptorServiceTest.java @@ -1,8 +1,15 @@ package com.celements.wiki; +import static com.celements.common.test.CelementsTestUtils.*; +import static com.celements.wiki.classes.XWikiServerClass.*; import static org.easymock.EasyMock.*; import static org.junit.Assert.*; +import java.net.URI; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + import org.junit.Before; import org.junit.Test; import org.xwiki.model.reference.DocumentReference; @@ -10,23 +17,41 @@ import com.celements.common.test.AbstractComponentTest; import com.celements.model.access.IModelAccessFacade; +import com.celements.model.access.exception.DocumentDeleteException; +import com.celements.model.access.exception.DocumentNotExistsException; +import com.celements.model.classes.ClassDefinition; +import com.celements.model.classes.fields.ClassField; +import com.celements.model.object.xwiki.XWikiObjectFetcher; import com.celements.model.util.ModelUtils; +import com.celements.wiki.WikiDescriptor.State; +import com.celements.wiki.WikiDescriptor.Visibility; +import com.celements.wiki.classes.XWikiServerClass; +import com.celements.wiki.exception.WikiDescriptorException; +import com.xpn.xwiki.XWikiConfigSource; import com.xpn.xwiki.XWikiConstant; +import com.xpn.xwiki.XWikiException; +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.objects.BaseObject; +import com.xpn.xwiki.objects.classes.BaseClass; +import com.xpn.xwiki.objects.classes.PropertyClass; public class XWikiServerDescriptorServiceTest extends AbstractComponentTest { - private WikiDescriptorService service; + private XWikiServerClass classDef; + private XWikiServerDescriptorService service; @Before public void prepareTest() throws Exception { - registerComponentMocks( - ModelUtils.class, - IModelAccessFacade.class); - service = getBeanFactory().getBean(WikiDescriptorService.class); + registerComponentMock(ModelUtils.class); + registerComponentMock(IModelAccessFacade.class); + registerComponentMock(QueryWikiService.class); + registerComponentMock(XWikiConfigSource.class); + classDef = getBeanFactory().getBean(XWikiServerClass.class); + service = getBeanFactory().getBean(XWikiServerDescriptorService.class); } @Test - public void test_loadingService() throws Exception { + public void test_loadingService() { replayDefault(); assertNotNull(service); verifyDefault(); @@ -37,10 +62,183 @@ public void test_getDescriptorDocRef_mainWiki() { expect(getMock(ModelUtils.class).getMainWikiRef()).andReturn(new WikiReference("unkownMain")); expect(getMock(ModelUtils.class).normalizeWikiRef(eq(XWikiConstant.MAIN_WIKI))) .andReturn(new WikiReference("main")); + replayDefault(); DocumentReference configDocRef = service.getDescriptorDocRef(XWikiConstant.MAIN_WIKI); verifyDefault(); + assertEquals("XWikiServerMain", configDocRef.getName()); } + @Test + public void test_createDescriptor() throws Exception { + WikiReference wikiRef = new WikiReference("mywiki"); + DocumentReference docRef = expectDescriptorDocRef(wikiRef); + XWikiDocument doc = new XWikiDocument(docRef); + expectClass(classDef, docRef.getWikiReference()); + expect(getMock(IModelAccessFacade.class).getOrCreateDocument(docRef)).andReturn(doc); + expect(getMock(XWikiConfigSource.class).getProperty("xwiki.url.protocol", "")) + .andReturn("https"); + getMock(IModelAccessFacade.class).saveDocument(same(doc), + eq("createDescriptor mywiki.example")); + + replayDefault(); + service.createDescriptor(wikiRef, "mywiki.example"); + verifyDefault(); + + XWikiObjectFetcher fetcher = XWikiObjectFetcher.on(doc).filter(CLASS_REF); + assertEquals(1, fetcher.count()); + assertEquals("mywiki", fetcher.fetchField(FIELD_PRETTY_NAME).findFirst().get()); + assertEquals("mywiki.example", fetcher.fetchField(FIELD_SERVER).findFirst().get()); + assertEquals(Boolean.TRUE, fetcher.fetchField(FIELD_SECURE).findFirst().get()); + assertEquals(Visibility.PUBLIC, fetcher.fetchField(FIELD_VISIBILITY).findFirst().get()); + assertEquals(State.ACTIVE, fetcher.fetchField(FIELD_STATE).findFirst().get()); + assertEquals("en", fetcher.fetchField(FIELD_LANGUAGE).findFirst().get()); + assertEquals("Content.WebHome", fetcher.fetchField(FIELD_HOMEPAGE).findFirst().get()); + assertEquals(Boolean.FALSE, fetcher.fetchField(FIELD_IS_TEMPLATE).findFirst().get()); + assertEquals(Boolean.FALSE, fetcher.fetchField(FIELD_OICD_ACTIVE).findFirst().get()); + assertEquals("#includeForm('XWiki.XWikiServerClassSheet')", doc.getContent()); + } + + @Test + public void test_getDescriptors_aliases() throws Exception { + WikiReference wikiRef = new WikiReference("mywiki"); + DocumentReference docRef = expectDescriptorDocRef(wikiRef); + XWikiDocument doc = new XWikiDocument(docRef); + addDescriptorObj(doc, wikiRef, "mywiki.example", true, false); + addDescriptorObj(doc, wikiRef, "alias.example", false, true); + expect(getMock(IModelAccessFacade.class).getDocument(docRef)).andReturn(doc); + expect(getMock(QueryWikiService.class).toUri(1, "mywiki.example")) + .andReturn(Optional.of(URI.create("https://mywiki.example"))); + expect(getMock(QueryWikiService.class).toUri(0, "alias.example")) + .andReturn(Optional.of(URI.create("http://alias.example"))); + + replayDefault(); + List ret = service.getDescriptors(wikiRef); + verifyDefault(); + + assertEquals(2, ret.size()); + assertDescriptor(ret.get(0), wikiRef, "mywiki.example", true, false, + URI.create("https://mywiki.example")); + assertDescriptor(ret.get(1), wikiRef, "alias.example", false, true, + URI.create("http://alias.example")); + } + + @Test + public void test_isOicdEnabled_true() throws Exception { + WikiReference wikiRef = new WikiReference("mywiki"); + DocumentReference docRef = expectDescriptorDocRef(wikiRef); + XWikiDocument doc = new XWikiDocument(docRef); + addDescriptorObj(doc, wikiRef, "mywiki.example", true, false); + addDescriptorObj(doc, wikiRef, "alias.example", false, true); + expect(getMock(IModelAccessFacade.class).getDocument(docRef)).andReturn(doc); + expect(getMock(QueryWikiService.class).toUri(anyInt(), anyString())).andReturn(Optional.empty()) + .times(2); + + replayDefault(); + assertTrue(service.isOicdEnabled(wikiRef)); + verifyDefault(); + } + + @Test + public void test_isOicdEnabled_false() throws Exception { + WikiReference wikiRef = new WikiReference("mywiki"); + DocumentReference docRef = expectDescriptorDocRef(wikiRef); + XWikiDocument doc = new XWikiDocument(docRef); + addDescriptorObj(doc, wikiRef, "mywiki.example", true, false); + expect(getMock(IModelAccessFacade.class).getDocument(docRef)).andReturn(doc); + expect(getMock(QueryWikiService.class).toUri(anyInt(), anyString())) + .andReturn(Optional.empty()); + + replayDefault(); + assertFalse(service.isOicdEnabled(wikiRef)); + verifyDefault(); + } + + @Test + public void test_isOicdEnabled_missingWiki() throws Exception { + WikiReference wikiRef = new WikiReference("missingwiki"); + DocumentReference docRef = expectDescriptorDocRef(wikiRef); + expect(getMock(IModelAccessFacade.class).getDocument(docRef)) + .andThrow(new DocumentNotExistsException(docRef)); + + replayDefault(); + assertFalse(service.isOicdEnabled(wikiRef)); + verifyDefault(); + } + + @Test + public void test_deleteDescriptors() throws Exception { + WikiReference wikiRef = new WikiReference("mywiki"); + DocumentReference docRef = expectDescriptorDocRef(wikiRef); + getMock(IModelAccessFacade.class).deleteDocument(docRef, true); + + replayDefault(); + service.deleteDescriptors(wikiRef); + verifyDefault(); + } + + @Test + public void test_deleteDescriptors_exception() throws Exception { + WikiReference wikiRef = new WikiReference("mywiki"); + DocumentReference docRef = expectDescriptorDocRef(wikiRef); + getMock(IModelAccessFacade.class).deleteDocument(docRef, true); + expectLastCall().andThrow(new DocumentDeleteException(docRef)); + + replayDefault(); + WikiDescriptorException exp = assertThrows(WikiDescriptorException.class, + () -> service.deleteDescriptors(wikiRef)); + verifyDefault(); + assertEquals(wikiRef, exp.getWikiRef()); + } + + private DocumentReference expectDescriptorDocRef(WikiReference wikiRef) { + WikiReference mainWikiRef = new WikiReference("xwikidb"); + WikiReference normWikiRef = new WikiReference(wikiRef.getName()); + DocumentReference docRef = new DocumentReference( + mainWikiRef.getName(), XWikiConstant.XWIKI_SPACE, + XWikiServerDescriptorService.DOC_NAME_PREFIX + + Character.toUpperCase(normWikiRef.getName().charAt(0)) + + normWikiRef.getName().substring(1)); + expect(getMock(ModelUtils.class).normalizeWikiRef(eq(wikiRef))).andReturn(normWikiRef); + expect(getMock(ModelUtils.class).getMainWikiRef()).andReturn(mainWikiRef); + return docRef; + } + + private void addDescriptorObj(XWikiDocument doc, WikiReference wikiRef, String host, + boolean secure, boolean oicd) { + BaseObject obj = new BaseObject(); + obj.setXClassReference(CLASS_REF.getDocRef(doc.getDocumentReference().getWikiReference())); + obj.setStringValue(FIELD_PRETTY_NAME.getName(), wikiRef.getName()); + obj.setStringValue(FIELD_SERVER.getName(), host); + obj.setIntValue(FIELD_SECURE.getName(), secure ? 1 : 0); + obj.setStringValue(FIELD_VISIBILITY.getName(), "public"); + obj.setStringValue(FIELD_STATE.getName(), "active"); + obj.setStringValue(FIELD_LANGUAGE.getName(), "en"); + obj.setStringValue(FIELD_HOMEPAGE.getName(), "Content.WebHome"); + obj.setIntValue(FIELD_IS_TEMPLATE.getName(), 0); + obj.setIntValue(FIELD_OICD_ACTIVE.getName(), oicd ? 1 : 0); + doc.addXObject(obj); + } + + private void assertDescriptor(WikiDescriptor descriptor, WikiReference wikiRef, String server, + boolean secure, boolean oicd, URI uri) { + assertEquals(wikiRef, descriptor.wiki()); + assertEquals(wikiRef.getName(), descriptor.prettyName()); + assertEquals(server, descriptor.server()); + assertEquals(Visibility.PUBLIC, descriptor.visibility()); + assertEquals(State.ACTIVE, descriptor.state()); + assertEquals("en", descriptor.language()); + assertEquals(secure, descriptor.secure()); + assertEquals(oicd, descriptor.oicd()); + assertEquals(uri, descriptor.uri()); + } + + private BaseClass expectClass(ClassDefinition classDef, WikiReference wikiRef) + throws XWikiException { + BaseClass bClass = expectNewBaseObject(classDef.getDocRef(wikiRef)); + return expectPropertyClasses(bClass, classDef.getFields().stream() + .collect(Collectors.toMap(ClassField::getName, ClassField::getXField))); + } + } diff --git a/celements-wiki-manager/component/src/test/java/com/celements/wiki/api/WikiControllerTest.java b/celements-wiki-manager/component/src/test/java/com/celements/wiki/api/WikiControllerTest.java new file mode 100644 index 000000000..a11ccdd3b --- /dev/null +++ b/celements-wiki-manager/component/src/test/java/com/celements/wiki/api/WikiControllerTest.java @@ -0,0 +1,193 @@ +package com.celements.wiki.api; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +import java.net.URI; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.aop.framework.Advised; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.server.ResponseStatusException; +import org.xwiki.model.reference.WikiReference; + +import com.celements.auth.user.User; +import com.celements.auth.user.UserService; +import com.celements.common.test.AbstractComponentTest; +import com.celements.rights.access.IRightsAccessFacadeRole; +import com.celements.wiki.WikiCacheRefresher; +import com.celements.wiki.WikiCreator; +import com.celements.wiki.WikiDescriptor; +import com.celements.wiki.WikiDescriptor.State; +import com.celements.wiki.WikiDescriptor.Visibility; +import com.celements.wiki.WikiDescriptorService; +import com.celements.wiki.WikiService; +import com.celements.wiki.exception.WikiExistsException; +import com.celements.wiki.exception.WikiMissingException; +import com.xpn.xwiki.user.api.XWikiUser; + +public class WikiControllerTest extends AbstractComponentTest { + + private WikiController controller; + private User user; + + @Before + public void prepareTest() throws Exception { + registerComponentMock(WikiService.class); + registerComponentMock(WikiDescriptorService.class); + registerComponentMock(WikiCreator.class); + registerComponentMock(WikiCacheRefresher.class); + registerComponentMock(IRightsAccessFacadeRole.class); + registerComponentMock(UserService.class); + user = createDefaultMock(User.class); + controller = getBeanTarget(getBeanFactory().getBean(WikiController.class)); + } + + @SuppressWarnings("unchecked") + private T getBeanTarget(T bean) throws Exception { + if (bean instanceof Advised advised) { + return (T) advised.getTargetSource().getTarget(); + } + return bean; + } + + @Test + public void test_getWikis() throws Exception { + expectSuperAdmin(); + WikiReference wikiRef = new WikiReference("mywiki"); + expect(getMock(WikiService.class).streamAllWikis()).andReturn(Stream.of(wikiRef)); + expectDescriptor(wikiRef); + + replayDefault(); + List ret = controller.getWikis(); + verifyDefault(); + assertEquals(1, ret.size()); + assertEquals(wikiRef, ret.get(0).wiki()); + assertEquals("My Wiki", ret.get(0).prettyName()); + assertEquals("mywiki.example", ret.get(0).server()); + assertEquals(Visibility.PUBLIC, ret.get(0).visibility()); + assertEquals(State.ACTIVE, ret.get(0).state()); + assertEquals(URI.create("https://mywiki.example"), ret.get(0).uri()); + } + + @Test + public void test_getWiki() throws Exception { + expectSuperAdmin(); + WikiReference wikiRef = new WikiReference("mywiki"); + expectDescriptor(wikiRef); + + replayDefault(); + List ret = controller.getWiki("mywiki"); + verifyDefault(); + assertEquals(1, ret.size()); + assertEquals(wikiRef, ret.get(0).wiki()); + assertEquals("My Wiki", ret.get(0).prettyName()); + assertEquals("mywiki.example", ret.get(0).server()); + assertEquals(Visibility.PUBLIC, ret.get(0).visibility()); + assertEquals(State.ACTIVE, ret.get(0).state()); + assertEquals("en", ret.get(0).language()); + assertEquals(Boolean.TRUE, ret.get(0).secure()); + assertEquals(Boolean.FALSE, ret.get(0).oicd()); + assertEquals(URI.create("https://mywiki.example"), ret.get(0).uri()); + } + + @Test + public void test_createWiki() throws Exception { + expectSuperAdmin(); + WikiReference wikiRef = new WikiReference("newwiki"); + getMock(WikiCreator.class).createWiki(wikiRef); + getMock(WikiCacheRefresher.class).refresh(); + expectDescriptor(wikiRef); + + replayDefault(); + ResponseEntity> ret = controller.createWiki("newwiki"); + verifyDefault(); + assertEquals(HttpStatus.CREATED, ret.getStatusCode()); + assertEquals(wikiRef, ret.getBody().get(0).wiki()); + assertEquals("My Wiki", ret.getBody().get(0).prettyName()); + assertEquals(URI.create("https://newwiki.example"), ret.getBody().get(0).uri()); + } + + @Test + public void test_createWiki_conflict() throws Exception { + expectSuperAdmin(); + WikiReference wikiRef = new WikiReference("existingwiki"); + getMock(WikiCreator.class).createWiki(wikiRef); + expectLastCall().andThrow(new WikiExistsException(wikiRef)); + + replayDefault(); + assertThrows(WikiExistsException.class, () -> controller.createWiki("existingwiki")); + verifyDefault(); + } + + @Test + public void test_handleException_wikiExists() throws Exception { + expect(getMock(IRightsAccessFacadeRole.class).isSuperAdmin()).andReturn(true); + WikiReference wikiRef = new WikiReference("existingwiki"); + + replayDefault(); + ResponseEntity ret = controller.handleException(new WikiExistsException(wikiRef)); + verifyDefault(); + assertEquals(HttpStatus.CONFLICT, ret.getStatusCode()); + } + + @Test + public void test_getWikis_unauthorized() throws Exception { + expect(getXContext().getWiki().checkAuth(same(getXContext()))).andReturn(null); + + replayDefault(); + try { + controller.getWikis(); + fail("Expected UNAUTHORIZED"); + } catch (ResponseStatusException rse) { + assertEquals(HttpStatus.UNAUTHORIZED, rse.getStatus()); + } + verifyDefault(); + } + + @Test + public void test_getWikis_forbidden() throws Exception { + expectAuth(); + expect(getMock(IRightsAccessFacadeRole.class).isSuperAdmin(user)).andReturn(false); + + replayDefault(); + try { + controller.getWikis(); + fail("Expected FORBIDDEN"); + } catch (ResponseStatusException rse) { + assertEquals(HttpStatus.FORBIDDEN, rse.getStatus()); + } + verifyDefault(); + } + + private void expectSuperAdmin() throws Exception { + expectAuth(); + expect(getMock(IRightsAccessFacadeRole.class).isSuperAdmin(user)).andReturn(true); + } + + private void expectAuth() throws Exception { + XWikiUser xuser = new XWikiUser("xwiki:XWiki.Admin", true); + expect(getXContext().getWiki().checkAuth(same(getXContext()))).andReturn(xuser); + expect(getMock(UserService.class).getUser(eq("xwiki:XWiki.Admin"))).andReturn(user); + } + + private void expectDescriptor(WikiReference wikiRef) throws WikiMissingException { + WikiDescriptor descriptor = new WikiDescriptor( + wikiRef, + "My Wiki", + wikiRef.getName() + ".example", + Visibility.PUBLIC, + State.ACTIVE, + "en", + true, + false, + URI.create("https://" + wikiRef.getName() + ".example")); + expect(getMock(WikiDescriptorService.class).getDescriptors(wikiRef)) + .andReturn(List.of(descriptor)); + } + +} diff --git a/celements-wiki-manager/web-module/src/main/webapp/docs/xwiki/WikiManager/CreateNewWiki.xml b/celements-wiki-manager/web-module/src/main/webapp/docs/xwiki/WikiManager/CreateNewWiki.xml index 08a745905..c1979dfb5 100644 --- a/celements-wiki-manager/web-module/src/main/webapp/docs/xwiki/WikiManager/CreateNewWiki.xml +++ b/celements-wiki-manager/web-module/src/main/webapp/docs/xwiki/WikiManager/CreateNewWiki.xml @@ -57,603 +57,19 @@ -############################################################################################ -## Create a new wiki with initial minimum informations step by step or in one page. -## -## Can use URL parameters : -## -doc -## 0 : Just show input and properties names -## 1 : Print documentation for each field -## -stepbystep -## 0 : All informations in one page and create button -## 1 : Step by step based on javascript -## -############################################################################################ -## PLUGINS DEPENDANCIES -#set ($WikiManager = $xwiki.wikimanager) -#if (!$WikiManager) - #error($msg.get("wikimanager.pluginnotenabled")) -#end -#if (!$xwiki.applicationmanager) - #error($msg.get("xapp.pluginnotenabled")) -#end -#if(!$xwiki.isVirtualMode()) - #error($msg.get("wikimanager.notinvirtualmode")) -#end -############################################################################################ -## MACROS -#macro(getRequestList $paramlist $paramname) - #set ($paramtable = []) - #set ($paramtable = $request.getParameterValues($paramname)) - #if ($paramtable) - #set ($paramlist = []) - #foreach($paramvalue in $paramtable) - #set ($ok = $paramlist.add($paramvalue)) - #end - #end -#end -## -#macro(printUsersAndGroups $users $groups $rightlevel $userlist $grouplist $hidden) - <select #if ($hidden) type="hidden" #end name="${rightlevel}users" id="${rightlevel}users" multiple="multiple"> - #foreach ($user in $users) - #if ($context.database == $context.mainWikiName) #set ($user = "${context.mainWikiName}:${user}") #end - <option value="$user" #if ($userlist && $userlist.contains($user)) selected="selected" #end>$xwiki.getUserName($user, $util.null, false)</option> - #end - </select> - <select #if ($hidden) type="hidden" #end name="${rightlevel}groups" id="${rightlevel}groups" multiple="multiple"> - #foreach ($group in $groups) - #if ($context.database == $context.mainWikiName) #set ($group = "${context.mainWikiName}:${group}") #end - #set ($pointindex = $group.indexOf(".") + 1) - <option value="$group" #if ($grouplist && $grouplist.contains($group)) selected="selected" #end>$group.substring($pointindex)</option> - #end - </select> -#end -## -#macro(addRights $prefdoc $userlist $grouplist $rights $needsave) - #set ($users = "") - #foreach($user in $userlist) - #if ($users != "") - #set ($users = "${users},${user}") - #else - #set ($users = $user) - #end - #end - #set ($groups = "") - #foreach($group in $grouplist) - #if ($groups != "") - #set ($groups = "${groups},${group}") - #else - #set ($groups = $group) - #end - #end - ## - #if (($users != "") || ($groups != "")) - #set ($rightsobj = $prefdoc.newObject("XWiki.XWikiGlobalRights")) - ## - #set ($ok = $rightsobj.set("users", $users)) - #set ($ok = $rightsobj.set("groups", $groups)) - #set ($ok = $rightsobj.set("levels", $rights)) - #set ($ok = $rightsobj.set("allow", 1)) - ## - #set ($needsave = true) - #end -#end -############################################################################################ -## TOOLS -#set ($Exception = $WikiManager.DefaultException) -#set ($ALIASSUFFIX = ".ng.demospace.ch") -#set ($WSTEPID_INTRO = 0) ## Wiki creation introduction -#set ($WSTEPNAME_INTRO = "wstep_intro") -#set ($WSTEPID_WIKINAME = 1) ## Wiki name -#set ($WSTEPNAME_WIKINAME = "wstep_wikiname") -#set ($WSTEPID_WIKIDESC = 2) ## Wiki descriptor informations -#set ($WSTEPNAME_WIKIDESC = "wstep_wikidesc") -#set ($WSTEPID_DATAFROM = 3) ## Initialise wiki data from wiki template or XAR package -#set ($WSTEPNAME_DATAFROM = "wstep_datafrom") -#set ($WSTEPID_USERS = 4) ## Preregistered users -#set ($WSTEPNAME_USERS = "wstep_users") -#set ($WSTEPID_SUMMARY = 5) ## Summary be fore create -#set ($WSTEPNAME_SUMMARY = "wstep_summary") -#set ($WSTEPLIST = [$WSTEPNAME_INTRO, $WSTEPNAME_WIKINAME, $WSTEPNAME_WIKIDESC, $WSTEPNAME_DATAFROM, $WSTEPNAME_USERS, $WSTEPNAME_SUMMARY]) -#set ($ISWIKINAMEAVAILABLE = $xwiki.getDocument("WikiCode.IsWikiOrDatabaseAvailableService").URL) -#set ($MSG_ERROR_WIKIALREADYEXISTS = "<div class=\"errormessage\"><span class=\"messagetype\">$msg.get('error'): </span>$msg.get('wikimanager.wikiname.error.wikialreadyexists')</div>") -#set ($MSG_WARNING_DATABASEALREADYEXISTS = "<div class=\"warningmessage\"><span class=\"messagetype\">$msg.get('warning'): </span>$msg.get('wikimanager.wikiname.error.databasealreadyexists')</div>") -#set ($MSG_ERROR_DATABASEALREADYEXISTS = "<div class=\"errormessage\"><span class=\"messagetype\">$msg.get('error'): </span>$msg.get('wikimanager.wikiname.error.databasealreadyexists')</div>") -#set ($MSG_ERROR_WIKINAMEALREADYUSED = "<div class=\"errormessage\"><span class=\"messagetype\">$msg.get('error'): </span>$msg.get('wikimanager.wikiname.error.alreadyused')</div>") -#set ($MSG_ERROR_WIKINAMEEMPTY = "<div class=\"errormessage\"><span class=\"messagetype\">$msg.get('error'): </span>$msg.get('wikimanager.wikiname.error.empty')</div>") -#set ($MSG_INFO_WIKINAMEVALID = "<div class=\"infomessage\"><span class=\"messagetype\">$msg.get('info'): </span>$msg.get('wikimanager.wikiname.info.valid')</div>") -## -############################################################################################ -## REQUEST PARAMETERS -#if ($request.stepbystep) - #set ($wstepbystep = $request.stepbystep) -#end -#if ($request.doc && $request.doc == "1") - #set ($documentation = 1) -#end -## -#set ($wikidocument = $WikiManager.createWikiDocument()) -#set ($wikidocumentobject = $wikidocument.updateObjectFromRequest("XWiki.XWikiServerClass")) -## -#if ($request.actioncreate) - #set ($action = "create") -#else - #set ($action = $request.getParameter("action")) -#end -## -#set ($wikiname = $request.getParameter("wikiname")) -#set ($wikitemplate = $request.getParameter("wikitemplate")) -#set ($wikipackage = $request.getParameter("wikipackage")) -#if ($wikidocument.owner == "") - $wikidocument.set("owner", $context.user) -#end -#if ($wikidocument.server == "" && $wikiname && $wikiname != "") - $wikidocument.set("server", "${wikiname}.${DOMAINNAME}") -#end -## -#getRequestList($readeruserlist "readersusers") -#getRequestList($readergrouplist "readersgroups") -#getRequestList($writeruserlist "writersusers") -#getRequestList($writergrouplist "writersgroups") -#getRequestList($adminuserlist "adminsusers") -#getRequestList($admingrouplist "adminsgroups") -#if ($request.forcewikiname && $request.forcewikiname == 'on') - #set ($failonexist = false) -#else - #set ($failonexist = true) -#end -## -############################################################################# -## -1 $msg.get("wikimanager.createwiki") -#if ($wstepbystep) - [$msg.get("wikimanager.action.createwiki.nonstepbystep")>CreateNewWiki#if($documentation)?doc=1#end] -#else - [$msg.get("wikimanager.action.createwiki.stepbystep")>CreateNewWiki?stepbystep=0&amp;#if($documentation)doc=1#end] -#end -## -#if ($action && $action == "create") - #set ($result = $WikiManager.createNewWiki($wikiname, $wikitemplate, $wikipackage, $wikidocument, $failonexist)) - ## - #if ($result == $Exception.ERROR_NOERROR) - ## Init new wiki global rights - #set ($currentwiki = $context.database) - #set ($ok = $context.setDatabase($wikidocument.wikiName)) - ## - #set ($prefdoc = $xwiki.getDocument("XWiki.XWikiPreferences")) - ## - #set ($needsave = false) - ## - #addRights($prefdoc $readeruserlist $readergrouplist "view, comment" $needsave) - #addRights($prefdoc $writeruserlist $writergrouplist "edit, view, comment" $needsave) - #addRights($prefdoc $adminuserlist $admingrouplist "admin" $needsave) - ## - #if ($needsave) - $prefdoc.save() - #end - ## - #set ($ok = $context.setDatabase($currentwiki)) - ## - #info($msg.get("wikimanager.successcreatewiki", [$wikiname, $wikidocument.getHomePageUrl()])) - #else - #if ($result == $Exception.ERROR_WM_WIKIALREADYEXISTS) - #error($msg.get("wikimanager.errorcreatewiki.ERROR_WM_WIKIALREADYEXISTS", [$wikiname, $result])) - #else - #error($msg.get("wikimanager.errorcreatewiki", [$wikiname, $context.lastexception])) - #end - #end -#end -## -############################################################################# -## -{pre} -<script type="text/javascript"> -// <![CDATA[ - var domainnamesetted = false; - var prettynamesetted = false; - var lastwikiname; -#if ($wstepbystep) - var steps = new Array(#foreach ($wstep in $WSTEPLIST)#if ($velocityCount > 1), #end"$wstep"#end) - var currentstep = $wstepbystep; +1 Wiki Creation API - function getUsersGroupsValue(users, groups) - { - var str = ""; +This page no longer creates wikis. The legacy Wiki Manager plugin flow has been retired. - if (users.value != "" || users.value != "") { - str = "<ul class=\"star\">"; +Use the wiki creation API instead: - if (users.value != "") - str += "<li>Users: " + users.value + "<\/li>" - if (groups.value != "") - str += "<li>Groups: " + groups.value + "<\/li>" +{code} +POST /api/v1/wikis/{WIKI_NAME} +{code} - str += "<\/ul>"; - } - - return str; - } +The endpoint requires an authenticated superadmin user. - function refreshSummary() - { - $("summarywikiname").innerHTML = "<p>" + $("wikiname").value + "<\/p>"; - $("summarywikiprettyname").innerHTML = "<p>" + $("XWiki.XWikiServerClass_0_wikiprettyname").value + "<\/p>"; - $("summarywikidesc").innerHTML = "<p>" + $("XWiki.XWikiServerClass_0_description").value + "<\/p>"; - $("summarywikidomain").innerHTML = "<p>" + $("XWiki.XWikiServerClass_0_server").value + "<\/p>"; - $("summarywikiadmin").innerHTML = "<p>" + $("XWiki.XWikiServerClass_0_owner").value + "<\/p>"; - $("summarywikitemplate").innerHTML = "<p>" + $("wikitemplate").value + "<\/p>"; - $("summarywikipackage").innerHTML = "<p>" + $("wikipackage").value + "<\/p>"; - $("summaryreaders").innerHTML = getUsersGroupsValue($("readersusers"), $("readersgroups")); - $("summarywriters").innerHTML = getUsersGroupsValue($("writersusers"), $("writersgroups")); - $("summaryadmins").innerHTML = getUsersGroupsValue($("adminsusers"), $("adminsgroups")); - } - - function showStep() - { - for (var i = 0; i < steps.length; ++i) { - if (i != currentstep) - addClass($(steps[i]), "hidden"); - else - rmClass($(steps[i]), "hidden"); - } - - if (currentstep > 0) - rmClass($("actionprevious"), "hidden"); - else - addClass($("actionprevious"), "hidden"); - - if (currentstep < steps.length-1) { - rmClass($("actionnext"), "hidden"); - addClass($("actioncreate"), "hidden"); - } else { - addClass($("actionnext"), "hidden"); - rmClass($("actioncreate"), "hidden"); - - refreshSummary(); - } - } - - function goNext() - { - ++currentstep; - showStep(); - } - - function goPrevious() - { - --currentstep; - showStep(); - } - -#end - - function validateWikiName() - { - $('wikiname').value = noaccent($('wikiname').value).toLowerCase(); - - var wikiname = $('wikiname').value; - - if (lastwikiname == wikiname) - { - return; - } - - lastwikiname = wikiname; - - if (wikiname && wikiname != "") - { - $('wikinamevalidation').innerHTML = "$MSG_ERROR_WIKINAMEEMPTY"; - - var surl = "$ISWIKINAMEAVAILABLE" + "?xpage=plain&ajax=1&wikiname=" + escape(wikiname); - new Ajax.Request(surl, - { - method: 'get', - onSuccess: function(transport) { - var hideForceWikiName = false; - - if (transport.responseText == "true") - { - $('wikinamevalidation').innerHTML = "$MSG_INFO_WIKINAMEVALID"; - $('actioncreatebutton').disabled = false; - } - else if (transport.responseText == "database") - { - hideForceWikiName = false; - - forceWikiNameChanged(); - } - else if (transport.responseText == "wiki") - { - $('wikinamevalidation').innerHTML = "$MSG_ERROR_WIKIALREADYEXISTS"; - $('actioncreatebutton').disabled = true; - } - else - { - $('wikinamevalidation').innerHTML = "$MSG_ERROR_WIKINAMEALREADYUSED"; - $('actioncreatebutton').disabled = true; - } - - if (hideForceWikiName) - { - addClass($('forcewikinamediv'), "hidden"); - } - else - { - rmClass($('forcewikinamediv'), "hidden"); - } - } - }); - } - else - { - $('wikinamevalidation').innerHTML = "$MSG_ERROR_WIKINAMEEMPTY"; - $('actioncreatebutton').disabled = true; - addClass($('forcewikinamediv'), "hidden"); - } - } - - function forceWikiNameChanged() - { - if ($('forcewikiname').checked == true) - { - $('wikinamevalidation').innerHTML = "$MSG_WARNING_DATABASEALREADYEXISTS"; - $('actioncreatebutton').disabled = false; - } - else - { - $('wikinamevalidation').innerHTML = "$MSG_ERROR_DATABASEALREADYEXISTS"; - $('actioncreatebutton').disabled = true; - } - } - - function wikiNameChanged() - { - validateWikiName(); - - if (domainnamesetted == false) { - $("XWiki.XWikiServerClass_0_server").value = $("wikiname").value + "$ALIASSUFFIX"; - } - - if (prettynamesetted == false) { - $("XWiki.XWikiServerClass_0_wikiprettyname").value = $("wikiname").value.substring(0,1).toUpperCase() + $("wikiname").value.substring(1); - } - } - - function domainNameChanged() - { - domainnamesetted = true; - } - - function prettyNameChanged() - { - prettynamesetted = true; - } - - function validate() - { - } -// ]]> -</script> -{/pre} -<form method="get" action="" id="wikicreationform"> - #if ($wstepbystep) - <div id="$WSTEPNAME_INTRO"> - ##1.1 $msg.get("wikimanager.title.createwiki.intro") - <p>$msg.get("wikimanager.doc.createwiki.intro")</p> - </div> - #end - ## - ############################################################################# - ## - <div id="$WSTEPNAME_WIKINAME"> - #if ($wstepbystep) - 1.1 $msg.get("wikimanager.title.createwiki.wikiname") - #end - <table> - <tr> - <td> - <dl> - <dt>$msg.get("wikimanager.prop.wiki.wikiname")</dt> - <dd> - <input size="40" id="wikiname" name="wikiname" type="text" onchange="wikiNameChanged();" onkeyup="wikiNameChanged();" /> - <br /> - <div id="wikinamevalidation"></div> - <div id="forcewikinamediv"><input id="forcewikiname" name="forcewikiname" type="checkbox" #if ($failonexist == false)checked="true"#end onchange="forceWikiNameChanged();"/>$msg.get("wikimanager.wikiname.force")</div> - </dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.wikiname")</td> #end - </tr> - </table> - </div> - ## - ############################################################################# - ## - <div id="$WSTEPNAME_WIKIDESC"> - #if ($wstepbystep) - 1.1 $msg.get("wikimanager.title.createwiki.desc") - #if ($documentation) $msg.get("wikimanager.doc.createwiki.desc") #end - #end - <table> - <tr> - <td> - <dl> - <dt>$msg.get("wikimanager.prop.wiki.wikiprettyname")</dt> - <dd><input size="40" id="XWiki.XWikiServerClass_0_wikiprettyname" name="XWiki.XWikiServerClass_0_wikiprettyname" type="text" onchange="prettyNameChanged();" /></dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.desc.wikiprettyname")</td> #end - </tr> - <tr> - <td> - <dl> - <dt>$msg.get("wikimanager.prop.wiki.description")</dt> - <dd>$wikidocument.display("description", "edit")</dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.desc.description")</td> #end - </tr> - <tr> - <td> - <dl> - <dt>$msg.get("wikimanager.prop.wiki.server")</dt> - <dd><input size="40" id="XWiki.XWikiServerClass_0_server" name="XWiki.XWikiServerClass_0_server" type="text" onchange="domainNameChanged();" /></dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.desc.server.creation", [$ALIASSUFFIX])</td> #end - </tr> - <tr> - <td> - <dl> - <dt>$msg.get("wikimanager.prop.wiki.owner")</dt> - <dd>$wikidocument.display("owner", "edit")</dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.desc.owner")</td> #end - </tr> - </table> - </div> - ## - ############################################################################# - ## - <div id="$WSTEPNAME_DATAFROM"> - #if ($wstepbystep) - 1.1 $msg.get("wikimanager.title.createwiki.datafrom") - #if ($documentation) $msg.get("wikimanager.doc.createwiki.datafrom") #end - #end - <table> - <tr> - <td> - <dl> - <dt><label for="wikitemplate">$msg.get("wikimanager.wikitemplate")</label></dt> - <dd> - #set ($listtemplate=$WikiManager.getWikiTemplateList()) - <select #if($listtemplate.size() == 0)disabled="disabled"#end name="wikitemplate" id="wikitemplate"> - <option value="">---</option> - #foreach ($template in $listtemplate) - <option value="$template.wikiName">#if($template.wikiPrettyName != "")$template.wikiPrettyName#else$template.wikiName#end</option> - #end - </select> - </dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.datafrom.template")</td> #end - </tr> - <tr> - <td> - <dl> - <dt><label for="wikipackage">$msg.get("wikimanager.wikipackage")</label></dt> - <dd> - #set ($listpackage=$doc.getAttachmentList()) - <select #if($listpackage.size() == 0)disabled="disabled"#end name="wikipackage" id="wikipackage"> - <option value="">---</option> - #foreach ($package in $listpackage) - <option value="$package.getFilename()">$package.getFilename()</option> - #end - </select> - </dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.datafrom.package")</td> #end - </tr> - </table> - </div> - ## - ############################################################################# - ## - #set ($rightsmanager = $xwiki.rightsmanager) - #set ($users = $rightsmanager.usersApi.allGlobalUsersNames) - #set ($groups = $rightsmanager.groupsApi.allGlobalGroupsNames) - <div id="$WSTEPNAME_USERS"> - #if ($wstepbystep) - 1.1 $msg.get("wikimanager.title.createwiki.members") - #if ($documentation) $msg.get("wikimanager.doc.createwiki.members") #end - #end - <table> - <tr> - <td> - <dl> - <dt><label for="readersusers">$msg.get("wikimanager.readers")</label></dt> - <dd>#printUsersAndGroups($users $groups "readers" $readeruserlist $readergrouplist false)</dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.members.readers")</td> #end - </tr> - <tr> - <td> - <dl> - <dt><label for="writersusers">$msg.get("wikimanager.writers")</label></dt> - <dd>#printUsersAndGroups($users $groups "writers" $writeruserlist $writergrouplist false)</dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.members.writers")</td> #end - </tr> - <tr> - <td> - <dl> - <dt><label for="adminsusers">$msg.get("wikimanager.admins")</label></dt> - <dd>#printUsersAndGroups($users $groups "admins" $adminuserlist $admingrouplist false)</dd> - </dl> - </td> - #if ($documentation) <td>$msg.get("wikimanager.doc.createwiki.members.administrators")</td> #end - </tr> - </table> - </div> - ## - ############################################################################# - ## - #if ($wstepbystep) - <div id="$WSTEPNAME_SUMMARY"> - 1.1 $msg.get("wikimanager.title.createwiki.summary") - #if ($documentation) $msg.get("wikimanager.doc.createwiki.summary") #end - <table class="wiki-table" border="0" cellpadding="0" cellspacing="0"> - <tbody> - <tr><th>Properties</th><th>Values</th></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.prop.wiki.wikiname")*</td><td id="summarywikiname">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.prop.wiki.wikiprettyname")*</td><td id="summarywikiprettyname">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.prop.wiki.description")*</td><td id="summarywikidesc">---</td></tr> - <tr class="table-even"><td>*$msg.get("wikimanager.prop.wiki.server")*</td><td id="summarywikidomain">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.prop.wiki.owner")*</td><td id="summarywikiadmin">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.wikitemplate")*</td><td id="summarywikitemplate">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.wikipackage")*</td><td id="summarywikipackage">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.readers")*</td><td id="summaryreaders">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.writers")*</td><td id="summarywriters">---</td></tr> - <tr class="table-odd"><td>*$msg.get("wikimanager.admins")*</td><td id="summaryadmins">---</td></tr> - </tbody> - </table> - </div> - #end - ## - ############################################################################# - ## - <div> - #if ($wstepbystep) - <a href="javascript:void(0)" id="actionprevious" class="button" onclick="goPrevious();">${msg.get("wikimanager.action.previous")}</a> - | - <a href="javascript:void(0)" id="actionnext" class="button" onclick="goNext();">${msg.get("wikimanager.action.next")}</a> - #end - <div id="actioncreate"> - <br /> - #if ($request.stepbystep) <input type="hidden" name="stepbystep" value="$request.stepbystep" /> #end - #if ($request.doc) <input type="hidden" name="doc" value="$request.doc" /> #end - <input type="submit" id="actioncreatebutton" name="actioncreate" value="${msg.get("create")}" onclick="return validate();" /> - </div> - </div> -</form> -{pre} -<script type="text/javascript"> -// <![CDATA[ - validateWikiName() - -#if ($wstepbystep) - showStep(); - - if ($("XWiki.XWikiServerClass_0_server").value != "") - domainnamesetted = true; - - if ($("XWiki.XWikiServerClass_0_wikiprettyname").value != "") - prettynamesetted = true; -#end -// ]]> -</script> -{/pre} +{code} +curl -X POST -u ${USERNAME}:${PASSWORD} https://main.${HOST}/api/v1/wikis/${WIKI_NAME} +{code} + diff --git a/celements-xwiki-core/src/main/java/com/celements/init/update/WikiUpdater.java b/celements-xwiki-core/src/main/java/com/celements/init/update/WikiUpdater.java index 397721a94..50773f6ed 100644 --- a/celements-xwiki-core/src/main/java/com/celements/init/update/WikiUpdater.java +++ b/celements-xwiki-core/src/main/java/com/celements/init/update/WikiUpdater.java @@ -64,6 +64,14 @@ public Optional> getFuture(WikiReference wiki) { return Optional.ofNullable(wikiUpdates.get(wiki)); } + public void awaitCompletion(WikiReference wikiRef) { + CompletableFuture none = CompletableFuture.completedFuture(null); + CompletableFuture awaited; + do { + (awaited = getFuture(wikiRef).orElse(none)).join(); + } while (awaited != getFuture(wikiRef).orElse(none)); + } + public Map> getAllFutures() { return Collections.unmodifiableMap(wikiUpdates); }