mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-17 14:21:39 +00:00
Compare commits
68 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
50f26b9137 | ||
|
b6b1cc3ea0 | ||
|
0f1c1cdba1 | ||
|
841bc6844e | ||
|
a5bdf47f00 | ||
|
a0b279d1ff | ||
|
fb967dfa9e | ||
|
f0a51e1347 | ||
|
42d56f9d20 | ||
|
3f31e4b1a2 | ||
|
787a331869 | ||
|
5ce3a3ddd6 | ||
|
9ed96ec593 | ||
|
03b1fa8b09 | ||
|
d69f9b52c3 | ||
|
72b910bb48 | ||
|
cfaf3b280b | ||
|
00d814ec55 | ||
|
becabb3a41 | ||
|
033157800b | ||
|
b9c8ff91e4 | ||
|
c54d46ab67 | ||
|
dec514c5c2 | ||
|
7c5a8a1963 | ||
|
559171a32c | ||
|
b9f449df57 | ||
|
3185ecf6cb | ||
|
bd7f2a4250 | ||
|
79efa12b10 | ||
|
5807e756bd | ||
|
6ecb019b84 | ||
|
c26f933c44 | ||
|
43e528878e | ||
|
b120a9658f | ||
|
3875a84f74 | ||
|
8dddf293d0 | ||
|
d01e9ffbbc | ||
|
6f8507ebe2 | ||
|
923261d9b9 | ||
|
078e461b71 | ||
|
ddde92ef21 | ||
|
189011d528 | ||
|
af849d2144 | ||
|
53208f207c | ||
|
4cf3f77824 | ||
|
9d24e083bb | ||
|
6345c0a825 | ||
|
cda3d11c7e | ||
|
7ad35ac60d | ||
|
a164917232 | ||
|
507c6b2ed8 | ||
|
ab0d65897c | ||
|
d92844cebb | ||
|
25986d77d6 | ||
|
2b8948b84b | ||
|
64bf49cc22 | ||
|
3ce95c5262 | ||
|
e854a01988 | ||
|
65ba8b16e0 | ||
|
d2bb3a980d | ||
|
59b641474f | ||
|
9ee56762fb | ||
|
6cb8e84ee4 | ||
|
d540bb319b | ||
|
30a2bff92a | ||
|
ac08612183 | ||
|
031d1c740c | ||
|
aac73e2064 |
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
|
||||
|
@@ -619,11 +619,27 @@ public class BaseRMRestTest extends RestTest
|
||||
* @return
|
||||
*/
|
||||
public List<String> searchForContentAsUser(UserModel user, String term)
|
||||
{
|
||||
String query = "cm:name:*" + term + "*";
|
||||
return searchForContentAsUser(user,query,"afts");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns search results for the given search term
|
||||
*
|
||||
* @param user
|
||||
* @param term
|
||||
* @param query language
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public List<String> searchForContentAsUser(UserModel user, String q, String queryLanguage)
|
||||
{
|
||||
getRestAPIFactory().getRmRestWrapper().authenticateUser(user);
|
||||
RestRequestQueryModel queryReq = new RestRequestQueryModel();
|
||||
SearchRequest query = new SearchRequest(queryReq);
|
||||
queryReq.setQuery("cm:name:*" + term + "*");
|
||||
queryReq.setQuery(q);
|
||||
queryReq.setLanguage(queryLanguage);
|
||||
|
||||
List<String> names = new ArrayList<>();
|
||||
// wait for solr indexing
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Nelze vytv\u00e1\u0159et
|
||||
rm.action.create.transfer.child-error-message=Nelze vytv\u00e1\u0159et polo\u017eky ve slo\u017ece p\u0159enosu.
|
||||
rm.action.create.record.folder.child-error-message=Z\u00e1znamy je mo\u017en\u00e9 vytv\u00e1\u0159et pouze ve slo\u017ek\u00e1ch z\u00e1znam\u016f a toto bylo {0}.
|
||||
rm.action.transfer-non-editable=Nelze upravovat metadata kontejneru nebo slo\u017eky pro p\u0159enos.
|
||||
|
||||
rm.action.node.frozen.error-message=Akci {0} nelze prov\u00e9st, proto\u017ee uzel je zablokovan\u00fd nebo m\u00e1 zablokovan\u00e9 pod\u0159\u00edzen\u00e9 prvky.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Du kan ikke oprette elem
|
||||
rm.action.create.transfer.child-error-message=Du kan ikke oprette elementer i Overf\u00f8r-mapper.
|
||||
rm.action.create.record.folder.child-error-message=Du kan kun oprette poster i postmapper, og dette var en {0}.
|
||||
rm.action.transfer-non-editable=Du kan ikke redigere overf\u00f8rselsmappe- eller container-metadata.
|
||||
|
||||
rm.action.node.frozen.error-message=Handlingen kan ikke udf\u00f8res {0}, fordi noden er l\u00e5st eller har l\u00e5ste underordnede noder.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Sie k\u00f6nnen keine El
|
||||
rm.action.create.transfer.child-error-message=Sie k\u00f6nnen keine Elemente in \u00dcbertragungsordnern erstellen.
|
||||
rm.action.create.record.folder.child-error-message=In Record-Ordnern k\u00f6nnen Sie nur Records erstellen. Das war aber ein {0}.
|
||||
rm.action.transfer-non-editable=Sie k\u00f6nnen Metadaten von \u00dcbertragungsordnern oder -containern nicht bearbeiten.
|
||||
|
||||
rm.action.node.frozen.error-message=Die Aktion ''{0}'' kann nicht ausgef\u00fchrt werden, da der Knoten oder untergeordnete Elemente von ihm festgefahren ist bzw. sind.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=No se pueden crear eleme
|
||||
rm.action.create.transfer.child-error-message=No se pueden crear elementos en las carpetas de transferencia.
|
||||
rm.action.create.record.folder.child-error-message=Solo puede crear documentos de archivo en carpetas de documentos de archivo. {0} no se puede crear aqu\u00ed.
|
||||
rm.action.transfer-non-editable=No se puede editar una carpeta de transferencia ni los metadatos de un contenedor.
|
||||
|
||||
rm.action.node.frozen.error-message=No se puede realizar la acci\u00f3n {0} porque el nodo est\u00e1 congelado o tiene elementos secundarios congelados.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Siirtos\u00e4ili\u00f6\u
|
||||
rm.action.create.transfer.child-error-message=Siirtokansioihin ei voi luoda kohteita.
|
||||
rm.action.create.record.folder.child-error-message=Tietuekansioihin voi luoda ainoastaan tietueita, mutta t\u00e4m\u00e4 oli {0}.
|
||||
rm.action.transfer-non-editable=Siirtokansion tai -s\u00e4ili\u00f6n metatietoja ei voi muokata.
|
||||
|
||||
rm.action.node.frozen.error-message=Toimintoa {0} ei voitu suorittaa, koska solmu on j\u00e4\u00e4dytetty tai sill\u00e4 on j\u00e4\u00e4dytettyj\u00e4 alatasoja.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Impossible de cr\u00e9er
|
||||
rm.action.create.transfer.child-error-message=Impossible de cr\u00e9er des \u00e9l\u00e9ments dans les dossiers de transfert.
|
||||
rm.action.create.record.folder.child-error-message=Vous ne pouvez cr\u00e9er des documents d''archives que dans les dossiers d''archives, dans le cas pr\u00e9sent {0}.
|
||||
rm.action.transfer-non-editable=Impossible de modifier les m\u00e9tadonn\u00e9es de dossier de transfert ou de contenant.
|
||||
|
||||
rm.action.node.frozen.error-message=Impossible d''effectuer l''action {0} car le n\u0153ud ou ses enfants sont gel\u00e9s.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Impossibile creare eleme
|
||||
rm.action.create.transfer.child-error-message=Impossibile creare elementi nelle cartelle Trasferimento.
|
||||
rm.action.create.record.folder.child-error-message=I record possono essere creati solo nelle cartelle dei record e questa era {0}.
|
||||
rm.action.transfer-non-editable=Impossibile modificare la cartella di trasferimento o i metadati dei contenitori.
|
||||
|
||||
rm.action.node.frozen.error-message=Impossibile eseguire l''azione {0} poich\u00e9 il nodo \u00e8 congelato o presenta nodi figlio congelati.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=\u8ee2\u9001\u30b3\u30f3
|
||||
rm.action.create.transfer.child-error-message=\u8ee2\u9001\u30d5\u30a9\u30eb\u30c0\u5185\u3067\u306f\u30a2\u30a4\u30c6\u30e0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002
|
||||
rm.action.create.record.folder.child-error-message=\u30ec\u30b3\u30fc\u30c9\u3092\u4f5c\u6210\u3067\u304d\u308b\u306e\u306f\u30ec\u30b3\u30fc\u30c9\u30d5\u30a9\u30eb\u30c0\u5185\u306e\u307f\u3067\u3001\u3053\u308c\u306f {0} \u3067\u3059\u3002
|
||||
rm.action.transfer-non-editable=\u8ee2\u9001\u30d5\u30a9\u30eb\u30c0\u307e\u305f\u306f\u30b3\u30f3\u30c6\u30ca\u30e1\u30bf\u30c7\u30fc\u30bf\u306f\u7de8\u96c6\u3067\u304d\u307e\u305b\u3093\u3002
|
||||
|
||||
rm.action.node.frozen.error-message=\u30ce\u30fc\u30c9\u304c\u30d5\u30ea\u30fc\u30ba\u3057\u3066\u3044\u308b\u304b\u3001\u307e\u305f\u306f\u5b50\u304c\u51cd\u7d50\u3057\u3066\u3044\u308b\u305f\u3081\u3001\u30a2\u30af\u30b7\u30e7\u30f3 {0}\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Elementer kan ikke oppre
|
||||
rm.action.create.transfer.child-error-message=Elementer kan ikke opprettes i overf\u00f8ringsmapper.
|
||||
rm.action.create.record.folder.child-error-message=Oppf\u00f8ringer kan bare opprettes i oppf\u00f8ringsmapper, og dette er en {0}.
|
||||
rm.action.transfer-non-editable=Overf\u00f8ringsmapper eller beholdermetadata kan ikke redigeres.
|
||||
|
||||
rm.action.node.frozen.error-message=Kan ikke utf\u00f8re handlingen {0} fordi noden er frossen eller har frosne underordnede elementer.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=U kunt geen onderdelen m
|
||||
rm.action.create.transfer.child-error-message=U kunt geen onderdelen maken in overdrachtsmappen.
|
||||
rm.action.create.record.folder.child-error-message=U kunt alleen archiefstukken maken in archiefmappen en dit was een {0}.
|
||||
rm.action.transfer-non-editable=U kunt metagegevens in een overdrachtsmap of -container niet bewerken.
|
||||
|
||||
rm.action.node.frozen.error-message=Kan de actie {0} niet uitvoeren omdat de node geblokkeerd is of geblokkeerde onderliggende elementen heeft.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Nie mo\u017cna utworzy\u
|
||||
rm.action.create.transfer.child-error-message=Nie mo\u017cna utworzy\u0107 pozycji w folderach przesy\u0142ania.
|
||||
rm.action.create.record.folder.child-error-message=W folderach rekord\u00f3w mo\u017cna tworzy\u0107 tylko rekordy, a to by\u0142o {0}.
|
||||
rm.action.transfer-non-editable=Nie mo\u017cna edytowa\u0107 folderu przesy\u0142ania ani metadanych kontenera.
|
||||
|
||||
rm.action.node.frozen.error-message=Nie mo\u017cna wykona\u0107 czynno\u015bci {0}, poniewa\u017c w\u0119ze\u0142 jest zablokowany lub ma zablokowane elementy podrz\u0119dne.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=N\u00e3o \u00e9 poss\u00
|
||||
rm.action.create.transfer.child-error-message=N\u00e3o \u00e9 poss\u00edvel criar itens nas pastas de Transfer\u00eancia.
|
||||
rm.action.create.record.folder.child-error-message=\u00c9 poss\u00edvel apenas criar documentos arquiv\u00edsticos em pastas de documentos arquiv\u00edsticos; esta foi {0}.
|
||||
rm.action.transfer-non-editable=N\u00e3o \u00e9 poss\u00edvel editar os metadados das pastas de transfer\u00eancia ou cont\u00eainer.
|
||||
|
||||
rm.action.node.frozen.error-message=N\u00e3o \u00e9 poss\u00edvel executar a a\u00e7\u00e3o {0} porque o n\u00f3 est\u00e1 congelado ou tem filhos congelados.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=\u041d\u0435\u0432\u043e
|
||||
rm.action.create.transfer.child-error-message=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043f\u0430\u043f\u043a\u0430\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438.
|
||||
rm.action.create.record.folder.child-error-message=\u0417\u0430\u043f\u0438\u0441\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043f\u0430\u043f\u043a\u0430\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439, \u0430 \u044d\u0442\u043e {0}.
|
||||
rm.action.transfer-non-editable=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0438\u043b\u0438 \u043f\u0430\u043f\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438.
|
||||
|
||||
rm.action.node.frozen.error-message=\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 {0}, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443\u0437\u0435\u043b \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d \u0438\u043b\u0438 \u0438\u043c\u0435\u0435\u0442 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=Du kan inte skapa objekt
|
||||
rm.action.create.transfer.child-error-message=Du kan inte skapa objekt i \u00d6verf\u00f6ringsmappar.
|
||||
rm.action.create.record.folder.child-error-message=Du kan endast skapa handlingar i handlingsmappar och detta var en {0}.
|
||||
rm.action.transfer-non-editable=Du kan inte redigera \u00f6verf\u00f6ringsmappen eller beh\u00e5llarens metadata.
|
||||
|
||||
rm.action.node.frozen.error-message=Det gick inte att utf\u00f6ra \u00e5tg\u00e4rd {0} eftersom noden \u00e4r frusen eller har frysta underordnade.
|
||||
|
@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=\u60a8\u65e0\u6cd5\u5728
|
||||
rm.action.create.transfer.child-error-message=\u60a8\u65e0\u6cd5\u5728 Transfer \u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u9879\u76ee\u3002
|
||||
rm.action.create.record.folder.child-error-message=\u60a8\u53ea\u80fd\u5728\u8bb0\u5f55\u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u8bb0\u5f55\uff0c\u4e14\u8fd9\u662f\u4e00\u4e2a {0}\u3002
|
||||
rm.action.transfer-non-editable=\u60a8\u65e0\u6cd5\u7f16\u8f91\u4f20\u8f93\u6587\u4ef6\u5939\u6216\u5bb9\u5668\u5143\u6570\u636e\u3002
|
||||
|
||||
rm.action.node.frozen.error-message=\u65e0\u6cd5\u6267\u884c\u64cd\u4f5c{0}\uff0c\u56e0\u4e3a\u8282\u70b9\u5df2\u51bb\u7ed3\u6216\u51bb\u7ed3\u7684\u5b50\u8282\u70b9\u3002
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -306,7 +306,7 @@ public class RMAfterInvocationProvider extends RMSecurityCommon
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUnfiltered(NodeRef nodeRef)
|
||||
protected boolean isUnfiltered(NodeRef nodeRef)
|
||||
{
|
||||
return !nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT);
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Fetch image based on Tomcat 9.0, Java 11 and Centos 8
|
||||
# More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat
|
||||
FROM alfresco/alfresco-base-tomcat:9.0.45-java-11-centos-8
|
||||
FROM alfresco/alfresco-base-tomcat:9.0.52-java-11-centos-7
|
||||
|
||||
# Set default docker_context.
|
||||
ARG resource_path=target
|
||||
@@ -65,12 +65,12 @@ RUN sed -i -e "s_log4j.appender.File.File\=alfresco.log_log4j.appender.File.File
|
||||
|
||||
# fontconfig is required by Activiti worflow diagram generator
|
||||
# installing pinned dependencies as well
|
||||
RUN yum install -y fontconfig-2.13.1-3.el8 \
|
||||
dejavu-fonts-common-2.35-7.el8 \
|
||||
fontpackages-filesystem-1.44-22.el8 \
|
||||
freetype-2.9.1-4.el8_3.1 \
|
||||
libpng-1.6.34-5.el8 \
|
||||
dejavu-sans-fonts-2.35-7.el8 && \
|
||||
RUN yum install -y fontconfig-2.13.0-4.3.el7 \
|
||||
dejavu-fonts-common-2.33-6.el7 \
|
||||
fontpackages-filesystem-1.44-8.el7 \
|
||||
freetype-2.8-14.el7_9.1 \
|
||||
libpng-1.5.13-8.el7 \
|
||||
dejavu-sans-fonts-2.33-6.el7 && \
|
||||
yum clean all
|
||||
|
||||
# The standard configuration is to have all Tomcat files owned by root with group GROUPNAME and whilst owner has read/write privileges,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
14
pom.xml
14
pom.xml
@@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<properties>
|
||||
<acs.version.major>7</acs.version.major>
|
||||
<acs.version.minor>1</acs.version.minor>
|
||||
<acs.version.revision>0</acs.version.revision>
|
||||
<acs.version.revision>1</acs.version.revision>
|
||||
<acs.version.label />
|
||||
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
||||
|
||||
@@ -61,13 +61,13 @@
|
||||
<dependency.jackson-databind.version>2.12.4</dependency.jackson-databind.version>
|
||||
<dependency.cxf.version>3.4.4</dependency.cxf.version>
|
||||
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
|
||||
<dependency.webscripts.version>8.22</dependency.webscripts.version>
|
||||
<dependency.webscripts.version>8.25</dependency.webscripts.version>
|
||||
<dependency.bouncycastle.version>1.69</dependency.bouncycastle.version>
|
||||
<dependency.mockito-core.version>3.11.2</dependency.mockito-core.version>
|
||||
<dependency.mockito-all.version>1.10.19</dependency.mockito-all.version>
|
||||
<dependency.org-json.version>20210307</dependency.org-json.version>
|
||||
<dependency.commons-dbcp.version>1.4-DBCP330</dependency.commons-dbcp.version>
|
||||
<dependency.commons-io.version>2.8.0</dependency.commons-io.version>
|
||||
<dependency.commons-io.version>2.11.0</dependency.commons-io.version>
|
||||
<dependency.gson.version>2.8.5</dependency.gson.version>
|
||||
<dependency.httpclient.version>4.5.13</dependency.httpclient.version>
|
||||
<dependency.httpcore.version>4.4.14</dependency.httpcore.version>
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
<alfresco.googledrive.version>3.2.1.3</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>1.4.0.1</alfresco.aos-module.version>
|
||||
<alfresco.api-explorer.version>7.1.0-A1</alfresco.api-explorer.version>
|
||||
<alfresco.api-explorer.version>7.1.0.1</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
||||
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
||||
|
||||
<dependency.postgresql.version>42.2.20</dependency.postgresql.version>
|
||||
@@ -114,7 +114,7 @@
|
||||
<dependency.mariadb.version>2.7.2</dependency.mariadb.version>
|
||||
<dependency.tas-utility.version>3.0.45</dependency.tas-utility.version>
|
||||
<dependency.rest-assured.version>3.3.0</dependency.rest-assured.version>
|
||||
<dependency.tas-restapi.version>1.63</dependency.tas-restapi.version>
|
||||
<dependency.tas-restapi.version>1.64</dependency.tas-restapi.version>
|
||||
<dependency.tas-cmis.version>1.30</dependency.tas-cmis.version>
|
||||
<dependency.tas-email.version>1.8</dependency.tas-email.version>
|
||||
<dependency.tas-webdav.version>1.6</dependency.tas-webdav.version>
|
||||
@@ -142,7 +142,7 @@
|
||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||
<tag>11.128</tag>
|
||||
<tag>12.7</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -30,6 +30,7 @@ import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -355,7 +356,10 @@ public class RepositoryContainer extends AbstractRuntimeContainer
|
||||
return;
|
||||
}
|
||||
|
||||
if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest)
|
||||
// if the required authentication is not equal to guest, then it should be one of the following:
|
||||
// user | sysadmin | admin (the 'none' authentication is handled above)
|
||||
// in this case the guest user should not be able to execute those scripts.
|
||||
if (required != RequiredAuthentication.guest && isGuest)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access.");
|
||||
}
|
||||
@@ -383,28 +387,9 @@ public class RepositoryContainer extends AbstractRuntimeContainer
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// The user will now have been authenticated, based on HTTP Auth, Ticket etc
|
||||
// The user will now have been authenticated, based on HTTP Auth, Ticket, etc.
|
||||
// Check that the user they authenticated as has appropriate access to the script
|
||||
|
||||
// Check to see if they supplied HTTP Auth or Ticket as guest, on a script that needs more
|
||||
if (required == RequiredAuthentication.user || required == RequiredAuthentication.admin)
|
||||
{
|
||||
final String authenticatedUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
final String runAsUser = AuthenticationUtil.getRunAsUser();
|
||||
|
||||
if ( (authenticatedUser == null) ||
|
||||
(authenticatedUser.equals(runAsUser) && authorityService.hasGuestAuthority()) ||
|
||||
(!authenticatedUser.equals(runAsUser) && authorityService.isGuestAuthority(authenticatedUser)) )
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access.");
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if they're admin or system on an Admin only script
|
||||
if (required == RequiredAuthentication.admin && !(authorityService.hasAdminAuthority() || AuthenticationUtil.getFullyAuthenticatedUser().equals(AuthenticationUtil.getSystemUserName())))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access.");
|
||||
}
|
||||
checkScriptAccess(required, desc.getId());
|
||||
|
||||
if (debug)
|
||||
{
|
||||
@@ -424,7 +409,7 @@ public class RepositoryContainer extends AbstractRuntimeContainer
|
||||
|
||||
// Execute Web Script if authentication passed
|
||||
// The Web Script has its own txn management with potential runAs() user
|
||||
transactionedExecuteAs(script, scriptReq, scriptRes);
|
||||
transactionedExecuteAs(script, scriptReq, scriptRes, required);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -441,6 +426,65 @@ public class RepositoryContainer extends AbstractRuntimeContainer
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSystemUser()
|
||||
{
|
||||
return Objects.equals(AuthenticationUtil.getFullyAuthenticatedUser(), AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
private boolean isSysAdminUser()
|
||||
{
|
||||
return authorityService.hasSysAdminAuthority();
|
||||
}
|
||||
|
||||
private boolean isAdmin()
|
||||
{
|
||||
return authorityService.hasAdminAuthority();
|
||||
}
|
||||
|
||||
public final boolean isAdminOrSystemUser()
|
||||
{
|
||||
return isAdmin() || isSystemUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if they supplied HTTP Auth or Ticket as guest, on a script that needs more
|
||||
*/
|
||||
private void checkGuestAccess(RequiredAuthentication required, String scriptDescriptorId)
|
||||
{
|
||||
if (required == RequiredAuthentication.user || required == RequiredAuthentication.admin
|
||||
|| required == RequiredAuthentication.sysadmin)
|
||||
{
|
||||
final String authenticatedUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
final String runAsUser = AuthenticationUtil.getRunAsUser();
|
||||
|
||||
if ((authenticatedUser == null) || (authenticatedUser.equals(runAsUser)
|
||||
&& authorityService.hasGuestAuthority()) || (!authenticatedUser.equals(runAsUser)
|
||||
&& authorityService.isGuestAuthority(authenticatedUser)))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + scriptDescriptorId
|
||||
+ " requires user authentication; however, a guest has attempted access.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkScriptAccess(RequiredAuthentication required, String scriptDescriptorId)
|
||||
{
|
||||
// first, check guest access
|
||||
checkGuestAccess(required, scriptDescriptorId);
|
||||
|
||||
// Check to see if the user is sysAdmin, admin or system on a sysadmin scripts
|
||||
if (required == RequiredAuthentication.sysadmin && !(isSysAdminUser() || isAdminOrSystemUser()))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + scriptDescriptorId
|
||||
+ " requires system-admin authentication; however, a non-system-admin has attempted access.");
|
||||
}
|
||||
else if (required == RequiredAuthentication.admin && !isAdminOrSystemUser())
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + scriptDescriptorId
|
||||
+ " requires admin authentication; however, a non-admin has attempted access.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script within required level of transaction
|
||||
*
|
||||
@@ -626,6 +670,35 @@ public class RepositoryContainer extends AbstractRuntimeContainer
|
||||
}, runAs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script within required level of transaction as required effective user.
|
||||
*
|
||||
* @param script WebScript
|
||||
* @param scriptReq WebScriptRequest
|
||||
* @param scriptRes WebScriptResponse
|
||||
* @param requiredAuthentication Required authentication
|
||||
* @throws IOException
|
||||
*/
|
||||
private void transactionedExecuteAs(final WebScript script, final WebScriptRequest scriptReq,
|
||||
final WebScriptResponse scriptRes, RequiredAuthentication requiredAuthentication) throws IOException
|
||||
{
|
||||
// Execute as System if and only if, the current user is a member of System-Admin group, and he is not a super admin.
|
||||
// E.g. if 'jdoe' is a member of ALFRESCO_SYSTEM_ADMINISTRATORS group, then the work should be executed as System to satisfy the ACL checks.
|
||||
// But, if the current user is Admin (i.e. super admin, which by default he is a member fo the ALFRESCO_SYSTEM_ADMINISTRATORS group)
|
||||
// then don't wrap the work as RunAs, since he can do anything!
|
||||
if (requiredAuthentication == RequiredAuthentication.sysadmin && isSysAdminUser() && !isAdmin())
|
||||
{
|
||||
AuthenticationUtil.runAs(() -> {
|
||||
transactionedExecute(script, scriptReq, scriptRes);
|
||||
return null;
|
||||
}, AuthenticationUtil.SYSTEM_USER_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
transactionedExecuteAs(script, scriptReq, scriptRes);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
|
@@ -30,8 +30,19 @@ import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
import org.alfresco.repo.bulkimport.BulkFilesystemImporter;
|
||||
import org.alfresco.repo.bulkimport.BulkImportParameters;
|
||||
import org.alfresco.repo.bulkimport.NodeImporter;
|
||||
import org.alfresco.repo.bulkimport.impl.MultiThreadedBulkFilesystemImporter;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
@@ -39,8 +50,12 @@ import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* contains common fields and methods for the import web scripts.
|
||||
@@ -60,10 +75,10 @@ public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript
|
||||
// Web scripts parameters (common)
|
||||
protected static final String PARAMETER_REPLACE_EXISTING = "replaceExisting";
|
||||
protected static final String PARAMETER_EXISTING_FILE_MODE = "existingFileMode";
|
||||
protected static final String PARAMETER_VALUE_REPLACE_EXISTING = "replaceExisting";
|
||||
protected static final String PARAMETER_VALUE_REPLACE_EXISTING = "true";
|
||||
protected static final String PARAMETER_SOURCE_DIRECTORY = "sourceDirectory";
|
||||
protected static final String PARAMETER_DISABLE_RULES = "disableRules";
|
||||
protected static final String PARAMETER_VALUE_DISABLE_RULES = "disableRules";
|
||||
protected static final String PARAMETER_VALUE_DISABLE_RULES = "true";
|
||||
|
||||
protected static final String IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY = "importInProgress";
|
||||
protected static final String IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY ="bfsit.error.importAlreadyInProgress";
|
||||
@@ -75,7 +90,7 @@ public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript
|
||||
protected Repository repository;
|
||||
|
||||
protected volatile boolean importInProgress;
|
||||
|
||||
|
||||
protected NodeRef getTargetNodeRef(String targetNodeRefStr, String targetPath) throws FileNotFoundException
|
||||
{
|
||||
NodeRef targetNodeRef;
|
||||
@@ -219,4 +234,198 @@ public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
protected class MultithreadedImportWebScriptLogic
|
||||
{
|
||||
private final MultiThreadedBulkFilesystemImporter bulkImporter;
|
||||
private final Supplier<NodeImporter> nodeImporterFactory;
|
||||
private final WebScriptRequest request;
|
||||
private final Status status;
|
||||
private final Cache cache;
|
||||
|
||||
public MultithreadedImportWebScriptLogic(MultiThreadedBulkFilesystemImporter bulkImporter, Supplier<NodeImporter> nodeImporterFactory, WebScriptRequest request, Status status, Cache cache)
|
||||
{
|
||||
this.bulkImporter = Objects.requireNonNull(bulkImporter);
|
||||
this.nodeImporterFactory = Objects.requireNonNull(nodeImporterFactory);
|
||||
this.request = Objects.requireNonNull(request);
|
||||
this.status = Objects.requireNonNull(status);
|
||||
this.cache = Objects.requireNonNull(cache);
|
||||
}
|
||||
|
||||
public Map<String, Object> executeImport()
|
||||
{
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
cache.setNeverCache(true);
|
||||
String targetPath = null;
|
||||
|
||||
try
|
||||
{
|
||||
targetPath = request.getParameter(PARAMETER_TARGET_PATH);
|
||||
if (isRunning())
|
||||
{
|
||||
model.put(IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY, I18NUtil.getMessage(IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY));
|
||||
return model;
|
||||
}
|
||||
|
||||
final BulkImportParameters bulkImportParameters = getBulkImportParameters();
|
||||
final NodeImporter nodeImporter = nodeImporterFactory.get();
|
||||
|
||||
bulkImporter.asyncBulkImport(bulkImportParameters, nodeImporter);
|
||||
|
||||
waitForImportToBegin();
|
||||
|
||||
// redirect to the status Web Script
|
||||
status.setCode(Status.STATUS_MOVED_TEMPORARILY);
|
||||
status.setRedirect(true);
|
||||
status.setLocation(request.getServiceContextPath() + WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS);
|
||||
}
|
||||
catch (WebScriptException | IllegalArgumentException e)
|
||||
{
|
||||
status.setCode(Status.STATUS_BAD_REQUEST, e.getMessage());
|
||||
status.setRedirect(true);
|
||||
}
|
||||
catch (FileNotFoundException fnfe)
|
||||
{
|
||||
status.setCode(Status.STATUS_BAD_REQUEST,"The repository path '" + targetPath + "' does not exist !");
|
||||
status.setRedirect(true);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, buildTextMessage(t), t);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private void waitForImportToBegin() throws InterruptedException
|
||||
{
|
||||
// ACE-3047 fix, since bulk import is started asynchronously there is a chance that client
|
||||
// will get into the status page before import is actually started.
|
||||
// In this case wrong information (for previous import) will be displayed.
|
||||
// So lets ensure that import started before redirecting client to status page.
|
||||
int i = 0;
|
||||
while (!bulkImporter.getStatus().inProgress() && i < 10)
|
||||
{
|
||||
Thread.sleep(100);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private BulkImportParameters getBulkImportParameters() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = new BulkImportParametersExtractor(request::getParameter,
|
||||
AbstractBulkFileSystemImportWebScript.this::getTargetNodeRef,
|
||||
bulkImporter.getDefaultBatchSize(),
|
||||
bulkImporter.getDefaultNumThreads());
|
||||
return extractor.extract();
|
||||
}
|
||||
|
||||
private boolean isRunning()
|
||||
{
|
||||
return bulkImporter.getStatus().inProgress();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class BulkImportParametersExtractor
|
||||
{
|
||||
private final Function<String, String> paramsProvider;
|
||||
private final NodeRefCreator nodeRefCreator;
|
||||
private final int defaultBatchSize;
|
||||
private final int defaultNumThreads;
|
||||
|
||||
public BulkImportParametersExtractor(final Function<String, String> paramsProvider, final NodeRefCreator nodeRefCreator,
|
||||
final int defaultBatchSize, final int defaultNumThreads)
|
||||
{
|
||||
this.paramsProvider = Objects.requireNonNull(paramsProvider);
|
||||
this.nodeRefCreator = Objects.requireNonNull(nodeRefCreator);
|
||||
this.defaultBatchSize = defaultBatchSize;
|
||||
this.defaultNumThreads = defaultNumThreads;
|
||||
}
|
||||
|
||||
public BulkImportParameters extract() throws FileNotFoundException
|
||||
{
|
||||
BulkImportParameters result = new BulkImportParameters();
|
||||
|
||||
result.setTarget(getTargetNodeRef());
|
||||
setExistingFileMode(result);
|
||||
result.setNumThreads(getOptionalPositiveInteger(PARAMETER_NUM_THREADS).orElse(defaultNumThreads));
|
||||
result.setBatchSize(getOptionalPositiveInteger(PARAMETER_BATCH_SIZE).orElse(defaultBatchSize));
|
||||
setDisableRules(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setExistingFileMode(BulkImportParameters params)
|
||||
{
|
||||
String replaceExistingStr = getParamStringValue(PARAMETER_REPLACE_EXISTING);
|
||||
String existingFileModeStr = getParamStringValue(PARAMETER_EXISTING_FILE_MODE);
|
||||
|
||||
if (!isNullOrEmpty(replaceExistingStr) && !isNullOrEmpty(existingFileModeStr))
|
||||
{
|
||||
// Check that we haven't had both the deprecated and new (existingFileMode)
|
||||
// parameters supplied.
|
||||
throw new IllegalStateException(
|
||||
String.format("Only one of these parameters may be used, not both: %s, %s",
|
||||
PARAMETER_REPLACE_EXISTING,
|
||||
PARAMETER_EXISTING_FILE_MODE));
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(existingFileModeStr))
|
||||
{
|
||||
params.setExistingFileMode(BulkImportParameters.ExistingFileMode.valueOf(existingFileModeStr));
|
||||
}
|
||||
else
|
||||
{
|
||||
params.setReplaceExisting(PARAMETER_VALUE_REPLACE_EXISTING.equals(replaceExistingStr));
|
||||
}
|
||||
}
|
||||
|
||||
private void setDisableRules(final BulkImportParameters params)
|
||||
{
|
||||
final String disableRulesStr = getParamStringValue(PARAMETER_DISABLE_RULES);
|
||||
params.setDisableRulesService(!isNullOrEmpty(disableRulesStr) && PARAMETER_VALUE_DISABLE_RULES.equals(disableRulesStr));
|
||||
}
|
||||
|
||||
private NodeRef getTargetNodeRef() throws FileNotFoundException
|
||||
{
|
||||
String targetNodeRefStr = getParamStringValue(PARAMETER_TARGET_NODEREF);
|
||||
String targetPath = getParamStringValue(PARAMETER_TARGET_PATH);
|
||||
return nodeRefCreator.fromNodeRefAndPath(targetNodeRefStr, targetPath);
|
||||
}
|
||||
|
||||
private OptionalInt getOptionalPositiveInteger(final String paramName)
|
||||
{
|
||||
final String strValue = getParamStringValue(paramName);
|
||||
if (isNullOrEmpty(strValue))
|
||||
{
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
|
||||
final Integer asInt = Ints.tryParse(strValue);
|
||||
if (asInt == null || asInt < 1)
|
||||
{
|
||||
throw new WebScriptException("Error: parameter '" + paramName + "' must be an integer > 0.");
|
||||
}
|
||||
|
||||
return OptionalInt.of(asInt);
|
||||
}
|
||||
|
||||
private String getParamStringValue(String paramName)
|
||||
{
|
||||
Objects.requireNonNull(paramName);
|
||||
|
||||
return paramsProvider.apply(paramName);
|
||||
}
|
||||
|
||||
private boolean isNullOrEmpty(String str)
|
||||
{
|
||||
return str == null || str.trim().length() == 0;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
protected interface NodeRefCreator
|
||||
{
|
||||
NodeRef fromNodeRefAndPath(String nodeRef, String path) throws FileNotFoundException;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -27,17 +27,12 @@
|
||||
package org.alfresco.repo.web.scripts.bulkimport.copy;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.bulkimport.BulkImportParameters;
|
||||
import org.alfresco.repo.bulkimport.NodeImporter;
|
||||
import org.alfresco.repo.bulkimport.impl.MultiThreadedBulkFilesystemImporter;
|
||||
import org.alfresco.repo.bulkimport.impl.StreamingNodeImporterFactory;
|
||||
import org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
@@ -69,170 +64,22 @@ public class BulkFilesystemImportWebScript extends AbstractBulkFileSystemImportW
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(final WebScriptRequest request, final Status status, final Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
String targetNodeRefStr = null;
|
||||
String targetPath = null;
|
||||
String sourceDirectoryStr = null;
|
||||
@Deprecated String replaceExistingStr = null;
|
||||
String existingFileModeStr = null;
|
||||
String batchSizeStr = null;
|
||||
String numThreadsStr = null;
|
||||
String disableRulesStr = null;
|
||||
final MultithreadedImportWebScriptLogic importLogic = new MultithreadedImportWebScriptLogic(bulkImporter,
|
||||
() -> createNodeImporter(request), request, status, cache);
|
||||
return importLogic.executeImport();
|
||||
}
|
||||
|
||||
cache.setNeverCache(true);
|
||||
|
||||
try
|
||||
private NodeImporter createNodeImporter(WebScriptRequest request)
|
||||
{
|
||||
final String sourceDirectoryStr = request.getParameter(PARAMETER_SOURCE_DIRECTORY);
|
||||
if (sourceDirectoryStr == null || sourceDirectoryStr.trim().length() == 0)
|
||||
{
|
||||
if(!bulkImporter.getStatus().inProgress())
|
||||
{
|
||||
NodeRef targetNodeRef = null;
|
||||
File sourceDirectory = null;
|
||||
boolean replaceExisting = false;
|
||||
BulkImportParameters.ExistingFileMode existingFileMode = null;
|
||||
int batchSize = bulkImporter.getDefaultBatchSize();
|
||||
int numThreads = bulkImporter.getDefaultNumThreads();
|
||||
boolean disableRules = false;
|
||||
|
||||
// Retrieve, validate and convert parameters
|
||||
targetNodeRefStr = request.getParameter(PARAMETER_TARGET_NODEREF);
|
||||
targetPath = request.getParameter(PARAMETER_TARGET_PATH);
|
||||
sourceDirectoryStr = request.getParameter(PARAMETER_SOURCE_DIRECTORY);
|
||||
replaceExistingStr = request.getParameter(PARAMETER_REPLACE_EXISTING);
|
||||
existingFileModeStr = request.getParameter(PARAMETER_EXISTING_FILE_MODE);
|
||||
|
||||
batchSizeStr = request.getParameter(PARAMETER_BATCH_SIZE);
|
||||
numThreadsStr = request.getParameter(PARAMETER_NUM_THREADS);
|
||||
disableRulesStr = request.getParameter(PARAMETER_DISABLE_RULES);
|
||||
|
||||
targetNodeRef = getTargetNodeRef(targetNodeRefStr, targetPath);
|
||||
|
||||
if (sourceDirectoryStr == null || sourceDirectoryStr.trim().length() == 0)
|
||||
{
|
||||
throw new RuntimeException("Error: mandatory parameter '" + PARAMETER_SOURCE_DIRECTORY + "' was not provided.");
|
||||
}
|
||||
|
||||
sourceDirectory = new File(sourceDirectoryStr.trim());
|
||||
|
||||
if (replaceExistingStr != null && existingFileModeStr != null)
|
||||
{
|
||||
// Check that we haven't had both the deprecated and new (existingFileMode)
|
||||
// parameters supplied.
|
||||
throw new IllegalStateException(
|
||||
String.format("Only one of these parameters may be used, not both: %s, %s",
|
||||
PARAMETER_REPLACE_EXISTING,
|
||||
PARAMETER_EXISTING_FILE_MODE));
|
||||
}
|
||||
|
||||
if (replaceExistingStr != null && replaceExistingStr.trim().length() > 0)
|
||||
{
|
||||
replaceExisting = PARAMETER_VALUE_REPLACE_EXISTING.equals(replaceExistingStr);
|
||||
}
|
||||
|
||||
if (existingFileModeStr != null && existingFileModeStr.trim().length() > 0)
|
||||
{
|
||||
existingFileMode = BulkImportParameters.ExistingFileMode.valueOf(existingFileModeStr);
|
||||
}
|
||||
|
||||
if (disableRulesStr != null && disableRulesStr.trim().length() > 0)
|
||||
{
|
||||
disableRules = PARAMETER_VALUE_DISABLE_RULES.equals(disableRulesStr);
|
||||
}
|
||||
|
||||
// Initiate the import
|
||||
NodeImporter nodeImporter = nodeImporterFactory.getNodeImporter(sourceDirectory);
|
||||
BulkImportParameters bulkImportParameters = new BulkImportParameters();
|
||||
|
||||
if (numThreadsStr != null && numThreadsStr.trim().length() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
numThreads = Integer.parseInt(numThreadsStr);
|
||||
if(numThreads < 1)
|
||||
{
|
||||
throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0.");
|
||||
}
|
||||
bulkImportParameters.setNumThreads(numThreads);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0.");
|
||||
}
|
||||
}
|
||||
|
||||
if (batchSizeStr != null && batchSizeStr.trim().length() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
batchSize = Integer.parseInt(batchSizeStr);
|
||||
if(batchSize < 1)
|
||||
{
|
||||
throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0.");
|
||||
}
|
||||
bulkImportParameters.setBatchSize(batchSize);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0.");
|
||||
}
|
||||
}
|
||||
|
||||
if (existingFileMode != null)
|
||||
{
|
||||
bulkImportParameters.setExistingFileMode(existingFileMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fall back to the old/deprecated way.
|
||||
bulkImportParameters.setReplaceExisting(replaceExisting);
|
||||
}
|
||||
|
||||
bulkImportParameters.setTarget(targetNodeRef);
|
||||
bulkImportParameters.setDisableRulesService(disableRules);
|
||||
|
||||
bulkImporter.asyncBulkImport(bulkImportParameters, nodeImporter);
|
||||
|
||||
// ACE-3047 fix, since bulk import is started asynchronously there is a chance that client
|
||||
// will get into the status page before import is actually started.
|
||||
// In this case wrong information (for previous import) will be displayed.
|
||||
// So lets ensure that import started before redirecting client to status page.
|
||||
int i = 0;
|
||||
while (!bulkImporter.getStatus().inProgress() && i < 10)
|
||||
{
|
||||
Thread.sleep(100);
|
||||
i++;
|
||||
}
|
||||
|
||||
// redirect to the status Web Script
|
||||
status.setCode(Status.STATUS_MOVED_TEMPORARILY);
|
||||
status.setRedirect(true);
|
||||
status.setLocation(request.getServiceContextPath() + WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS);
|
||||
}
|
||||
else
|
||||
{
|
||||
model.put(IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY, I18NUtil.getMessage(IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY));
|
||||
}
|
||||
throw new WebScriptException("Error: mandatory parameter '" + PARAMETER_SOURCE_DIRECTORY + "' was not provided.");
|
||||
}
|
||||
catch (WebScriptException wse)
|
||||
{
|
||||
status.setCode(Status.STATUS_BAD_REQUEST, wse.getMessage());
|
||||
status.setRedirect(true);
|
||||
}
|
||||
catch (FileNotFoundException fnfe)
|
||||
{
|
||||
status.setCode(Status.STATUS_BAD_REQUEST,"The repository path '" + targetPath + "' does not exist !");
|
||||
status.setRedirect(true);
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
status.setCode(Status.STATUS_BAD_REQUEST,iae.getMessage());
|
||||
status.setRedirect(true);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, buildTextMessage(t), t);
|
||||
}
|
||||
|
||||
return model;
|
||||
|
||||
final File sourceDirectory = new File(sourceDirectoryStr.trim());
|
||||
|
||||
return nodeImporterFactory.getNodeImporter(sourceDirectory);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.quickshare;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -31,10 +31,12 @@ import java.util.Map;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.model.QuickShareModel;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.service.cmr.quickshare.InvalidSharedIdException;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
@@ -82,14 +84,15 @@ public class UnshareContentDelete extends AbstractQuickShareContent
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
|
||||
Pair<String, NodeRef> pair = quickShareService.getTenantNodeRefFromSharedId(sharedId);
|
||||
String networkTenantDomain = pair.getFirst();
|
||||
|
||||
String sharedBy = (String) nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
|
||||
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedBy))
|
||||
TenantUtil.runAsSystemTenant(() ->
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Can't perform unshare action: " + sharedId);
|
||||
}
|
||||
quickShareService.unshareContent(sharedId);
|
||||
checkIfCanDeleteSharedLink(sharedId);
|
||||
quickShareService.unshareContent(sharedId);
|
||||
return null;
|
||||
}, networkTenantDomain);
|
||||
|
||||
Map<String, Object> model = new HashMap<>(1);
|
||||
model.put("success", Boolean.TRUE);
|
||||
@@ -106,4 +109,14 @@ public class UnshareContentDelete extends AbstractQuickShareContent
|
||||
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find: " + sharedId);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfCanDeleteSharedLink(String sharedId) {
|
||||
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
|
||||
|
||||
String sharedBy = (String) nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
|
||||
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedBy))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Can't perform unshare action: " + sharedId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -274,15 +274,15 @@ public class QuickShareLinksImpl implements QuickShareLinks, RecognizedParamsExt
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
|
||||
Pair<String, NodeRef> pair = quickShareService.getTenantNodeRefFromSharedId(sharedId);
|
||||
String networkTenantDomain = pair.getFirst();
|
||||
|
||||
String sharedByUserId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
|
||||
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedByUserId))
|
||||
TenantUtil.runAsSystemTenant(() ->
|
||||
{
|
||||
throw new PermissionDeniedException("Can't perform unshare action: " + sharedId);
|
||||
}
|
||||
|
||||
quickShareService.unshareContent(sharedId);
|
||||
checkIfCanDeleteSharedLink(sharedId);
|
||||
quickShareService.unshareContent(sharedId);
|
||||
return null;
|
||||
}, networkTenantDomain);
|
||||
}
|
||||
catch (InvalidSharedIdException ex)
|
||||
{
|
||||
@@ -698,4 +698,14 @@ public class QuickShareLinksImpl implements QuickShareLinks, RecognizedParamsExt
|
||||
throw new InvalidArgumentException("A valid recipientEmail must be specified.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfCanDeleteSharedLink(String sharedId) {
|
||||
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
|
||||
|
||||
String sharedByUserId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
|
||||
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedByUserId))
|
||||
{
|
||||
throw new PermissionDeniedException("Can't perform unshare action: " + sharedId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -63,6 +63,7 @@ public class RestApiDirectUrlConfig extends AbstractDirectUrlConfig
|
||||
logger.error("Disabling REST API direct access URLs due to configuration error: " + ex.getMessage());
|
||||
setEnabled(false);
|
||||
}
|
||||
logger.info("REST API direct access URLs are " + (isEnabled() ? "enabled" : "disabled"));
|
||||
}
|
||||
|
||||
/* Helper method to validate the REST API direct access url configuration settings */
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -35,6 +35,7 @@ import org.alfresco.repo.jscript.ScriptUtils;
|
||||
import org.alfresco.repo.web.scripts.RepositoryContainer;
|
||||
import org.alfresco.service.cmr.admin.RepoUsage;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
|
||||
import org.springframework.extensions.webscripts.WebScript;
|
||||
|
||||
/**
|
||||
@@ -65,27 +66,61 @@ public class WebScriptUtils extends ScriptUtils
|
||||
*/
|
||||
public Object[] findWebScripts(String family)
|
||||
{
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
|
||||
List<Object> values = new ArrayList<>();
|
||||
|
||||
for (WebScript webscript : this.repositoryContainer.getRegistry().getWebScripts())
|
||||
{
|
||||
if (family != null)
|
||||
addScriptDescription(family, values, webscript);
|
||||
}
|
||||
|
||||
return values.toArray(new Object[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for webscript components with the given family name accessible to the current user.
|
||||
*
|
||||
* @param family the family
|
||||
*
|
||||
* @return An array of webscripts that match the given family name accessible to the current user
|
||||
*
|
||||
* @since 7.1
|
||||
*/
|
||||
public Object[] findWebScriptsForCurrentUser(String family)
|
||||
{
|
||||
List<Object> values = new ArrayList<>();
|
||||
|
||||
final boolean isAdminOrSystemUser = repositoryContainer.isAdminOrSystemUser();
|
||||
for (WebScript webscript : this.repositoryContainer.getRegistry().getWebScripts())
|
||||
{
|
||||
final RequiredAuthentication required = webscript.getDescription().getRequiredAuthentication();
|
||||
// Ignore admin webscripts if the current user is not an Admin or System
|
||||
if (RequiredAuthentication.admin == required && !isAdminOrSystemUser)
|
||||
{
|
||||
Set<String> familys = webscript.getDescription().getFamilys();
|
||||
if (familys != null && familys.contains(family))
|
||||
{
|
||||
values.add(webscript.getDescription());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
addScriptDescription(family, values, webscript);
|
||||
}
|
||||
|
||||
return values.toArray(new Object[0]);
|
||||
}
|
||||
|
||||
private void addScriptDescription(String family, List<Object> values, WebScript webscript)
|
||||
{
|
||||
if (family != null)
|
||||
{
|
||||
Set<String> families = webscript.getDescription().getFamilys();
|
||||
if (families != null && families.contains(family))
|
||||
{
|
||||
values.add(webscript.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
return values.toArray(new Object[0]);
|
||||
else
|
||||
{
|
||||
values.add(webscript.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getHostAddress()
|
||||
{
|
||||
try
|
||||
|
@@ -1070,7 +1070,7 @@
|
||||
<property name="enabled" value="${system.api.discovery.enabled}" />
|
||||
<property name="thumbnailService" ref="ThumbnailService" />
|
||||
<property name="restApiDirectUrlConfig" ref="restApiDirectUrlConfig" />
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="contentService" ref="contentService" />
|
||||
</bean>
|
||||
|
||||
<bean id="org.alfresco.rest.api.probes.ProbeEntityResource.get" class="org.alfresco.rest.api.probes.ProbeEntityResource">
|
||||
|
@@ -40,7 +40,7 @@ var Admin = Admin || {};
|
||||
var toolInfo = {};
|
||||
|
||||
// collect the tools required for the Admin Console
|
||||
var tools = utils.findWebScripts("AdminConsole");
|
||||
var tools = utils.findWebScriptsForCurrentUser("AdminConsole");
|
||||
|
||||
// process each tool and generate the data so that a label+link can
|
||||
// be output by the component template for each tool required
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<!-- COMMUNITY ONLY -->
|
||||
<family>AdminConsole:Edition:Community</family>
|
||||
<format default="html">argument</format>
|
||||
<authentication>admin</authentication>
|
||||
<authentication>sysadmin</authentication>
|
||||
<lifecycle>internal</lifecycle>
|
||||
<transaction allow="readonly">required</transaction>
|
||||
</webscript>
|
||||
</webscript>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<url>/admin/</url>
|
||||
<family>AdminConsoleHelper</family>
|
||||
<format default="html">argument</format>
|
||||
<authentication>admin</authentication>
|
||||
<authentication>sysadmin</authentication>
|
||||
<lifecycle>internal</lifecycle>
|
||||
<transaction allow="readonly">required</transaction>
|
||||
</webscript>
|
||||
</webscript>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</description>
|
||||
<url>/api/admin/jmxdump</url>
|
||||
<family>AdminConsoleHelper</family>
|
||||
<authentication>admin</authentication>
|
||||
<authentication>sysadmin</authentication>
|
||||
<transaction allow="readonly"/>
|
||||
<lifecycle>internal</lifecycle>
|
||||
</webscript>
|
||||
</webscript>
|
||||
|
@@ -3,8 +3,8 @@
|
||||
<description>Update and retrieve repository usage</description>
|
||||
<url>/api/admin/usage</url>
|
||||
<format default="json" />
|
||||
<authentication>admin</authentication>
|
||||
<authentication>sysadmin</authentication>
|
||||
<transaction>required</transaction>
|
||||
<family>Admin</family>
|
||||
<lifecycle>internal</lifecycle>
|
||||
</webscript>
|
||||
</webscript>
|
||||
|
@@ -42,6 +42,7 @@ import org.junit.runners.Suite;
|
||||
org.alfresco.rest.api.tests.TestPublicApiAtomPub10TCK.class,
|
||||
org.alfresco.rest.api.tests.TestPublicApiAtomPub11TCK.class,
|
||||
org.alfresco.rest.api.tests.TestPublicApiBrowser11TCK.class,
|
||||
org.alfresco.repo.web.scripts.bulkimport.BulkImportParametersExtractorTest.class
|
||||
})
|
||||
public class AppContext01TestSuite
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -31,10 +31,12 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.dictionary.Facetable;
|
||||
import org.alfresco.repo.dictionary.IndexTokenisationMode;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authority.AuthorityServiceImpl;
|
||||
import org.alfresco.repo.web.scripts.BaseWebScriptTest;
|
||||
import org.alfresco.service.cmr.admin.RepoAdminService;
|
||||
import org.alfresco.service.cmr.admin.RepoUsage;
|
||||
@@ -48,11 +50,18 @@ import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.i18n.MessageLookup;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.descriptor.DescriptorService;
|
||||
import org.alfresco.service.license.LicenseDescriptor;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.test_category.OwnJVMTestsCategory;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.json.JSONObject;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -74,29 +83,46 @@ import static org.mockito.Mockito.when;
|
||||
@Category(OwnJVMTestsCategory.class)
|
||||
public class AdminWebScriptTest extends BaseWebScriptTest
|
||||
{
|
||||
private ApplicationContext ctx;
|
||||
private RepoAdminService repoAdminService;
|
||||
private DescriptorService descriptorService;
|
||||
private RepoAdminService repoAdminService;
|
||||
private DescriptorService descriptorService;
|
||||
private PersonService personService;
|
||||
private MutableAuthenticationService authenticationService;
|
||||
|
||||
private String admin;
|
||||
private String guest;
|
||||
private String user1_sysAdmin;
|
||||
private String user2;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
ctx = getServer().getApplicationContext();
|
||||
repoAdminService = (RepoAdminService) ctx.getBean("RepoAdminService");
|
||||
descriptorService = (DescriptorService) ctx.getBean("DescriptorService");
|
||||
ApplicationContext ctx = getServer().getApplicationContext();
|
||||
repoAdminService = ctx.getBean("RepoAdminService", RepoAdminService.class);
|
||||
descriptorService = ctx.getBean("DescriptorService", DescriptorService.class);
|
||||
personService = ctx.getBean("PersonService", PersonService.class);
|
||||
authenticationService = ctx.getBean("AuthenticationService", MutableAuthenticationService.class);
|
||||
AuthorityService authorityService = ctx.getBean("AuthorityService", AuthorityService.class);
|
||||
admin = AuthenticationUtil.getAdminUserName();
|
||||
guest = AuthenticationUtil.getGuestUserName();
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(admin);
|
||||
|
||||
user1_sysAdmin = RandomStringUtils.randomAlphabetic(10);
|
||||
String user1_password = RandomStringUtils.randomAlphabetic(10);
|
||||
createUser(user1_sysAdmin, user1_password);
|
||||
authorityService.addAuthority(AuthorityServiceImpl.GROUP_ALFRESCO_SYSTEM_ADMINISTRATORS_AUTHORITY, user1_sysAdmin);
|
||||
|
||||
user2 = RandomStringUtils.randomAlphabetic(10);
|
||||
String user2_password = RandomStringUtils.randomAlphabetic(10);
|
||||
createUser(user2, user2_password);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
super.tearDown();
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
}
|
||||
|
||||
public void testGetRestrictions() throws Exception
|
||||
@@ -227,6 +253,129 @@ public class AdminWebScriptTest extends BaseWebScriptTest
|
||||
assertTrue(property.getResidual());
|
||||
}
|
||||
|
||||
public void testSysAdminAccess() throws Exception
|
||||
{
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
|
||||
String url = "/admin/admin-communitysummary";
|
||||
TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
|
||||
|
||||
Response response = sendRequest(req, Status.STATUS_OK, user1_sysAdmin);
|
||||
Document doc = Jsoup.parse(response.getContentAsString());
|
||||
assertNotNull(doc.title());
|
||||
assertTrue(doc.title().contains("System Summary"));
|
||||
|
||||
// Super Admin should still have access to all the scripts
|
||||
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||
doc = Jsoup.parse(response.getContentAsString());
|
||||
assertNotNull(doc.title());
|
||||
assertTrue(doc.title().contains("System Summary"));
|
||||
}
|
||||
|
||||
public void testSysAdminAccess_nodeBrowser() throws Exception
|
||||
{
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
|
||||
String nodeBrowserUrl = "/admin/admin-nodebrowser";
|
||||
|
||||
// test the get webscript of the node browser
|
||||
TestWebScriptServer.GetRequest getReq = new TestWebScriptServer.GetRequest(nodeBrowserUrl);
|
||||
// The node browser is only accessible to admins, not sysAdmins
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// test the post webscript of the node browser too
|
||||
TestWebScriptServer.PostRequest postReq = new TestWebScriptServer.PostRequest(nodeBrowserUrl, "",
|
||||
"multipart/form-data; boundary=----WebKitFormBoundaryjacWCXfJ3KjtRenA");
|
||||
// The node browser is only accessible to admins, not sysAdmins
|
||||
sendRequest(postReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// Normal user shouldn't have access either
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user2);
|
||||
|
||||
// Admin should have access to everything
|
||||
Response response = sendRequest(getReq, Status.STATUS_OK, admin);
|
||||
Document doc = Jsoup.parse(response.getContentAsString());
|
||||
assertNotNull(doc.title());
|
||||
assertTrue(doc.title().contains("Node Browser"));
|
||||
}
|
||||
|
||||
public void testSysAdminAccess_repoConsole() throws Exception
|
||||
{
|
||||
String repoConsoleUrl = "/admin/admin-repoconsole";
|
||||
|
||||
// test the get webscript of the repo console
|
||||
TestWebScriptServer.GetRequest getReq = new TestWebScriptServer.GetRequest(repoConsoleUrl);
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// test the post webscript of the repo console too
|
||||
TestWebScriptServer.PostRequest postReq = new TestWebScriptServer.PostRequest(repoConsoleUrl, "",
|
||||
"multipart/form-data; boundary=----WebKitFormBoundaryjacWCXfJ3KjtRenA");
|
||||
sendRequest(postReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// Normal user shouldn't have access either
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user2);
|
||||
|
||||
// Admin should have access to everything
|
||||
Response response = sendRequest(getReq, Status.STATUS_OK, admin);
|
||||
Document doc = Jsoup.parse(response.getContentAsString());
|
||||
assertNotNull(doc.title());
|
||||
assertTrue(doc.title().contains("Model and Messages Console"));
|
||||
}
|
||||
|
||||
public void testSysAdminAccess_tenantConsole() throws Exception
|
||||
{
|
||||
String tenantConsoleUrl = "/admin/admin-tenantconsole";
|
||||
// test the get webscript of the tenant console
|
||||
TestWebScriptServer.GetRequest getReq = new TestWebScriptServer.GetRequest(tenantConsoleUrl);
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// test the post webscript of the tenant console too
|
||||
TestWebScriptServer.PostRequest postReq = new TestWebScriptServer.PostRequest(tenantConsoleUrl, "",
|
||||
"multipart/form-data; boundary=----WebKitFormBoundaryjacWCXfJ3KjtRenA");
|
||||
sendRequest(postReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// Normal user shouldn't have access either
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user2);
|
||||
|
||||
// Admin should have access to everything
|
||||
Response response = sendRequest(getReq, Status.STATUS_OK, admin);
|
||||
Document doc = Jsoup.parse(response.getContentAsString());
|
||||
assertNotNull(doc.title());
|
||||
assertTrue(doc.title().contains("Tenant Admin Console"));
|
||||
}
|
||||
|
||||
public void testSysAdminAccess_workflowConsole() throws Exception
|
||||
{
|
||||
String workflowConsoleUrl = "/admin/admin-workflowconsole";
|
||||
// test the get webscript of the workflow console
|
||||
TestWebScriptServer.GetRequest getReq = new TestWebScriptServer.GetRequest(workflowConsoleUrl);
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// test the post webscript of the workflow console too
|
||||
TestWebScriptServer.PostRequest postReq = new TestWebScriptServer.PostRequest(workflowConsoleUrl, "",
|
||||
"multipart/form-data; boundary=----WebKitFormBoundaryjacWCXfJ3KjtRenA");
|
||||
sendRequest(postReq, Status.STATUS_UNAUTHORIZED, user1_sysAdmin);
|
||||
|
||||
// Normal user shouldn't have access either
|
||||
sendRequest(getReq, Status.STATUS_UNAUTHORIZED, user2);
|
||||
|
||||
// Admin should have access to everything
|
||||
Response response = sendRequest(getReq, Status.STATUS_OK, admin);
|
||||
Document doc = Jsoup.parse(response.getContentAsString());
|
||||
assertNotNull(doc.title());
|
||||
assertTrue(doc.title().contains("Workflow Admin Console"));
|
||||
}
|
||||
|
||||
public void testNonSysAdminAccess() throws Exception
|
||||
{
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
|
||||
String url = "/admin/admin-communitysummary";
|
||||
TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
|
||||
|
||||
sendRequest(req, Status.STATUS_UNAUTHORIZED, user2);
|
||||
}
|
||||
|
||||
private class SimplePropertyDefinition implements PropertyDefinition
|
||||
{
|
||||
private boolean isAspect;
|
||||
@@ -350,4 +499,19 @@ public class AdminWebScriptTest extends BaseWebScriptTest
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void createUser(String username, String password)
|
||||
{
|
||||
if (!personService.personExists(username))
|
||||
{
|
||||
this.authenticationService.createAuthentication(username, password.toCharArray());
|
||||
|
||||
PropertyMap personProps = new PropertyMap();
|
||||
personProps.put(ContentModel.PROP_USERNAME, username);
|
||||
personProps.put(ContentModel.PROP_FIRSTNAME, "testFirstName");
|
||||
personProps.put(ContentModel.PROP_LASTNAME, "testLastName");
|
||||
personProps.put(ContentModel.PROP_EMAIL, username + "@email.com");
|
||||
this.personService.createPerson(personProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bulkimport;
|
||||
|
||||
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_BATCH_SIZE;
|
||||
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_DISABLE_RULES;
|
||||
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_NUM_THREADS;
|
||||
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_TARGET_NODEREF;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.bulkimport.BulkImportParameters;
|
||||
import org.alfresco.repo.bulkimport.BulkImportParameters.ExistingFileMode;
|
||||
import org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.BulkImportParametersExtractor;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.junit.Test;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
|
||||
public class BulkImportParametersExtractorTest
|
||||
{
|
||||
private static final String TEST_NODE_REF = "workspace://SpacesStore/this-is-just-a-test-ref";
|
||||
private static final String TEST_MISSING_NODE_REF = "workspace://SpacesStore/this-is-just-a-not-existing-test-ref";
|
||||
private static final Integer DEFAULT_BATCH_SIZE = 1234;
|
||||
private static final Integer DEFAULT_NUMBER_OF_THREADS = 4321;
|
||||
|
||||
@Test
|
||||
public void shouldExtractTargetRef() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF));
|
||||
|
||||
final BulkImportParameters params = extractor.extract();
|
||||
|
||||
assertNotNull(params);
|
||||
assertNotNull(params.getTarget());
|
||||
assertEquals(TEST_NODE_REF, params.getTarget().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFallbackToDefaultValues() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF));
|
||||
|
||||
final BulkImportParameters params = extractor.extract();
|
||||
|
||||
assertEquals(DEFAULT_BATCH_SIZE, params.getBatchSize());
|
||||
assertEquals(DEFAULT_NUMBER_OF_THREADS, params.getNumThreads());
|
||||
assertFalse(params.isDisableRulesService());
|
||||
assertEquals(ExistingFileMode.SKIP, params.getExistingFileMode());
|
||||
assertNull(params.getLoggingInterval());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractDisableFolderRulesFlagWhenSetToTrue() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_DISABLE_RULES, "true"
|
||||
));
|
||||
|
||||
final BulkImportParameters params = extractor.extract();
|
||||
|
||||
assertTrue(params.isDisableRulesService());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractDisableFolderRulesFlagWhenSetToFalse() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_DISABLE_RULES, "false"
|
||||
));
|
||||
|
||||
final BulkImportParameters params = extractor.extract();
|
||||
|
||||
assertFalse(params.isDisableRulesService());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractDisableFolderRulesFlagWhenSetToNotBooleanValue() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_DISABLE_RULES, "unknown"
|
||||
));
|
||||
|
||||
final BulkImportParameters params = extractor.extract();
|
||||
|
||||
assertFalse(params.isDisableRulesService());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPropagateFileNotFoundExceptionWhenTargetIsNotFound()
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_MISSING_NODE_REF));
|
||||
|
||||
assertThrows(FileNotFoundException.class, extractor::extract);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractValidBatchSize() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_BATCH_SIZE, "1"));
|
||||
|
||||
final BulkImportParameters params = extractor.extract();
|
||||
|
||||
assertEquals(Integer.valueOf(1), params.getBatchSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailWithWebScriptExceptionWhenInvalidBatchSizeIsRequested() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_BATCH_SIZE, "not-a-number"));
|
||||
|
||||
try
|
||||
{
|
||||
extractor.extract();
|
||||
} catch (WebScriptException e)
|
||||
{
|
||||
assertNotNull(e.getMessage());
|
||||
assertTrue(e.getMessage().contains(PARAMETER_BATCH_SIZE));
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Expected exception to be thrown.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailWithWebScriptExceptionWhenNegativeBatchSizeIsRequested() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_BATCH_SIZE, "-1"));
|
||||
|
||||
try
|
||||
{
|
||||
extractor.extract();
|
||||
} catch (WebScriptException e)
|
||||
{
|
||||
assertNotNull(e.getMessage());
|
||||
assertTrue(e.getMessage().contains(PARAMETER_BATCH_SIZE));
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Expected exception to be thrown.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractValidNumberOfThreads() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_NUM_THREADS, "1"));
|
||||
|
||||
final BulkImportParameters params = extractor.extract();
|
||||
|
||||
assertEquals(Integer.valueOf(1), params.getNumThreads());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailWithWebScriptExceptionWhenInvalidNumberOfThreadsIsRequested() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_NUM_THREADS, "not-a-number"));
|
||||
|
||||
try
|
||||
{
|
||||
extractor.extract();
|
||||
} catch (WebScriptException e)
|
||||
{
|
||||
assertNotNull(e.getMessage());
|
||||
assertTrue(e.getMessage().contains(PARAMETER_NUM_THREADS));
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Expected exception to be thrown.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailWithWebScriptExceptionWhenNegativeNumberOfThreadsIsRequested() throws FileNotFoundException
|
||||
{
|
||||
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
|
||||
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
|
||||
PARAMETER_NUM_THREADS, "-1"));
|
||||
|
||||
try
|
||||
{
|
||||
extractor.extract();
|
||||
} catch (WebScriptException e)
|
||||
{
|
||||
assertNotNull(e.getMessage());
|
||||
assertTrue(e.getMessage().contains(PARAMETER_NUM_THREADS));
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Expected exception to be thrown.");
|
||||
}
|
||||
|
||||
private BulkImportParametersExtractor givenExtractor(Map<String, String> params)
|
||||
{
|
||||
|
||||
return new BulkImportParametersExtractor(params::get, this::testRefCreator, DEFAULT_BATCH_SIZE, DEFAULT_NUMBER_OF_THREADS);
|
||||
}
|
||||
|
||||
private NodeRef testRefCreator(String nodeRef, String path) throws FileNotFoundException
|
||||
{
|
||||
if (TEST_MISSING_NODE_REF.equals(nodeRef))
|
||||
{
|
||||
throw new FileNotFoundException(new NodeRef(nodeRef));
|
||||
}
|
||||
return new NodeRef(nodeRef);
|
||||
}
|
||||
|
||||
}
|
@@ -78,8 +78,6 @@ public class DeletedNodesTest extends AbstractSingleNetworkSiteTest
|
||||
|
||||
protected static final String URL_DELETED_NODES = "deleted-nodes";
|
||||
private static final String URL_RENDITIONS = "renditions";
|
||||
|
||||
private final static long DELAY_IN_MS = 500;
|
||||
|
||||
@Override
|
||||
public void setup() throws Exception
|
||||
@@ -732,6 +730,45 @@ public class DeletedNodesTest extends AbstractSingleNetworkSiteTest
|
||||
HttpResponse dauResponse = post(getRequestArchivedContentDirectUrl(contentNodeId), null, null, null, null, 501);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestArchivedRenditionDirectUrl() throws Exception
|
||||
{
|
||||
setRequestContext(user1);
|
||||
|
||||
// Create a folder within the site document's library
|
||||
Date now = new Date();
|
||||
String folder1 = "folder" + now.getTime() + "_1";
|
||||
Folder createdFolder = createFolder(tDocLibNodeId, folder1, null);
|
||||
assertNotNull(createdFolder);
|
||||
String f1Id = createdFolder.getId();
|
||||
|
||||
// Create multipart request using an existing file
|
||||
String fileName = "quick.pdf";
|
||||
File file = getResourceFile(fileName);
|
||||
MultiPartBuilder multiPartBuilder = MultiPartBuilder.create().setFileData(new MultiPartBuilder.FileData(fileName, file));
|
||||
MultiPartBuilder.MultiPartRequest reqBody = multiPartBuilder.build();
|
||||
|
||||
// Upload quick.pdf file into 'folder'
|
||||
HttpResponse response = post(getNodeChildrenUrl(f1Id), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||
Document document = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||
String contentNodeId = document.getId();
|
||||
|
||||
Rendition rendition = createAndGetRendition(contentNodeId, "doclib");
|
||||
assertNotNull(rendition);
|
||||
String renditionID = rendition.getId();
|
||||
assertEquals(Rendition.RenditionStatus.CREATED, rendition.getStatus());
|
||||
|
||||
deleteNode(contentNodeId);
|
||||
|
||||
HttpResponse dauResponse = post(getRequestArchivedRenditonContentDirectUrl(contentNodeId, renditionID), null, null, null, null, 501);
|
||||
}
|
||||
|
||||
private String addToDocumentLibrary(String name, String nodeType, String userId) throws Exception
|
||||
{
|
||||
String parentId = getSiteContainerNodeId(Nodes.PATH_MY, "documentLibrary");
|
||||
return createNode(parentId, name, nodeType, null).getId();
|
||||
}
|
||||
|
||||
private String getDeletedNodeRenditionsUrl(String nodeId)
|
||||
{
|
||||
return URL_DELETED_NODES + "/" + nodeId + "/" + URL_RENDITIONS;
|
||||
|
@@ -224,6 +224,11 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
|
||||
return URL_DELETED_NODES + "/" + nodeId + "/" + REQUEST_DIRECT_ACCESS_URL;
|
||||
}
|
||||
|
||||
protected String getRequestArchivedRenditonContentDirectUrl(String nodeId, String renditionID)
|
||||
{
|
||||
return URL_DELETED_NODES + "/" + nodeId + "/" + URL_RENDITIONS + "/" + renditionID + "/" + REQUEST_DIRECT_ACCESS_URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The api scope. either public or private
|
||||
*
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>11.128</version>
|
||||
<version>12.7</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -73,6 +73,7 @@ public class ContentStoreDirectUrlConfig extends AbstractDirectUrlConfig
|
||||
logger.error("Disabling content store direct access URLs due to configuration error: " + ex.getMessage());
|
||||
setEnabled(false);
|
||||
}
|
||||
logger.info("Content store direct access URLs are " + (isEnabled() ? "enabled" : "disabled"));
|
||||
}
|
||||
|
||||
/* Helper method to validate the content direct access url configuration settings */
|
||||
|
@@ -96,6 +96,7 @@ public class SystemWideDirectUrlConfig implements DirectUrlConfig
|
||||
logger.error("Disabling system-wide direct access URLs due to configuration error: " + ex.getMessage());
|
||||
setEnabled(false);
|
||||
}
|
||||
logger.info("System-wide direct access URLs are " + (isEnabled() ? "enabled" : "disabled"));
|
||||
}
|
||||
|
||||
/* Helper method to validate the system-wide direct access url configuration settings */
|
||||
|
@@ -415,12 +415,13 @@ implements TenantDeployer, DictionaryListener, /*TenantDictionaryListener, */Mes
|
||||
|
||||
for (NodeRef messageResource : nodeRefs)
|
||||
{
|
||||
String resourceName = (String) nodeService.getProperty(messageResource, ContentModel.PROP_NAME);
|
||||
|
||||
String bundleBaseName = messageService.getBaseBundleName(resourceName);
|
||||
String messageResourcePath = nodeService.getPath(messageResource).toPrefixString(namespaceService);
|
||||
String bundleBasePrefixedName = messageResourcePath.substring(messageResourcePath.lastIndexOf("/"));
|
||||
String bundleBaseName = messageService.getBaseBundleName(bundleBasePrefixedName);
|
||||
|
||||
if (!resourceBundleBaseNames.contains(bundleBaseName))
|
||||
{
|
||||
messageService.registerResourceBundle(storeRef.toString() + repositoryLocation.getPath() + bundleBaseName);
|
||||
resourceBundleBaseNames.add(bundleBaseName);
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +1,33 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.permissions.impl.acegi;
|
||||
|
||||
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
|
||||
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
@@ -46,8 +49,6 @@ import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.OwnableService;
|
||||
@@ -59,6 +60,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
|
||||
/**
|
||||
* @author andyh
|
||||
*/
|
||||
@@ -395,61 +397,53 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
|
||||
{
|
||||
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
||||
}
|
||||
else if (StoreRef.class.isAssignableFrom(params[cad.parameter[0]]))
|
||||
|
||||
if (List.class.isAssignableFrom(params[cad.parameter[0]]))
|
||||
{
|
||||
StoreRef storeRef = getArgument(invocation, cad.parameter[0]);
|
||||
if (storeRef != null)
|
||||
List<?> listArgument = getArgument(invocation, cad.parameter[0]);
|
||||
if (listArgument != null)
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
NodeRef listNodeRef;
|
||||
Integer accessAbstainOrDeny = null;
|
||||
for (Object listElement : listArgument)
|
||||
{
|
||||
log.debug("\tPermission test against the store - using permissions on the root node");
|
||||
}
|
||||
if (nodeService.exists(storeRef))
|
||||
{
|
||||
testNodeRef = nodeService.getRootNode(storeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (NodeRef.class.isAssignableFrom(params[cad.parameter[0]]))
|
||||
{
|
||||
testNodeRef = getArgument(invocation, cad.parameter[0]);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
if (testNodeRef != null)
|
||||
{
|
||||
if (nodeService.exists(testNodeRef))
|
||||
listNodeRef = getNodeRef(listElement, nodeService);
|
||||
Integer currentValue = shouldAbstainOrDeny(cad.required, listNodeRef, abstainForClassQNames, nodeService, permissionService);
|
||||
|
||||
if (currentValue != null)
|
||||
{
|
||||
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
|
||||
if (currentValue == AccessDecisionVoter.ACCESS_DENIED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
accessAbstainOrDeny = currentValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("\tPermission test on non-existing node " +testNodeRef);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter[0]]))
|
||||
{
|
||||
ChildAssociationRef testChildRef = getArgument(invocation, cad.parameter[0]);
|
||||
if (testChildRef != null)
|
||||
{
|
||||
testNodeRef = testChildRef.getChildRef();
|
||||
if (log.isDebugEnabled())
|
||||
|
||||
if (accessAbstainOrDeny != null)
|
||||
{
|
||||
if (nodeService.exists(testNodeRef))
|
||||
{
|
||||
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("\tPermission test on non-existing node " + testNodeRef);
|
||||
}
|
||||
return accessAbstainOrDeny;
|
||||
}
|
||||
if((hasMethodEntry == null) || (hasMethodEntry.booleanValue()))
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
||||
Object testObject = getArgument(invocation, cad.parameter[0]);
|
||||
//If the execution reaches here, then testNodeRef is always null
|
||||
testNodeRef = getNodeRef(testObject, nodeService);
|
||||
}
|
||||
}
|
||||
else if (cad.typeString.equals(ACL_ITEM))
|
||||
@@ -584,44 +578,10 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
|
||||
}
|
||||
}
|
||||
|
||||
if (testNodeRef != null)
|
||||
Integer accessAbstainOrDeny = shouldAbstainOrDeny(cad.required, testNodeRef, abstainForClassQNames, nodeService, permissionService);
|
||||
if (accessAbstainOrDeny != null)
|
||||
{
|
||||
// now we know the node - we can abstain for certain types and aspects (eg. RM)
|
||||
if(abstainForClassQNames.size() > 0)
|
||||
{
|
||||
// check node exists
|
||||
if (nodeService.exists(testNodeRef))
|
||||
{
|
||||
QName typeQName = nodeService.getType(testNodeRef);
|
||||
if(abstainForClassQNames.contains(typeQName))
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
}
|
||||
|
||||
Set<QName> aspectQNames = nodeService.getAspects(testNodeRef);
|
||||
for(QName abstain : abstainForClassQNames)
|
||||
{
|
||||
if(aspectQNames.contains(abstain))
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("\t\tNode ref is not null");
|
||||
}
|
||||
if (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED)
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("\t\tPermission is denied");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
return AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
return accessAbstainOrDeny;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.permissions.impl.acegi;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import net.sf.acegisecurity.vote.AccessDecisionVoter;
|
||||
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Utility methods extracted from AclEntryVoter
|
||||
*
|
||||
* @author Lev Belava
|
||||
*/
|
||||
final class ACLEntryVoterUtils
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ACLEntryVoterUtils.class);
|
||||
|
||||
private ACLEntryVoterUtils()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets NodeRef for testObject based on inferred type
|
||||
*
|
||||
* @param testObject Tested object to work on
|
||||
* @param nodeService Node service to perform checks on refs
|
||||
* @return NodeRef for testObject or null if (testObject is null or StoreRef from testObject does not exist in the provided NodeService)
|
||||
* @throws ACLEntryVoterException if testObject is not null and not one of a NodeRef or ChildAssociationRef types
|
||||
*/
|
||||
static NodeRef getNodeRef(Object testObject, NodeService nodeService)
|
||||
{
|
||||
if (testObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (StoreRef.class.isAssignableFrom(testObject.getClass()))
|
||||
{
|
||||
LOG.debug("Permission test against the store - using permissions on the root node");
|
||||
StoreRef storeRef = (StoreRef) testObject;
|
||||
if (nodeService.exists(storeRef))
|
||||
{
|
||||
return nodeService.getRootNode(storeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("StoreRef does not exist");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (NodeRef.class.isAssignableFrom(testObject.getClass()))
|
||||
{
|
||||
NodeRef result = (NodeRef) testObject;
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
if (nodeService.exists(result))
|
||||
{
|
||||
LOG.debug("Permission test on node {}", nodeService.getPath(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("Permission test on non-existing node {}", result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (ChildAssociationRef.class.isAssignableFrom(testObject.getClass()))
|
||||
{
|
||||
ChildAssociationRef testChildRef = (ChildAssociationRef) testObject;
|
||||
NodeRef result = testChildRef.getChildRef();
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
if (nodeService.exists(result))
|
||||
{
|
||||
LOG.debug("Permission test on node {}", nodeService.getPath(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("Permission test on non-existing node {}", result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if tested NodeRef instance is abstained or denied based on set of QNames to abstain and
|
||||
*
|
||||
* @param requiredPermissionReference Required permissions
|
||||
* @param testNodeRef NodeRef to be verified
|
||||
* @param abstainForClassQNames Set of QNames to abstain
|
||||
* @param nodeService Node service to perform checks on tested NodeRef
|
||||
* @param permissionService Permission service to check for required permissions
|
||||
* @return null if testNodeRef is not abstained or denied, otherwise returns appropriate status.
|
||||
*/
|
||||
static Integer shouldAbstainOrDeny(SimplePermissionReference requiredPermissionReference, NodeRef testNodeRef, Set<QName> abstainForClassQNames,
|
||||
NodeService nodeService, PermissionService permissionService)
|
||||
{
|
||||
if (testNodeRef == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
LOG.debug("Node ref is not null");
|
||||
|
||||
if (abstainForClassQNames.size() > 0 && nodeService.exists(testNodeRef))
|
||||
{
|
||||
if (abstainForClassQNames.contains(nodeService.getType(testNodeRef)))
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
}
|
||||
Set<QName> testNodeRefAspects = nodeService.getAspects(testNodeRef);
|
||||
for (QName abstain : abstainForClassQNames)
|
||||
{
|
||||
if (testNodeRefAspects.contains(abstain))
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AccessStatus.DENIED == permissionService.hasPermission(testNodeRef, requiredPermissionReference.toString()))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Permission is denied");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
return AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -12,6 +12,7 @@ ALTER TABLE alf_transaction
|
||||
DROP COLUMN IF EXISTS server_id;
|
||||
|
||||
DROP TABLE IF EXISTS alf_server;
|
||||
DROP SEQUENCE IF EXISTS alf_server_seq;
|
||||
|
||||
--
|
||||
-- Record script finish
|
||||
|
@@ -125,7 +125,7 @@ cm_contentmodel.aspect.cm_auditable.title=Kan overv\u00e5ges
|
||||
cm_contentmodel.aspect.cm_auditable.description=Kan overv\u00e5ges
|
||||
cm_contentmodel.property.cm_created.title=Oprettelsesdato
|
||||
cm_contentmodel.property.cm_created.description=Oprettelsesdato
|
||||
cm_contentmodel.property.cm_creator.title=Oprettet af
|
||||
cm_contentmodel.property.cm_creator.title=Opretter
|
||||
cm_contentmodel.property.cm_creator.description=Den person, der oprettede elementet
|
||||
cm_contentmodel.property.cm_modified.title=\u00c6ndringsdato
|
||||
cm_contentmodel.property.cm_modified.description=Tidspunkt for, hvorn\u00e5r elementet senest blev \u00e6ndret
|
||||
|
@@ -93,7 +93,7 @@ iptcxmp_iptcmodel.property.Iptc4xmpExt_DigitalSourcefileType.title=Originalfotos
|
||||
iptcxmp_iptcmodel.property.Iptc4xmpExt_DigitalSourcefileType.description=Kildens digitale filtype.
|
||||
iptcxmp_iptcmodel.property.Iptc4xmpExt_DigitalSourceType.title=Kildetype til dette foto
|
||||
iptcxmp_iptcmodel.property.Iptc4xmpExt_DigitalSourceType.description=Kildetype til dette digitale billede
|
||||
iptcxmp_iptcmodel.property.Iptc4xmpExt_Event.title=Event
|
||||
iptcxmp_iptcmodel.property.Iptc4xmpExt_Event.title=H\u00e6ndelse
|
||||
iptcxmp_iptcmodel.property.Iptc4xmpExt_Event.description=Navngiver eller beskriver den specifikke begivenhed indholdet relaterer til.
|
||||
iptcxmp_iptcmodel.property.plus_ImageSupplierID.title=Billedes leverand\u00f8r-ID
|
||||
iptcxmp_iptcmodel.property.plus_ImageSupplierID.description=Identificerer emnets den nyeste leverand\u00f8r, som ikke n\u00f8dvendigvis er ejer eller opretter.
|
||||
@@ -125,7 +125,7 @@ iptcxmp_iptcmodel.property.plus_LicensorCity.title=By
|
||||
iptcxmp_iptcmodel.property.plus_LicensorCity.description=By for en person eller virksomhed, der skal kontaktes for at f\u00e5 en licens til brug af emnet, eller som har licens p\u00e5 emnet.
|
||||
iptcxmp_iptcmodel.property.plus_LicensorCountry.title=Land
|
||||
iptcxmp_iptcmodel.property.plus_LicensorCountry.description=Land for en person eller virksomhed, der skal kontaktes for at f\u00e5 en licens til brug af emnet, eller som har licens p\u00e5 emnet.
|
||||
iptcxmp_iptcmodel.property.plus_LicensorEmail.title=e-mail
|
||||
iptcxmp_iptcmodel.property.plus_LicensorEmail.title=E-mailadresse
|
||||
iptcxmp_iptcmodel.property.plus_LicensorEmail.description=E-mail for en person eller virksomhed, der skal kontaktes for at f\u00e5 en licens til brug af emnet, eller som har licens p\u00e5 emnet.
|
||||
iptcxmp_iptcmodel.property.plus_LicensorExtendedAddress.title=Udviddet adresse
|
||||
iptcxmp_iptcmodel.property.plus_LicensorExtendedAddress.description=Udvidet adresse for en person eller virksomhed, der skal kontaktes for at f\u00e5 en licens til brug af emnet, eller som har licens p\u00e5 emnet.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=Die folgenden Probleme werden behoben, sobald das lange Ausf\u00fchrungspatch ''{0}'' ausgef\u00fchrt wurde.
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=Los siguientes problemas se resolver\u00e1n una vez que se haya ejecutado el parche de larga duraci\u00f3n {0}
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=Les probl\u00e8mes suivants seront r\u00e9solus une fois la longue ex\u00e9cution du correctif {0} termin\u00e9e
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=I problemi seguenti verranno risolti al termine dell''esecuzione della patch di lunga durata {0}
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=\u9577\u6642\u9593\u30d1\u30b9{0}\u3092\u5b9f\u884c\u3059\u308b\u3068\u3001\u6b21\u306e\u554f\u984c\u304c\u89e3\u6c7a\u3055\u308c\u307e\u3059
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=F\u00f8lgende problemer vil bli l\u00f8st s\u00e5 snart den lengekj\u00f8rende oppdateringen {0} har blitt kj\u00f8rt
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=De volgende problemen worden opgelost zodra de langlopende patch {0} is uitgevoerd
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=Os seguintes problemas ser\u00e3o resolvidos ap\u00f3s o patch de longa execu\u00e7\u00e3o {0} ter sido executado
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0448\u0435\u043d\u044b \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0433\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f {0}
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -38,7 +38,7 @@ system.schema_comp.index_columns_validator=Number of columns in index doesn''t m
|
||||
system.schema_comp.column_names_validator=Column types do not match. Was {0}, but expected {1}
|
||||
system.schema_comp.schema_version_validator=version must be at least ''{0}''
|
||||
# Optional long running patch messages...
|
||||
system.schema_comp.patch_run_suggestion=The following problems will be resolved once the long running patch {0} has been run
|
||||
system.schema_comp.patch_run_suggestion=\u4e00\u65e6\u8fd0\u884c\u4e86\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u4fee\u8865\u7a0b\u5e8f{0}\uff0c\u4ee5\u4e0b\u95ee\u9898\u5c06\u5f97\u5230\u89e3\u51b3
|
||||
|
||||
# Clustering
|
||||
system.cluster.license.not_enabled=License does not permit clustering: clustering is disabled.
|
||||
|
@@ -3,7 +3,7 @@
|
||||
repository.name=Main Repository
|
||||
|
||||
# Schema number
|
||||
version.schema=15002
|
||||
version.schema=15100
|
||||
|
||||
# Directory configuration
|
||||
|
||||
|
@@ -209,6 +209,7 @@ import org.junit.runners.Suite;
|
||||
org.alfresco.repo.security.authentication.AuthorizationTest.class,
|
||||
org.alfresco.repo.security.permissions.PermissionCheckedCollectionTest.class,
|
||||
org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSetTest.class,
|
||||
org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtilsTest.class,
|
||||
org.alfresco.repo.security.authentication.ChainingAuthenticationServiceTest.class,
|
||||
org.alfresco.repo.security.authentication.NameBasedUserNameGeneratorTest.class,
|
||||
org.alfresco.repo.version.common.VersionImplTest.class,
|
||||
|
@@ -31,17 +31,18 @@ import java.io.PrintWriter;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.dictionary.DictionaryDAO;
|
||||
import org.alfresco.repo.dictionary.NamespaceDAO;
|
||||
import org.alfresco.repo.i18n.MessageService;
|
||||
import org.alfresco.repo.node.db.DbNodeServiceImpl;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
@@ -50,6 +51,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
|
||||
import org.alfresco.service.cmr.admin.RepoAdminService;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -67,6 +69,8 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @see RepoAdminServiceImpl
|
||||
*
|
||||
@@ -88,6 +92,7 @@ public class RepoAdminServiceImplTest extends TestCase
|
||||
private NamespaceService namespaceService;
|
||||
private BehaviourFilter behaviourFilter;
|
||||
private DictionaryDAO dictionaryDAO;
|
||||
private MessageService messageService;
|
||||
|
||||
final String modelPrefix = "model-";
|
||||
final static String MKR = "{MKR}";
|
||||
@@ -140,6 +145,7 @@ public class RepoAdminServiceImplTest extends TestCase
|
||||
namespaceService = (NamespaceService) ctx.getBean("NamespaceService");
|
||||
behaviourFilter = (BehaviourFilter)ctx.getBean("policyBehaviourFilter");
|
||||
dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO");
|
||||
messageService = (MessageService) ctx.getBean("MessageService");
|
||||
|
||||
DbNodeServiceImpl dbNodeService = (DbNodeServiceImpl)ctx.getBean("dbNodeService");
|
||||
dbNodeService.setEnableTimestampPropagation(false);
|
||||
@@ -865,8 +871,182 @@ public class RepoAdminServiceImplTest extends TestCase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TODO - Test custom message management
|
||||
//
|
||||
|
||||
// Test deploy bundle from classpath
|
||||
public void testDeployMessageBundleFromClasspath() throws Exception
|
||||
{
|
||||
String bundleBaseName = "mycustommessages";
|
||||
String resourceClasspath = "alfresco/extension/messages/" + bundleBaseName;
|
||||
|
||||
final String message_key = "mycustommessages.key1";
|
||||
final String message_value_default = "This is a custom message";
|
||||
final String message_value_fr = "Ceci est un message personnalis\\u00e9";
|
||||
final String message_value_de = "Dies ist eine benutzerdefinierte Nachricht";
|
||||
|
||||
// Undeploy the bundle
|
||||
if (repoAdminService.getMessageBundles().contains(bundleBaseName))
|
||||
{
|
||||
repoAdminService.undeployMessageBundle(bundleBaseName);
|
||||
}
|
||||
|
||||
// Verify the custom bundle is registered
|
||||
assertFalse("The custom bundle should not be deployed", repoAdminService.getMessageBundles().contains(bundleBaseName));
|
||||
|
||||
// Depoly the message bundle
|
||||
repoAdminService.deployMessageBundle(resourceClasspath);
|
||||
|
||||
// Reload the messages
|
||||
repoAdminService.reloadMessageBundle(bundleBaseName);
|
||||
|
||||
// Verify the custom bundle is registered
|
||||
assertTrue("The custom bundle should be deployed", repoAdminService.getMessageBundles().contains(bundleBaseName));
|
||||
|
||||
// Verify we have the messages for each locale
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
|
||||
assertMessageValue("Cannot retrieve default message value", message_value_default, message_key, Locale.getDefault());
|
||||
assertMessageValue("Cannot retrieve french message value", message_value_fr, message_key, Locale.FRANCE);
|
||||
assertMessageValue("Cannot retrieve german message value", message_value_de, message_key, Locale.GERMANY);
|
||||
|
||||
// Test deploy a non existent bundle
|
||||
try
|
||||
{
|
||||
repoAdminService.deployMessageBundle("alfresco/extension/messages/inexistentbundle");
|
||||
fail("Bundle was not supposed to be deployed");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Expected to fail
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test deploy bundle from repo and reload bundles
|
||||
public void testDeployMessageBundleFromRepo() throws Exception
|
||||
{
|
||||
final String bundleBaseName = "repoBundle";
|
||||
final String message_key = "repoBundle.key1";
|
||||
final String message_value = "Value 1";
|
||||
final String message_value_fr = "Value FR";
|
||||
final String message_value_de = "Value DE";
|
||||
final String message_value_new = "New Value 1";
|
||||
|
||||
// Set location
|
||||
NodeRef rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(rootNodeRef, "/app:company_home/app:dictionary/app:messages", null,
|
||||
namespaceService, false);
|
||||
assertEquals(1, nodeRefs.size());
|
||||
NodeRef messagesNodeRef = nodeRefs.get(0);
|
||||
|
||||
// Clear messages of this bundle if they exist and are registered
|
||||
clearRepoBundles(messagesNodeRef);
|
||||
|
||||
assertEquals(0, repoAdminService.getMessageBundles().size());
|
||||
|
||||
// Create and upload the message files
|
||||
NodeRef messageNode_default = createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, null,
|
||||
message_value);
|
||||
createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, Locale.FRANCE.toString(), message_value_fr);
|
||||
createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, Locale.GERMANY.toString(),
|
||||
message_value_de);
|
||||
|
||||
// Reload the messages
|
||||
repoAdminService.reloadMessageBundle(bundleBaseName);
|
||||
|
||||
// Verify we have the messages for each locale
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
|
||||
assertMessageValue("Cannot retrieve default message value", message_value, message_key, Locale.getDefault());
|
||||
assertMessageValue("Cannot retrieve french message value", message_value_fr, message_key, Locale.FRANCE);
|
||||
assertMessageValue("Cannot retrieve german message value", message_value_de, message_key, Locale.GERMANY);
|
||||
|
||||
// Change the values
|
||||
putContentInMessageNode(messageNode_default, message_key, message_value_new);
|
||||
|
||||
// Verify we still have the old value
|
||||
assertMessageValue("Unexpected change of message value", message_value, message_key, Locale.getDefault());
|
||||
|
||||
// Reload the messages
|
||||
repoAdminService.reloadMessageBundle(bundleBaseName);
|
||||
|
||||
// Verify new values
|
||||
assertMessageValue("Change of message value not reflected", message_value_new, message_key, Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create messages node
|
||||
*/
|
||||
private NodeRef createMessagesNodeWithSingleKey(NodeRef parentNode, String bundleName, String key, String locale,
|
||||
String localeValue)
|
||||
{
|
||||
String msg_extension = ".properties";
|
||||
String filename = bundleName + msg_extension;
|
||||
String messageValue = localeValue;
|
||||
|
||||
if (locale != null)
|
||||
{
|
||||
filename = bundleName + "_" + locale + msg_extension;
|
||||
}
|
||||
// Create a model node
|
||||
NodeRef messageNode = this.nodeService.createNode(
|
||||
parentNode,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, filename),
|
||||
ContentModel.TYPE_CONTENT,
|
||||
Collections.<QName, Serializable> singletonMap(ContentModel.PROP_NAME, filename)
|
||||
).getChildRef();
|
||||
|
||||
putContentInMessageNode(messageNode, key, messageValue);
|
||||
|
||||
return messageNode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write content of message node
|
||||
*/
|
||||
private void putContentInMessageNode(NodeRef nodeRef, String key, String value)
|
||||
{
|
||||
ContentWriter contentWriter = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.setEncoding("UTF-8");
|
||||
contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
String messagesString = key + "=" + value;
|
||||
contentWriter.putContent(messagesString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Repo Bundle
|
||||
*/
|
||||
private void clearRepoBundles(NodeRef parentNode)
|
||||
{
|
||||
List<String> repoBundles = repoAdminService.getMessageBundles();
|
||||
for (String repoBundle : repoBundles)
|
||||
{
|
||||
repoAdminService.undeployMessageBundle(repoBundle);
|
||||
}
|
||||
|
||||
List<ChildAssociationRef> messageNodes = nodeService.getChildAssocs(parentNode);
|
||||
for (ChildAssociationRef messageChildRef : messageNodes)
|
||||
{
|
||||
NodeRef messageNode = messageChildRef.getChildRef();
|
||||
nodeService.deleteNode(messageNode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Repo Bundle
|
||||
*/
|
||||
private void assertMessageValue(String errorMessage, String expectedValue, String key, Locale locale)
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper()
|
||||
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
assertEquals(errorMessage, expectedValue, messageService.getMessage(key, locale));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -25,9 +25,14 @@
|
||||
*/
|
||||
package org.alfresco.repo.dictionary;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
@@ -53,8 +58,6 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Category(BaseSpringTestsCategory.class)
|
||||
@@ -94,6 +97,14 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
|
||||
"</model>";
|
||||
|
||||
public static final String MESSAGES_KEY = "my_bootstrap_test";
|
||||
public static final String MESSAGES_VALUE = "My Message";
|
||||
public static final String MESSAGES_VALUE_FR = "Mon message";
|
||||
public static final String FOLDERNAME_MODELS = "models";
|
||||
public static final String FOLDERNAME_MESSAGES = "messages";
|
||||
public static final String BUNDLENAME_MESSAGES = "testBootstap";
|
||||
public static final String FILENAME_MESSAGES_EXT = ".properties";
|
||||
|
||||
/** Behaviour filter */
|
||||
private BehaviourFilter behaviourFilter;
|
||||
|
||||
@@ -123,7 +134,8 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
|
||||
private UserTransaction txn;
|
||||
private StoreRef storeRef;
|
||||
private NodeRef rootNodeRef;
|
||||
private NodeRef rootModelsNodeRef;
|
||||
private NodeRef rootMessagesNodeRef;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
@@ -151,7 +163,17 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
|
||||
// Create the store and get the root node
|
||||
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(this.storeRef);
|
||||
|
||||
NodeRef rootNodeRef = this.nodeService.getRootNode(this.storeRef);
|
||||
this.rootModelsNodeRef = this.nodeService
|
||||
.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, FOLDERNAME_MODELS), ContentModel.TYPE_FOLDER)
|
||||
.getChildRef();
|
||||
|
||||
this.rootMessagesNodeRef = this.nodeService
|
||||
.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, FOLDERNAME_MESSAGES), ContentModel.TYPE_FOLDER)
|
||||
.getChildRef();
|
||||
|
||||
txn.commit();
|
||||
|
||||
@@ -167,18 +189,20 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
this.bootstrap.setNamespaceService(this.namespaceService);
|
||||
this.bootstrap.setMessageService(this.messageService);
|
||||
this.bootstrap.setPolicyComponent(this.policyComponent);
|
||||
|
||||
RepositoryLocation location = new RepositoryLocation();
|
||||
location.setStoreProtocol(this.storeRef.getProtocol());
|
||||
location.setStoreId(this.storeRef.getIdentifier());
|
||||
location.setQueryLanguage(RepositoryLocation.LANGUAGE_PATH);
|
||||
// NOTE: we are not setting the path for now .. in doing so we are searching the root node only
|
||||
|
||||
List<RepositoryLocation> locations = new ArrayList<RepositoryLocation>();
|
||||
locations.add(location);
|
||||
|
||||
this.bootstrap.setRepositoryModelsLocations(locations);
|
||||
|
||||
|
||||
RepositoryLocation modelsLocation = new RepositoryLocation(this.storeRef,
|
||||
this.nodeService.getPath(rootModelsNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH);
|
||||
RepositoryLocation messagesLocation = new RepositoryLocation(this.storeRef,
|
||||
this.nodeService.getPath(rootMessagesNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH);
|
||||
|
||||
List<RepositoryLocation> modelsLocations = new ArrayList<RepositoryLocation>();
|
||||
modelsLocations.add(modelsLocation);
|
||||
List<RepositoryLocation> messagesLocations = new ArrayList<RepositoryLocation>();
|
||||
messagesLocations.add(messagesLocation);
|
||||
|
||||
this.bootstrap.setRepositoryModelsLocations(modelsLocations);
|
||||
this.bootstrap.setRepositoryMessagesLocations(messagesLocations);
|
||||
|
||||
// register with dictionary service
|
||||
this.bootstrap.register();
|
||||
txn.commit();
|
||||
@@ -224,7 +248,15 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
"Test model one",
|
||||
"base1",
|
||||
"prop1");
|
||||
|
||||
|
||||
// Create a message file for the default locale
|
||||
NodeRef messageNodeDefaultLoc = createMessagesNode(null, null);
|
||||
// Create a message file for the french locale
|
||||
createMessagesNode(Locale.FRANCE.toString(), MESSAGES_VALUE_FR);
|
||||
// Construct baseBundleName for validation
|
||||
String baseBundleName = storeRef.toString()
|
||||
+ messageService.getBaseBundleName(nodeService.getPath(messageNodeDefaultLoc).toPrefixString(namespaceService));
|
||||
|
||||
// Check that the model is not in the dictionary yet
|
||||
try
|
||||
{
|
||||
@@ -251,6 +283,12 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
QName.createQName("http://www.alfresco.org/model/test3DictionaryBootstrapFromRepo/1.0", "testModel3"));
|
||||
assertNotNull(modelDefinition3);
|
||||
|
||||
// Check if the messages were registered correctly
|
||||
assertTrue("The message bundle should be registered", messageService.getRegisteredBundles().contains(baseBundleName));
|
||||
assertEquals("The default message value is not as expected", MESSAGES_VALUE, messageService.getMessage(MESSAGES_KEY));
|
||||
assertEquals("The message value in french is not as expected", MESSAGES_VALUE_FR,
|
||||
messageService.getMessage(MESSAGES_KEY, Locale.FRANCE));
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
@@ -277,7 +315,7 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
{
|
||||
// Create a model node
|
||||
NodeRef model = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
this.rootModelsNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}models"),
|
||||
ContentModel.TYPE_DICTIONARY_MODEL).getChildRef();
|
||||
@@ -300,6 +338,39 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create messages node
|
||||
*
|
||||
* @return NodeRef
|
||||
*/
|
||||
private NodeRef createMessagesNode(String locale, String localeValue)
|
||||
{
|
||||
String filename = BUNDLENAME_MESSAGES + FILENAME_MESSAGES_EXT;
|
||||
String messageValue = MESSAGES_VALUE;
|
||||
|
||||
if (locale != null)
|
||||
{
|
||||
filename = BUNDLENAME_MESSAGES + "_" + locale + FILENAME_MESSAGES_EXT;
|
||||
messageValue = localeValue;
|
||||
}
|
||||
// Create a model node
|
||||
NodeRef messageNode = this.nodeService.createNode(
|
||||
this.rootMessagesNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, filename),
|
||||
ContentModel.TYPE_CONTENT,
|
||||
Collections.<QName, Serializable> singletonMap(ContentModel.PROP_NAME, filename)
|
||||
).getChildRef();
|
||||
|
||||
ContentWriter contentWriter = this.contentService.getWriter(messageNode, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.setEncoding("UTF-8");
|
||||
contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
String messagesString = MESSAGES_KEY + "=" + messageValue;
|
||||
contentWriter.putContent(messagesString);
|
||||
|
||||
return messageNode;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Gets the model string
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -96,6 +96,8 @@ public abstract class AbstractPermissionTest extends TestCase
|
||||
|
||||
protected NodeRef systemNodeRef;
|
||||
|
||||
protected NodeRef abstainedNode;
|
||||
|
||||
protected AuthenticationComponent authenticationComponent;
|
||||
|
||||
protected ModelDAO permissionModelDAO;
|
||||
@@ -186,6 +188,8 @@ public abstract class AbstractPermissionTest extends TestCase
|
||||
props = createPersonProperties(USER2_LEMUR);
|
||||
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
|
||||
|
||||
abstainedNode= nodeService.createNode(rootNodeRef, ContentModel.ASSOC_FAILED_THUMBNAIL, system, ContentModel.TYPE_FAILED_THUMBNAIL).getChildRef();
|
||||
|
||||
// create an authentication object e.g. the user
|
||||
if(authenticationDAO.userExists(USER1_ANDY))
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.permissions.impl.acegi;
|
||||
|
||||
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
|
||||
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sf.acegisecurity.vote.AccessDecisionVoter;
|
||||
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ACLEntryVoterUtilsTest
|
||||
{
|
||||
private final NodeRef testNodeRef = new NodeRef("workspace://testNodeRef/testNodeRef");
|
||||
private final NodeRef rootNodeRef = new NodeRef("workspace://rootNodeRef/rootNodeRef");
|
||||
private final NodeRef refNodeForTestObject = new NodeRef("workspace://refNodeForTestObject/refNodeForTestObject");
|
||||
private final NodeRef childRefNode = new NodeRef("workspace://childRefNode/childRefNode");
|
||||
private final StoreRef testStoreNodeRef = new StoreRef("system://testStoreRefMock/testStoreRefMock");
|
||||
private final SimplePermissionReference simplePermissionReference = SimplePermissionReference.getPermissionReference(QName.createQName("uri", "local"), "Write");
|
||||
private final QName qNameToAbstain1 = QName.createQName("{test}testnode1");
|
||||
private final QName qNameToAbstain2 = QName.createQName("{test}testnode2");
|
||||
private final QName qNameToAbstain3 = QName.createQName("{test}testnode3");
|
||||
private final QName qNameNotFromTheAbstainSet = QName.createQName("{test}testnodeAbstain");
|
||||
private final Set<QName> qNamesToAbstain = Set.of(qNameToAbstain1, qNameToAbstain2, qNameToAbstain3);
|
||||
@Mock
|
||||
private PermissionService permissionServiceMock;
|
||||
@Mock
|
||||
private NodeService nodeServiceMock;
|
||||
@Mock
|
||||
private ChildAssociationRef childAssocRefMock;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.TRUE);
|
||||
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.TRUE);
|
||||
when(nodeServiceMock.getRootNode(testStoreNodeRef)).thenReturn(rootNodeRef);
|
||||
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameNotFromTheAbstainSet);
|
||||
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet));
|
||||
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.DENIED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsAccessDeniedFromPermissionService()
|
||||
{
|
||||
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||
is(AccessDecisionVoter.ACCESS_DENIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullOnNullTestObject()
|
||||
{
|
||||
assertThat(getNodeRef(null, nodeServiceMock), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test(expected = ACLEntryVoterException.class)
|
||||
public void throwsExceptionWhenParameterIsNotNodeRefOrChildAssociationRef()
|
||||
{
|
||||
getNodeRef("TEST", nodeServiceMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsGivenTestNodeRefWhenStoreRefDoesNotExist()
|
||||
{
|
||||
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.FALSE);
|
||||
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsRootNode()
|
||||
{
|
||||
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(rootNodeRef));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNodeRefFromTestObject()
|
||||
{
|
||||
assertThat(getNodeRef(refNodeForTestObject, nodeServiceMock), is(refNodeForTestObject));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsChildRefFromChildAssocRef()
|
||||
{
|
||||
when(childAssocRefMock.getChildRef()).thenReturn(childRefNode);
|
||||
assertThat(getNodeRef(childAssocRefMock, nodeServiceMock), is(childRefNode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullOnNullTestNodeRef()
|
||||
{
|
||||
assertThat(shouldAbstainOrDeny(simplePermissionReference, null, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||
is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullOnAbstainClassQnamesIsEmptyAndThereAreNoDeniedPermissions()
|
||||
{
|
||||
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
|
||||
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, Collections.emptySet(), nodeServiceMock, permissionServiceMock),
|
||||
is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullOnTestNodeRefDoesNotExistAndThereAreNoDeniedPermissions()
|
||||
{
|
||||
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.FALSE);
|
||||
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
|
||||
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||
is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullOnNodeTypeAndNodeAspectsAreNotInSetToAbstainAndThereAreNoDeniedPermissions()
|
||||
{
|
||||
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
|
||||
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||
is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsAbstainWhenNodeRefTypeIsInSetToAbstain()
|
||||
{
|
||||
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameToAbstain2);
|
||||
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||
is(AccessDecisionVoter.ACCESS_ABSTAIN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsAbstainWhenAtLeastOneAspectIsInSetToAbstain()
|
||||
{
|
||||
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet, qNameToAbstain3));
|
||||
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||
is(AccessDecisionVoter.ACCESS_ABSTAIN));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
mycustommessages.key1=This is a custom message
|
@@ -0,0 +1 @@
|
||||
mycustommessages.key1=Dies ist eine benutzerdefinierte Nachricht
|
@@ -0,0 +1 @@
|
||||
mycustommessages.key1=Ceci est un message personnalis\u00e9
|
Reference in New Issue
Block a user