53c79f41a3
* Harden Firestore fold update rule This prevents editing fields on the fold that would lead to strange and disruptive results, for example, changing the curatorId to another user, or manually changing followCount. * Harden Firestore follower update rule This prevents users from creating follower entries with the userId of someone else, which would effectively subscribe that person to the fold. * Harden Firestore comment posting rule This prevents people from posting comments with inauthentic user information. * Fix silly bugs in comment rules I made
81 lines
2.7 KiB
Plaintext
81 lines
2.7 KiB
Plaintext
rules_version = '2';
|
|
|
|
// To deploy: `firebase deploy --only firestore:rules`
|
|
service cloud.firestore {
|
|
match /databases/{database}/documents {
|
|
|
|
function isAdmin() {
|
|
return request.auth.uid == 'igi2zGXsfxYPgB0DJTXVJVmwCOr2' // Austin
|
|
|| request.auth.uid == '5LZ4LgYuySdL1huCWe7bti02ghx2' // James
|
|
|| request.auth.uid == 'tlmGNz9kjXc2EteizMORes4qvWl2' // Stephen
|
|
|| request.auth.uid == 'IPTOzEqrpkWmEzh6hwvAyY9PqFb2' // Manifold
|
|
}
|
|
|
|
match /users/{userId} {
|
|
allow read;
|
|
allow update: if resource.data.id == request.auth.uid
|
|
&& request.resource.data.diff(resource.data).affectedKeys()
|
|
.hasOnly(['bio', 'bannerUrl', 'website', 'twitterHandle', 'discordHandle']);
|
|
}
|
|
|
|
match /private-users/{userId} {
|
|
allow read: if resource.data.id == request.auth.uid || isAdmin();
|
|
}
|
|
|
|
match /private-users/{userId}/views/{viewId} {
|
|
allow create: if userId == request.auth.uid;
|
|
}
|
|
|
|
match /private-users/{userId}/events/{eventId} {
|
|
allow create: if userId == request.auth.uid;
|
|
}
|
|
|
|
match /private-users/{userId}/latency/{loadTimeId} {
|
|
allow create: if userId == request.auth.uid;
|
|
}
|
|
|
|
match /contracts/{contractId} {
|
|
allow read;
|
|
allow update: if request.resource.data.diff(resource.data).affectedKeys()
|
|
.hasOnly(['description', 'closeTime', 'tags', 'lowercaseTags']);
|
|
allow update: if isAdmin();
|
|
}
|
|
|
|
match /{somePath=**}/bets/{betId} {
|
|
allow read;
|
|
}
|
|
|
|
function commentMatchesUser(userId, comment) {
|
|
// it's a bad look if someone can impersonate other ids/names/avatars so check everything
|
|
let user = get(/databases/$(database)/documents/users/$(userId));
|
|
return comment.userId == userId
|
|
&& comment.userName == user.data.name
|
|
&& comment.userUsername == user.data.username
|
|
&& comment.userAvatarUrl == user.data.avatarUrl;
|
|
}
|
|
|
|
match /{somePath=**}/comments/{commentId} {
|
|
allow read;
|
|
allow create: if request.auth != null && commentMatchesUser(request.auth.uid, request.resource.data);
|
|
}
|
|
|
|
match /{somePath=**}/answers/{answerId} {
|
|
allow read;
|
|
}
|
|
|
|
match /folds/{foldId} {
|
|
allow read;
|
|
allow update: if request.auth.uid == resource.data.curatorId
|
|
&& request.resource.data.diff(resource.data).affectedKeys()
|
|
.hasOnly(['name', 'about', 'tags', 'lowercaseTags']);
|
|
allow delete: if request.auth.uid == resource.data.curatorId;
|
|
}
|
|
|
|
match /{somePath=**}/followers/{userId} {
|
|
allow read;
|
|
allow create, update: if request.auth.uid == userId && request.resource.data.userId == userId;
|
|
allow delete: if request.auth.uid == userId;
|
|
}
|
|
}
|
|
}
|