Skip to content

Commit

Permalink
Use owner id when writing and authenticating LOIs and submissions (#1951
Browse files Browse the repository at this point in the history
)
  • Loading branch information
gino-m authored Aug 9, 2024
1 parent cf653ce commit 17883b9
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 11 deletions.
23 changes: 14 additions & 9 deletions firestore/firestore.rules
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,17 @@
}
/**
* Returns true iff the user with the provided email created the specified resource.
* Returns true iff the current user is the owner of the specified LOI.
*/
function isCreator(resource) {
// TODO(#1154): Make `owner` its own field and stop assuming `creator==owner`.
return resource.data.created.user.email == request.auth.token.email;
function isLoiOwner(loi) {
return loi.data['5'] == request.auth.uid;
}
/**
* Returns true iff the current user is the owner of the specified submission.
*/
function isSubmissionOwner(submission) {
return submission.data['5'] == request.auth.uid;
}
// Allow users to read, create, and write their own profiles in the db.
Expand Down Expand Up @@ -138,20 +144,19 @@
// Allow if user has has read access to the survey.
allow read: if canViewSurvey(getSurvey(surveyId));
// Allow if user is owner of the new LOI and can collect data.
// TODO(#1154): Require owner as well.
allow create: if canCollectData(getSurvey(surveyId));
allow create: if isLoiOwner(request.resource) && canCollectData(getSurvey(surveyId));
// Allow if user is owner of the existing LOI or can manage survey.
allow write: if isCreator(resource) || canManageSurvey(getSurvey(surveyId));
allow write: if isLoiOwner(resource) || canManageSurvey(getSurvey(surveyId));
}
// Apply passlist and survey-level ACLs to submission documents.
match /surveys/{surveyId}/submissions/{submissionId} {
// Allow if user has has read access to the survey.
allow read: if canViewSurvey(getSurvey(surveyId));
// Allow if user is owner of the new submission and can collect data.
allow create: if isCreator(request.resource) && canCollectData(getSurvey(surveyId));
allow create: if isSubmissionOwner(request.resource) && canCollectData(getSurvey(surveyId));
// Allow if user is owner of the existing submission or can manage survey.
allow write: if isCreator(resource) || canManageSurvey(getSurvey(surveyId));
allow write: if isSubmissionOwner(resource) || canManageSurvey(getSurvey(surveyId));
}
// Apply passlist and survey-level ACLs to job documents.
Expand Down
13 changes: 11 additions & 2 deletions functions/src/import-geojson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export function importGeoJsonCallback(

const db = getDatastore();

const ownerId = user.uid;

// This code will process each file uploaded.
busboy.on('file', async (_field, file, _filename) => {
const {survey: surveyId, job: jobId} = params;
Expand Down Expand Up @@ -101,7 +103,9 @@ export function importGeoJsonCallback(
return;
}
try {
const data = toDocumentData(toLoiPb(geoJsonLoi as Feature, jobId));
const data = toDocumentData(
toLoiPb(geoJsonLoi as Feature, jobId, ownerId)
);
const loi = {
...data,
...geoJsonToLoiLegacy(geoJsonLoi, jobId),
Expand Down Expand Up @@ -169,12 +173,17 @@ function geoJsonToLoiLegacy(geoJsonLoi: Feature, jobId: string): DocumentData {
* Convert the provided GeoJSON LocationOfInterest and jobId into a
* LocationOfInterest for insertion into the data store.
*/
function toLoiPb(feature: Feature, jobId: string): Pb.LocationOfInterest {
function toLoiPb(
feature: Feature,
jobId: string,
ownerId: string
): Pb.LocationOfInterest {
// TODO: Add created/modified metadata.
const {id, geometry, properties} = feature;
const geometryPb = toGeometryPb(geometry);
return new Pb.LocationOfInterest({
jobId,
ownerId,
customTag: id?.toString(),
source: Pb.LocationOfInterest.Source.IMPORTED,
geometry: geometryPb,
Expand Down

0 comments on commit 17883b9

Please sign in to comment.