Skip to content

Commit

Permalink
feat: limit rest and client access to private project
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Eng committed Sep 15, 2017
1 parent 42efdc2 commit 197d22c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 51 deletions.
Expand Up @@ -10,11 +10,14 @@

import org.apache.commons.lang.StringUtils;
import org.hibernate.Session;

import javax.inject.Inject;
import javax.inject.Named;

import org.zanata.dao.DocumentDAO;
import org.zanata.model.HDocument;
import org.zanata.model.HLocale;
import org.zanata.model.HProject;
import org.zanata.model.HProjectIteration;
import org.zanata.model.po.HPoHeader;
import org.zanata.rest.NoSuchEntityException;
Expand All @@ -32,45 +35,35 @@ public class ETagUtils implements Serializable {
@Inject
private DocumentDAO documentDAO;

@Inject
private RestSlugValidator restSlugValidator;

/**
* Retrieves the ETag for the Project
*
* <p>
* This algorithm takes into account changes in Project Iterations as well.
*
* @param slug
* Project slug
* @param slug Project slug
* @return calculated EntityTag
* @throws NoSuchEntityException
* if project is obsolete or does not exist
* @throws NoSuchEntityException if project is obsolete or does not exist
*/
public EntityTag generateTagForProject(String slug) {
Integer projectVersion =
(Integer) session
.createQuery(
"select p.versionNum from HProject p where slug =:slug "
+ "and status not in (:statusList)")
.setParameter("slug", slug)
.setParameterList("statusList",
new Object[] { OBSOLETE })
.setComment("ETagUtils.generateTagForProject-project")
.uniqueResult();

if (projectVersion == null)
throw new NoSuchEntityException("Project '" + slug + "' not found.");

HProject project =
restSlugValidator.retrieveAndCheckProject(slug, false);
@SuppressWarnings("unchecked")
List<Integer> iterationVersions =
session.createQuery(
"select i.versionNum from HProjectIteration i "
+ "where i.project.slug =:slug and status not in (:statusList)")
+
"where i.project.slug =:slug and status not in (:statusList)")
.setParameter("slug", slug)
.setParameterList("statusList",
new Object[] { OBSOLETE })
new Object[]{ OBSOLETE })
.setComment("ETagUtils.generateTagForProject-iteration")
.list();

String hash =
HashUtil.generateHash(projectVersion + ':'
HashUtil.generateHash(project.getVersionNum() + ':'
+ StringUtils.join(iterationVersions, ':'));

return EntityTag.valueOf(hash);
Expand All @@ -79,32 +72,17 @@ public EntityTag generateTagForProject(String slug) {
/**
* Retrieves the ETag for the ProjectIteration
*
* @param projectSlug
* project slug
* @param iterationSlug
* iteration slug
* @param projectSlug project slug
* @param iterationSlug iteration slug
* @return calculated EntityTag
* @throw NoSuchEntityException if iteration is obsolete or does not exist
*/
public EntityTag generateETagForIteration(String projectSlug,
String iterationSlug) {
Integer iterationVersion =
(Integer) session
.createQuery(
"select i.versionNum from HProjectIteration i where i.slug =:islug and i.project.slug =:pslug "
+ "and status not in (:statusList) and i.project.status not in (:statusList)")
.setParameter("islug", iterationSlug)
.setParameter("pslug", projectSlug)
.setParameterList("statusList",
new Object[] { OBSOLETE })
.setComment("ETagUtils.generateETagForIteration")
.uniqueResult();

if (iterationVersion == null)
throw new NoSuchEntityException("Project Iteration '"
+ iterationSlug + "' not found.");
HProjectIteration version = restSlugValidator
.retrieveAndCheckIteration(projectSlug, iterationSlug, false);

String hash = HashUtil.generateHash(String.valueOf(iterationVersion));
String hash = HashUtil.generateHash(String.valueOf(version.getVersionNum()));

return EntityTag.valueOf(hash);
}
Expand Down Expand Up @@ -134,7 +112,7 @@ public EntityTag generateETagForTranslatedDocument(
HProjectIteration iteration, String docId, HLocale locale) {
String stateHash =
documentDAO.getTranslatedDocumentStateHash(iteration
.getProject().getSlug(), iteration.getSlug(), docId,
.getProject().getSlug(), iteration.getSlug(), docId,
locale);
return EntityTag.valueOf(stateHash);
}
Expand Down
Expand Up @@ -35,6 +35,7 @@
import org.zanata.model.HProjectIteration;
import org.zanata.rest.NoSuchEntityException;
import org.zanata.rest.ReadOnlyEntityException;
import org.zanata.security.ZanataIdentity;
import org.zanata.service.LocaleService;

import java.io.Serializable;
Expand All @@ -56,13 +57,16 @@ public class RestSlugValidator implements Serializable {
private ProjectDAO projectDAO;
@Inject
private ProjectIterationDAO projectIterationDAO;
@Inject
private ZanataIdentity identity;

@Nonnull
public HProject retrieveAndCheckProject(@Nonnull String projectSlug,
boolean requiresWriteAccess) {
HProject hProject = projectDAO.getBySlug(projectSlug);
if (hProject == null
|| hProject.getStatus().equals(EntityStatus.OBSOLETE)) {
|| !haveReadAccess(hProject) ||
hProject.getStatus().equals(EntityStatus.OBSOLETE)) {
throw new NoSuchEntityException(
"Project \'" + projectSlug + "\' not found.");
}
Expand All @@ -76,8 +80,6 @@ public HProject retrieveAndCheckProject(@Nonnull String projectSlug,

/**
* @param requiresWriteAccess
* @return
* @see ProjectService#retrieveAndCheckProject
*/
@Nonnull
public HProjectIteration retrieveAndCheckIteration(
Expand All @@ -87,8 +89,8 @@ public HProjectIteration retrieveAndCheckIteration(
retrieveAndCheckProject(projectSlug, requiresWriteAccess);
HProjectIteration hProjectIteration =
projectIterationDAO.getBySlug(hProject, iterationSlug);
if (hProjectIteration == null || hProjectIteration.getStatus()
.equals(EntityStatus.OBSOLETE)) {
if (hProjectIteration == null || !haveReadAccess(hProjectIteration) ||
hProjectIteration.getStatus().equals(EntityStatus.OBSOLETE)) {
throw new NoSuchEntityException("Project Iteration \'" + projectSlug
+ ":" + iterationSlug + "\' not found.");
}
Expand Down Expand Up @@ -146,4 +148,21 @@ public HLocale validateTargetLocale(@Nonnull LocaleId locale,
throw e;
}
}

/**
* Check if current user have read access to the project version
* (checking for private project)
*/
public boolean haveReadAccess(HProjectIteration version) {
return identity.hasPermission(version, "read");
}

/**
* Check if current user have read access to the project
* (checking for private project)
*/
public boolean haveReadAccess(HProject project) {
return identity.hasPermission(project, "read");
}

}
Expand Up @@ -387,10 +387,12 @@ public Response putResourceMetaWithDocId(ResourceMeta messageBody,
if (hProjectIteration == null) {
throw new NoSuchEntityException("Project Iteration \'" + projectSlug
+ ":" + iterationSlug + "\' not found.");
} else if (hProjectIteration.getStatus().equals(EntityStatus.OBSOLETE)
} else if (!haveReadAccess(hProjectIteration) ||
hProjectIteration.getStatus().equals(EntityStatus.OBSOLETE)
|| hProject.getStatus().equals(EntityStatus.OBSOLETE)) {
throw new NoSuchEntityException("Project Iteration \'" + projectSlug
+ ":" + iterationSlug + "\' not found.");
throw new NoSuchEntityException(
"Project Iteration \'" + projectSlug
+ ":" + iterationSlug + "\' not found.");
} else if (writeOperation) {
if (hProjectIteration.getStatus().equals(EntityStatus.READONLY)
|| hProject.getStatus().equals(EntityStatus.READONLY)) {
Expand Down Expand Up @@ -424,4 +426,12 @@ private HLocale validateTargetLocale(LocaleId locale, String projectSlug,
public HProjectIteration getSecuredIteration() {
return retrieveAndCheckIteration(false);
}

/**
* Check if current user have read access to the project
* (checking for private project)
*/
public boolean haveReadAccess(HProjectIteration version) {
return identity.hasPermission(version, "read");
}
}

0 comments on commit 197d22c

Please sign in to comment.