Skip to content

Commit 73aef96

Browse files
pjeanjeanmichitux
authored andcommitted
XWIKI-21411: Improve check of translation document author rights
* Check both author and content author and improve JavaDoc (cherry picked from commit c4c8d61)
1 parent 915fe68 commit 73aef96

File tree

4 files changed

+310
-14
lines changed

4 files changed

+310
-14
lines changed

xwiki-platform-core/xwiki-platform-localization/xwiki-platform-localization-sources/xwiki-platform-localization-source-wiki/src/main/java/org/xwiki/localization/wiki/internal/AbstractDocumentTranslationBundle.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,39 +138,57 @@ protected void setReference(DocumentReference reference)
138138
setId(this.idPrefix + this.serializer.serialize(reference));
139139
}
140140

141-
protected LocalizedTranslationBundle loadDocumentLocaleBundle(Locale locale) throws Exception
141+
/**
142+
* Gets the document that defines the translation bundle for a given locale.
143+
*
144+
* @param locale the requested locale
145+
* @return the document defining the translation bundle, or null if it could not be fetched yet and requires a retry
146+
*/
147+
protected XWikiDocument getDocumentLocaleBundle(Locale locale) throws Exception
142148
{
143149
XWikiContext context = this.contextProvider.get();
144150

145151
if (context == null) {
146-
// No context for some reason, lets try later
152+
// No context for some reason, let's try later.
147153
return null;
148154
}
149155

150156
XWiki xwiki = context.getWiki();
151157

152158
if (xwiki == null) {
153-
// No XWiki instance ready, lets try later
159+
// No XWiki instance ready, let's try later.
154160
return null;
155161
}
156162

157163
XWikiDocument document = xwiki.getDocument(this.documentReference, context);
158164

159165
if (locale != null && !locale.equals(Locale.ROOT) && !locale.equals(document.getDefaultLocale())) {
160166
document = xwiki.getDocument(new DocumentReference(document.getDocumentReference(), locale), context);
167+
}
161168

162-
if (document.isNew()) {
163-
// No document found for this locale
164-
return LocalizedTranslationBundle.EMPTY;
165-
}
169+
return document;
170+
}
171+
172+
protected LocalizedTranslationBundle loadDocumentLocaleBundle(Locale locale) throws Exception
173+
{
174+
XWikiDocument document = getDocumentLocaleBundle(locale);
175+
176+
if (document == null) {
177+
// Either no context or XWiki instance not ready, let's try later.
178+
return null;
179+
}
180+
181+
if (document.isNew()) {
182+
// No document found for this locale.
183+
return LocalizedTranslationBundle.EMPTY;
166184
}
167185

168186
String content = document.getContent();
169187

170188
Properties properties = new Properties();
171189
properties.load(new StringReader(content));
172190

173-
// Convert to LocalBundle
191+
// Convert to LocalBundle.
174192
DefaultLocalizedTranslationBundle localeBundle = new DefaultLocalizedTranslationBundle(this, locale);
175193

176194
TranslationMessageParser parser = getTranslationMessageParser();

xwiki-platform-core/xwiki-platform-localization/xwiki-platform-localization-sources/xwiki-platform-localization-source-wiki/src/main/java/org/xwiki/localization/wiki/internal/ComponentDocumentTranslationBundle.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
*/
2020
package org.xwiki.localization.wiki.internal;
2121

22+
import java.util.Locale;
23+
2224
import org.xwiki.bridge.event.WikiDeletedEvent;
2325
import org.xwiki.component.descriptor.ComponentDescriptor;
2426
import org.xwiki.component.manager.ComponentLookupException;
@@ -27,6 +29,11 @@
2729
import org.xwiki.localization.message.TranslationMessageParser;
2830
import org.xwiki.model.reference.DocumentReference;
2931
import org.xwiki.observation.event.Event;
32+
import org.xwiki.security.authorization.AccessDeniedException;
33+
34+
import com.xpn.xwiki.XWiki;
35+
import com.xpn.xwiki.XWikiContext;
36+
import com.xpn.xwiki.doc.XWikiDocument;
3037

3138
/**
3239
* Component wiki document based implementation of Bundle.
@@ -37,6 +44,8 @@
3744
*/
3845
public class ComponentDocumentTranslationBundle extends AbstractDocumentTranslationBundle
3946
{
47+
private DocumentTranslationBundleFactory factory;
48+
4049
private ComponentDescriptor<TranslationBundle> descriptor;
4150

4251
/**
@@ -45,17 +54,54 @@ public class ComponentDocumentTranslationBundle extends AbstractDocumentTranslat
4554
* @param componentManager used to lookup components needed to manipulate wiki documents
4655
* @param translationMessageParser the parser to use for each message
4756
* @param descriptor the component descriptor used to unregister the bundle
57+
* @param factory the factory
4858
* @throws ComponentLookupException failed to lookup some required components
4959
*/
5060
public ComponentDocumentTranslationBundle(String idPrefix, DocumentReference documentReference,
5161
ComponentManager componentManager, TranslationMessageParser translationMessageParser,
52-
ComponentDescriptor<TranslationBundle> descriptor) throws ComponentLookupException
62+
ComponentDescriptor<TranslationBundle> descriptor, DocumentTranslationBundleFactory factory)
63+
throws ComponentLookupException
5364
{
5465
super(idPrefix, documentReference, componentManager, translationMessageParser);
5566

67+
this.factory = factory;
5668
this.descriptor = descriptor;
5769
}
5870

71+
/**
72+
* {@inheritDoc}
73+
* This overrides the default implementation to first check the author rights for the document.
74+
*
75+
* @param locale the requested locale
76+
* @return the document defining the translation bundle if its author has the necessary rights, the default locale
77+
* otherwise, and fallback on the original implementation if the document doesn't exist or could not be fetched
78+
*/
79+
@Override
80+
protected XWikiDocument getDocumentLocaleBundle(Locale locale) throws Exception
81+
{
82+
XWikiDocument document = super.getDocumentLocaleBundle(locale);
83+
84+
if (document != null && !document.isNew()) {
85+
XWikiContext context = this.contextProvider.get();
86+
XWiki xwiki = context.getWiki();
87+
XWikiDocument defaultLocaleDocument = xwiki.getDocument(this.documentReference, context);
88+
89+
if (defaultLocaleDocument != document) {
90+
// We only need to check rights for non-default locales.
91+
try {
92+
this.factory.checkRegistrationAuthorizationForDocumentLocaleBundle(document, defaultLocaleDocument);
93+
} catch (AccessDeniedException e) {
94+
this.logger.warn("Failed to load and register the translation for locale [{}] from document [{}]. "
95+
+ "Falling back to default locale.", locale, document.getDocumentReference());
96+
// We return the default translation bundle if the requested one has permission issues.
97+
return defaultLocaleDocument;
98+
}
99+
}
100+
}
101+
102+
return document;
103+
}
104+
59105
@Override
60106
public void onEvent(Event event, Object source, Object data)
61107
{

xwiki-platform-core/xwiki-platform-localization/xwiki-platform-localization-sources/xwiki-platform-localization-source-wiki/src/main/java/org/xwiki/localization/wiki/internal/DocumentTranslationBundleFactory.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.xwiki.localization.wiki.internal.TranslationDocumentModel.Scope;
5757
import org.xwiki.model.reference.DocumentReference;
5858
import org.xwiki.model.reference.DocumentReferenceResolver;
59+
import org.xwiki.model.reference.EntityReference;
5960
import org.xwiki.model.reference.EntityReferenceSerializer;
6061
import org.xwiki.model.reference.WikiReference;
6162
import org.xwiki.observation.EventListener;
@@ -324,7 +325,7 @@ private ComponentDocumentTranslationBundle createComponentDocumentBundle(XWikiDo
324325
try {
325326
documentBundle =
326327
new ComponentDocumentTranslationBundle(ID_PREFIX, document.getDocumentReference(),
327-
this.componentManagerProvider.get(), this.translationParser, descriptor);
328+
this.componentManagerProvider.get(), this.translationParser, descriptor, this);
328329
} catch (ComponentLookupException e) {
329330
throw new TranslationBundleDoesNotExistsException("Failed to create document bundle", e);
330331
}
@@ -434,6 +435,23 @@ private void registerTranslationBundle(XWikiDocument document) throws Translatio
434435
}
435436
}
436437

438+
/**
439+
* Checks that the author of a document defining a translation bundle has the necessary rights to make it
440+
* available, based on the scope of the default locale translation bundle.
441+
*
442+
* @param document the document defining the translation bundle to check
443+
* @param defaultLocaleDocument the document containing the default locale translation bundle
444+
* @throws AccessDeniedException when the document author does not have enough rights for the defined scope
445+
*/
446+
protected void checkRegistrationAuthorizationForDocumentLocaleBundle(XWikiDocument document,
447+
XWikiDocument defaultLocaleDocument) throws AccessDeniedException
448+
{
449+
Scope scope = getScope(defaultLocaleDocument);
450+
if (scope != null && scope != Scope.ON_DEMAND) {
451+
checkRegistrationAuthorization(document, scope);
452+
}
453+
}
454+
437455
/**
438456
* @param document the translation document
439457
* @param scope the scope
@@ -442,18 +460,24 @@ private void registerTranslationBundle(XWikiDocument document) throws Translatio
442460
*/
443461
private void checkRegistrationAuthorization(XWikiDocument document, Scope scope) throws AccessDeniedException
444462
{
463+
EntityReference entityReference;
445464
switch (scope) {
446465
case GLOBAL:
447466
this.authorizationManager.checkAccess(Right.PROGRAM, document.getAuthorReference(), null);
467+
this.authorizationManager.checkAccess(Right.PROGRAM, document.getContentAuthorReference(), null);
448468
break;
449469
case WIKI:
450-
this.authorizationManager.checkAccess(Right.ADMIN, document.getAuthorReference(), document
451-
.getDocumentReference().getWikiReference());
470+
entityReference = document.getDocumentReference().getWikiReference();
471+
this.authorizationManager.checkAccess(Right.ADMIN, document.getAuthorReference(), entityReference);
472+
this.authorizationManager.checkAccess(Right.ADMIN, document.getContentAuthorReference(),
473+
entityReference);
452474
break;
453475
case USER:
454476
if (this.configuration.isRestrictUserTranslations()) {
455-
this.authorizationManager.checkAccess(Right.SCRIPT, document.getAuthorReference(),
456-
document.getDocumentReference());
477+
entityReference = document.getDocumentReference();
478+
this.authorizationManager.checkAccess(Right.SCRIPT, document.getAuthorReference(), entityReference);
479+
this.authorizationManager.checkAccess(Right.SCRIPT, document.getContentAuthorReference(),
480+
entityReference);
457481
}
458482
break;
459483
default:

0 commit comments

Comments
 (0)