Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Firebase insecure rules #86

Open
awest25 opened this issue Feb 22, 2024 · 7 comments
Open

Fix Firebase insecure rules #86

awest25 opened this issue Feb 22, 2024 · 7 comments
Assignees
Labels
bug Something isn't working medium

Comments

@awest25
Copy link
Collaborator

awest25 commented Feb 22, 2024

Currently our access rules are set for development, allowing anybody read/write abilities.

Fix the rules for Firestore and Storage.

Ask @awest25 or @Fredenck for the login to the Firebase console.

@awest25 awest25 added the bug Something isn't working label Feb 22, 2024
@tyu-hi tyu-hi self-assigned this Oct 29, 2024
@tyu-hi
Copy link
Collaborator

tyu-hi commented Nov 5, 2024

To do:

  • prevent users (tennis team) from making changes to the site. currently, women and men accounts can access their collections as seen in firebase.
  • we need to limit permissions for players (for now) and not let them access the collection -> have them be read-only.
  • also don't let the tennis teams edit the tagging section.

thoughts:

  • general BSA account for read/write perms, so that tagging can only be accessed by us.
  • separate account for tagging vs. general account for all of us.

@tyu-hi
Copy link
Collaborator

tyu-hi commented Nov 13, 2024

version 1

notes:

  • I'm assuming there is an admin account, but I don't see it in the firebase database?? so I'm making it up here (?). I've set it as admin@ucla.edu.
  • Need to change admin email later to the real one
  • also, I'm allowing only Admin to read/write the UCLA (W) and UCLA (M) collections, but UCLA (W) and UCLA (M) can read the matches collection --> is this what we want?

rules implementation:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Helper functions
    function isAuthenticated() {
      return request.auth != null;
    }
    
    function isAdmin() {
      let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
      // Replace with actual admin email(s) ??
      return isAuthenticated() && 
        userData.email == "admin@ucla.edu"; // Specify the exact admin email ! But this implementation isn't so secure!
    }
    
    // Check if user is on women's team
    function isWomensTeamPlayer() {
      let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
      return isAuthenticated() && 
        userData.email.matches(".*@ucla.edu") &&
        userData.displayName == "UCLA Women's Tennis";
    }
    
    // Check if user is on men's team
    function isMensTeamPlayer() {
      let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
      return isAuthenticated() && 
        userData.email.matches(".*@ucla.edu") &&
        userData.displayName == "UCLA Men's Tennis";
    }

    // UCLA Women's Team Collection
    match /UCLA (W)/{document=**} {
      allow read, write: if isAdmin();
    }

    // UCLA Men's Team Collection
    match /UCLA (M)/{document=**} {
      allow read, write: if isAdmin();
    }

    // Matches Collection
    match /matches/{match} {
      allow read: if isAuthenticated() && (
        isAdmin() || 
        (isMensTeamPlayer() && resource.data.clientTeam == 'UCLA (M)') ||
        (isWomensTeamPlayer() && resource.data.clientTeam == 'UCLA (W)')
      );
      allow write: if isAdmin();
    }

    // Teams Collection
    match /teams/{team} {
      allow read: if isAuthenticated();
      allow write: if isAdmin();
    }

    // Users Collection
    match /users/{userId} {
      allow read: if isAuthenticated();
      allow write: if isAdmin() || 
        (isAuthenticated() && request.auth.uid == userId && 
         // Prevent players from changing their team or email
         (!isMensTeamPlayer() && !isWomensTeamPlayer() || 
          !request.resource.data.diff(resource.data).affectedKeys().hasAny(['teams', 'email'])));
    }

    // Default deny
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

@tyu-hi
Copy link
Collaborator

tyu-hi commented Nov 19, 2024

admin email: uclatennisconsulting@gmail.com

@tyu-hi
Copy link
Collaborator

tyu-hi commented Nov 19, 2024

notes

  • remove matches collection as it's deprecated --> it's a part of UCLA (M) and UCLA (W) which contains their matches data so allow them to read but not write
  • in the future, we want to add more collections with groups besides UCLA (M/F), so find a way to dynamically check the collections read/write permissions

@tyu-hi
Copy link
Collaborator

tyu-hi commented Nov 19, 2024

version 2

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Helper functions
    function isAuthenticated() {
      return request.auth != null;
    }
    
    function isAdmin() {
      let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
      // Replace with actual admin email(s) ??
      return isAuthenticated() && 
        userData.email == "admin@ucla.edu"; // Specify the exact admin email ! But this implementation isn't so secure!
    }
    
    // Check if user is on women's team
    function isWomensTeamPlayer() {
      let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
      return isAuthenticated() && 
        userData.email.matches(".*@ucla.edu") &&
        userData.displayName == "UCLA Women's Tennis";
    }
    
    // Check if user is on men's team
    function isMensTeamPlayer() {
      let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
      return isAuthenticated() && 
        userData.email.matches(".*@ucla.edu") &&
        userData.displayName == "UCLA Men's Tennis";
    }

    // UCLA Women's Team Collection
    match /UCLA (W)/{document=**} {
      allow read, write: if isAdmin();
    }

    // UCLA Men's Team Collection
    match /UCLA (M)/{document=**} {
      allow read, write: if isAdmin();
    }


    // Teams Collection
    match /teams/{team} {
      allow read: if isAuthenticated();
      allow write: if isAdmin();
    }

    // Users Collection
    match /users/{userId} {
      allow read: if isAuthenticated();
      allow write: if isAdmin() || 
        (isAuthenticated() && request.auth.uid == userId && 
         // Prevent players from changing their team or email
         (!isMensTeamPlayer() && !isWomensTeamPlayer() || 
          !request.resource.data.diff(resource.data).affectedKeys().hasAny(['teams', 'email'])));
    }

    // Default deny
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

@Fredenck
Copy link
Collaborator

here's some comments from me and ChatGPT:
make sure you're using uclatennisconsulting@gmail.com for admin email.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    function isAuthenticated() {
      return request.auth != null;
    }

    function isAdmin() {
      return request.auth.token.isAdmin == true; // Use custom claims for admin check
    }

    function isTeamPlayer(teamName) {
      let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
      return isAuthenticated() &&
             userData.email.matches(".*@ucla.edu") &&
             userData.displayName == teamName;
    }

    match /UCLA (W)/{document=**} {
      allow read, write: if isAdmin();
    }

    match /UCLA (M)/{document=**} {
      allow read, write: if isAdmin();
    }

    match /teams/{teamId} {
      allow read: if isAuthenticated();
      allow write: if isAdmin();
    }

    match /users/{userId} {
      allow read: if isAuthenticated();
      allow write: if isAdmin() ||
        (isAuthenticated() && request.auth.uid == userId && 
         !request.resource.data.diff(resource.data).affectedKeys().hasAny(['teams', 'email', 'uid', 'roles']));
    }

    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working medium
Projects
None yet
Development

No branches or pull requests

4 participants