* Send out email template for 3 trending markets * Rich text to plaintext descriptions, other ui changes * Lint * Filter for closed markets * Change sign * First order must be closeTime * Send 6 emails, check flag twice * Exclude contracts with trump and president in the name * interesting markets email * sendInterestingMarketsEmail * Change subject line back Co-authored-by: mantikoros <sgrugett@gmail.com>
		
			
				
	
	
		
			173 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| rules_version = '2';
 | |
| 
 | |
| // To pick the right project: `firebase projects:list`, then `firebase use <project-name>`
 | |
| // To deploy: `firebase deploy --only firestore:rules`
 | |
| service cloud.firestore {
 | |
|   match /databases/{database}/documents {
 | |
| 
 | |
|     function isAdmin() {
 | |
|       return request.auth.token.email in [
 | |
|         'akrolsmir@gmail.com',
 | |
|         'jahooma@gmail.com',
 | |
|         'taowell@gmail.com',
 | |
|         'manticmarkets@gmail.com'
 | |
|       ]
 | |
|     }
 | |
| 
 | |
|     match /stats/stats {
 | |
|       allow read;
 | |
|     }
 | |
| 
 | |
|     match /users/{userId} {
 | |
|       allow read;
 | |
|       allow update: if userId == request.auth.uid
 | |
|                        && request.resource.data.diff(resource.data).affectedKeys()
 | |
|                                                                     .hasOnly(['bio', 'bannerUrl', 'website', 'twitterHandle', 'discordHandle', 'followedCategories', 'lastPingTime','shouldShowWelcome']);
 | |
|       // User referral rules
 | |
|       allow update: if userId == request.auth.uid
 | |
|                          && request.resource.data.diff(resource.data).affectedKeys()
 | |
|                           .hasOnly(['referredByUserId', 'referredByContractId', 'referredByGroupId'])
 | |
|                           // only one referral allowed per user
 | |
|                           && !("referredByUserId" in resource.data)
 | |
|                           // user can't refer themselves
 | |
|                           && !(userId == request.resource.data.referredByUserId);
 | |
|                           // quid pro quos enabled (only once though so nbd) - bc I can't make this work:
 | |
|                           // && (get(/databases/$(database)/documents/users/$(request.resource.data.referredByUserId)).referredByUserId == resource.data.id);
 | |
|     }
 | |
| 
 | |
|   	match /{somePath=**}/portfolioHistory/{portfolioHistoryId} {
 | |
|       allow read;
 | |
|     }
 | |
| 
 | |
|     match /{somePath=**}/challenges/{challengeId}{
 | |
|       allow read;
 | |
|     }
 | |
| 
 | |
|     match /contracts/{contractId}/challenges/{challengeId}{
 | |
|       allow read;
 | |
|       allow create: if request.auth.uid == request.resource.data.creatorId;
 | |
|       // allow update if there have been no claims yet and if the challenge is still open
 | |
|       allow update: if request.auth.uid == resource.data.creatorId;
 | |
|     }
 | |
| 
 | |
|     match /users/{userId}/follows/{followUserId} {
 | |
|       allow read;
 | |
|       allow write: if request.auth.uid == userId;
 | |
|     }
 | |
| 
 | |
|     match /{somePath=**}/follows/{followUserId} {
 | |
|       allow read;
 | |
|     }
 | |
| 
 | |
|     match /private-users/{userId} {
 | |
|       allow read: if userId == request.auth.uid || isAdmin();
 | |
|       allow update: if (userId == request.auth.uid || isAdmin())
 | |
|                        && request.resource.data.diff(resource.data).affectedKeys()
 | |
|                        .hasOnly(['apiKey', 'unsubscribedFromResolutionEmails', 'unsubscribedFromCommentEmails', 'unsubscribedFromAnswerEmails', 'notificationPreferences', 'unsubscribedFromWeeklyTrendingEmails' ]);
 | |
|     }
 | |
| 
 | |
|     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 /private-users/{userId}/cache/{docId} {
 | |
|       allow read: if userId == request.auth.uid || isAdmin();
 | |
|     }
 | |
| 
 | |
|     match /contracts/{contractId} {
 | |
|       allow read;
 | |
|       allow update: if request.resource.data.diff(resource.data).affectedKeys()
 | |
|                                                                  .hasOnly(['tags', 'lowercaseTags', 'groupSlugs', 'groupLinks']);
 | |
|       allow update: if request.resource.data.diff(resource.data).affectedKeys()
 | |
|                                                                  .hasOnly(['description', 'closeTime', 'question'])
 | |
|                        && resource.data.creatorId == request.auth.uid;
 | |
|       allow update: if isAdmin();
 | |
|           match /comments/{commentId} {
 | |
|             allow create: if request.auth != null && commentMatchesUser(request.auth.uid, request.resource.data);
 | |
|           }
 | |
|     }
 | |
| 
 | |
|     match /{somePath=**}/bets/{betId} {
 | |
|       allow read;
 | |
|     }
 | |
| 
 | |
|     match /{somePath=**}/liquidity/{liquidityId} {
 | |
|       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;
 | |
|     }
 | |
| 
 | |
|     match /{somePath=**}/answers/{answerId} {
 | |
|       allow read;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     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;
 | |
|     }
 | |
| 
 | |
|     match /txns/{txnId} {
 | |
|       allow read;
 | |
|     }
 | |
| 
 | |
|     // Note: `resource` = existing doc, `request.resource` = incoming doc
 | |
|     match /manalinks/{slug} {
 | |
|       // Anyone can view any manalink
 | |
|       allow get;
 | |
|       // Only you can create a manalink with your fromId
 | |
|       allow create: if request.auth.uid == request.resource.data.fromId;
 | |
|       // Only you can list and change your own manalinks
 | |
|       allow list, update: if request.auth.uid == resource.data.fromId;
 | |
|     }
 | |
| 
 | |
|     match /users/{userId}/notifications/{notificationId} {
 | |
|       allow read;
 | |
|       allow update: if resource.data.userId == request.auth.uid
 | |
|                        && request.resource.data.diff(resource.data).affectedKeys()
 | |
|                                                                     .hasOnly(['isSeen', 'viewTime']);
 | |
|     }
 | |
| 
 | |
|      match /groups/{groupId} {
 | |
|           allow read;
 | |
|           allow update: if request.auth.uid == resource.data.creatorId
 | |
|                            && request.resource.data.diff(resource.data)
 | |
|                            .affectedKeys()
 | |
|                            .hasOnly(['name', 'about', 'contractIds', 'memberIds', 'anyoneCanJoin' ]);
 | |
|          allow update: if (request.auth.uid in resource.data.memberIds  || resource.data.anyoneCanJoin)
 | |
|                            && request.resource.data.diff(resource.data)
 | |
|                            .affectedKeys()
 | |
|                            .hasOnly([ 'contractIds', 'memberIds' ]);
 | |
|           allow delete: if request.auth.uid == resource.data.creatorId;
 | |
| 
 | |
|           function isMember() {
 | |
|             return request.auth.uid in get(/databases/$(database)/documents/groups/$(groupId)).data.memberIds;
 | |
|           }
 | |
|           match /comments/{commentId} {
 | |
|           	allow read;
 | |
|             allow create: if request.auth != null && commentMatchesUser(request.auth.uid, request.resource.data) && isMember();
 | |
|           }
 | |
|         }
 | |
|   }
 | |
| }
 |