/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This 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 2.1 of * the License, or (at your option) any later version. * * This software 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 this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.annotation.rights.internal; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.slf4j.Logger; import org.xwiki.annotation.Annotation; import org.xwiki.annotation.io.IOService; import org.xwiki.annotation.reference.TypedStringEntityReferenceResolver; import org.xwiki.annotation.rights.AnnotationRightService; import org.xwiki.component.annotation.Component; import org.xwiki.model.EntityType; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.DocumentReferenceResolver; import org.xwiki.model.reference.EntityReference; import org.xwiki.security.authorization.AuthorizationManager; import org.xwiki.security.authorization.Right; /** * Implementation of the rights service based on the XWiki access rights. * * @version $Id: 815d38c13f2c80058d521a59a9d1807368ffc299 $ * @since 2.3M1 */ @Component @Singleton public class XWikiAnnotationRightService implements AnnotationRightService { /** * Entity reference handler to resolve the reference target. <br> * TODO: should be a current reference resolver, to be fully correct, but for the moment it will be a default one, * since current resolver does not exist in 2.1.1 and a current typed resolver would fail. Plus, all references * passed to this service should be absolute. */ @Inject private TypedStringEntityReferenceResolver referenceResolver; /** * The annotations storage service, used to retrieve information about annotations to check the rights on it. */ @Inject private IOService annotationsStorageService; @Inject private AuthorizationManager authorization; @Inject @Named("user/current") private DocumentReferenceResolver<String> userAndGroupReferenceResolver; /** * The logger to log. */ @Inject private Logger logger; @Override public boolean canAddAnnotation(String target, String userName) { // if the user has comment right on the document represented by the target return this.authorization.hasAccess(Right.COMMENT, getUserReference(userName), getDocumentReference(target)); } @Override public boolean canEditAnnotation(String annotationId, String target, String userName) { // if the user has edit right on the document represented by the target, or is the author of the annotation try { boolean hasEditRight = this.authorization.hasAccess(Right.EDIT, getUserReference(userName), getDocumentReference(target)); if (hasEditRight) { return true; } // check if it's the author of the annotation Annotation ann = annotationsStorageService.getAnnotation(target, annotationId); return ann != null && ann.getAuthor().equals(userName); } catch (Exception e) { logException(e, target, userName); return false; } } @Override public boolean canViewAnnotatedTarget(String target, String userName) { return canViewAnnotations(target, userName); } @Override public boolean canViewAnnotations(String target, String userName) { // if user can view the target, it should be able to view annotations on it return this.authorization.hasAccess(Right.VIEW, getUserReference(userName), getDocumentReference(target)); } /** * Helper method to parse the target as a reference and extract a serialized document reference from it: the * document reference serialized if the target can be parsed as a typed reference, or the initial string itself * otherwise. * * @param target the serialized reference to target to extract the document reference from * @return the serialized reference to the document to which the target refers */ private EntityReference getDocumentReference(String target) { EntityReference ref = this.referenceResolver.resolve(target, EntityType.DOCUMENT); return ref.extractReference(EntityType.DOCUMENT); } private DocumentReference getUserReference(String username) { return this.userAndGroupReferenceResolver.resolve(username); } /** * Helper method to log an xwiki exception during rights checking process. * * @param e exception to log * @param target the annotation target for which exception has occurred * @param user the user name for which exception occurred on verification */ private void logException(Exception e, String target, String user) { this.logger.warn("Couldn't get access rights for the target [{}] for user [{}]", target, user, e); } }