Skip to content

Instantly share code, notes, and snippets.

@CodeOfficer
Forked from pfiadDi/firestore.rules
Created September 1, 2021 16:08
Show Gist options
  • Save CodeOfficer/2e5cadd59ee65f08a69d119086a0ee53 to your computer and use it in GitHub Desktop.
Save CodeOfficer/2e5cadd59ee65f08a69d119086a0ee53 to your computer and use it in GitHub Desktop.
Firestore Advanced Security Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAuthenticated() {
return request.auth != null;
}
function isDefined(field) {
return field in request.resource.data
}
function val(field) {
return request.resource.data[field];
}
function isString(field) {
return string(val(field)) == val(field);
}
function isInt(field) {
return int(val(field)) == val(field);
}
function isIntWithValue(value) {
return int(value) == value;
}
function hasTimestampKeys(field) {
return request.resource.data[field].keys().hasOnly(['nanoseconds','seconds'])
}
function isTimestamp(field) {
return correctSizeField(2, field) && hasTimestampKeys(field) && isIntWithValue(request.resource.data[field].seconds) && isIntWithValue(request.resource.data[field].nanoseconds)
}
function isCreatingStatusObject(field) {
return isNotCreatingStatusError(field) || isCreatingStatusError(field);
}
function isNotCreatingStatusError(field) {
return correctSizeField(1, field) && request.resource.data[field].keys().hasOnly(['status']) && isCreatingStatus(request.resource.data[field].status)
}
function isCreatingStatusError(field) {
return correctSizeField(2, field) && request.resource.data[field].keys().hasOnly(['status','error']) && isCreatingStatus(request.resource.data[field]['status'])
}
function isValidAuthUid() {
return request.auth.uid == request.resource.data.uid;
}
function correctSize(no) {
return request.resource.data.size() == no;
}
function correctSizeField(no,field) {
return request.resource.data[field].size() == no;
}
function isCreatingStatus(value) {
return value in ['Drafting','Request','Success','CreatingFailed'];
}
function isCorrectStatus(value) {
return value in ['Draft','Active','Paused','Ended'];
}
function isCorrectPhrasing(value) {
return value in ['WithoutArticle','FemaleArticle','MaleArticle','NoneChosen'];
}
function isOwner(uid) {
return uid in request.resource.data.owners;
}
function isOwnerUpdate(uid) {
return uid in resource.data.owners;
}
function onlyAllowedFields() {
return request.resource.data.keys().hasOnly(['name','status','participants','endDate','startDate','companyName','owners', 'phrasing','creatingStatus'])
}
match /surveys/{surveyId} {
allow create: if isAuthenticated() && isDefined('name') && isString('name') && isDefined('status') && isDefined('participants') && isInt('participants') && isDefined('endDate') && isTimestamp('endDate') && isDefined('startDate') && isTimestamp('startDate') && isDefined('companyName') && isString('companyName') && isDefined('status') && isCorrectStatus(val('status')) && isDefined('owners') && isOwner(request.auth.uid) && onlyAllowedFields() && isDefined('phrasing') && isCorrectPhrasing(val('phrasing')) && isDefined('creatingStatus') && isCreatingStatusObject('creatingStatus');
allow update: if isAuthenticated() && isDefined('name') && isString('name') && isDefined('status') && isDefined('participants') && isInt('participants') && isDefined('endDate') && isTimestamp('endDate') && isDefined('startDate') && isTimestamp('startDate') && isDefined('companyName') && isString('companyName') && isDefined('status') && isCorrectStatus(val('status')) && isDefined('owners') && isOwnerUpdate(request.auth.uid) && onlyAllowedFields() && isDefined('phrasing') && isCorrectPhrasing(val('phrasing')) && isDefined('creatingStatus') && isCreatingStatusObject('creatingStatus');
allow read: if isAuthenticated();
}
match /surveys/{surveyId}/reports/{reportId} {
allow write: if false;
allow read: if isAuthenticated();
}
match /surveys/{surveyId}/introduction/{introductionId} {
allow write: if false;
allow read: if isAuthenticated();
}
match /surveys/{surveyId}/traits/{traitsId} {
allow write: if false;
allow read: if isAuthenticated();
}
match /surveys/{surveyId}/end/{endId} {
allow write: if false;
allow read: if isAuthenticated();
}
match /surveys/{surveyId}/answers/{answerId} {
function surveyData() {
return get(/databases/$(database)/documents/surveys/$(surveyId)).data;
}
function isActive() {
return request.time >= surveyData().startDate && request.time <= surveyData().endDate
}
allow create: if isAuthenticated() && isValidAuthUid() && isDefined('uid') && isString('uid') && correctSize(6) && (request.time >= get(/databases/$(database)/documents/surveys/$(surveyId)).data.startDate && request.time <= get(/databases/$(database)/documents/surveys/$(surveyId)).data.endDate);
allow update: if false;
allow read: if isAuthenticated();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment