-
Notifications
You must be signed in to change notification settings - Fork 2
Develop #91
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
Develop #91
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "firestore": { | ||
| "rules": "firestore.rules" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,6 +59,8 @@ service cloud.firestore { | |
| && (!('roast' in data) || (data.roast is string && data.roast.size() <= 8000)) | ||
| && (!('roastBrutal' in data) || (data.roastBrutal is string && data.roastBrutal.size() <= 8000)) | ||
| && (!('roastMild' in data) || (data.roastMild is string && data.roastMild.size() <= 8000)) | ||
| // extraTagsByCategory: mapa de categoria → lista de nomes de skills criadas pelo usuário | ||
| && (!('extraTagsByCategory' in data) || data.extraTagsByCategory is map) | ||
| && data.skills is map | ||
| && data.skills.keys().hasAll(['frontend', 'backend', 'ux_ui', 'dados', 'hardware_android', 'vibe_coding']) | ||
| && data.skills.frontend is number && data.skills.backend is number | ||
|
|
@@ -71,6 +73,37 @@ service cloud.firestore { | |
| && data.canvas.veto is list && data.canvas.veto.size() <= 50; | ||
| } | ||
|
|
||
| // ───────────────────────────────────────────── | ||
| // SKILLS | ||
| // Catálogo global de skills. Qualquer usuário | ||
| // autenticado pode ler. Criação permitida apenas | ||
| // para skills com campos obrigatórios válidos. | ||
| // Edição e deleção bloqueadas para usuários comuns. | ||
| // ───────────────────────────────────────────── | ||
| function isValidSkill(data) { | ||
| return data.keys().hasAll(['id', 'name', 'normalizedName', 'status', 'usageCount', 'createdBy', 'createdAt']) | ||
| && data.id is string && data.id.size() > 0 && data.id.size() <= 128 | ||
| && data.name is string && data.name.size() > 0 && data.name.size() <= 100 | ||
| && data.normalizedName is string && data.normalizedName.size() > 0 && data.normalizedName.size() <= 100 | ||
| && data.status is string && data.status in ['pending', 'approved', 'rejected'] | ||
| && data.usageCount is number && data.usageCount >= 0 | ||
| && data.createdBy is string | ||
| && (!('category' in data) || data.category == null || (data.category is string && data.category.size() <= 50)); | ||
|
Comment on lines
+83
to
+91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Lock down the
Also applies to: 99-101 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| match /skills/{skillId} { | ||
| // Leitura pública para usuários autenticados (autocomplete) | ||
| allow read: if isSignedIn(); | ||
|
|
||
| // Criação: usuário autenticado, skill válida, ID determinístico = normalizedName | ||
| allow create: if isSignedIn() | ||
| && skillId == incoming().normalizedName | ||
| && isValidSkill(incoming()); | ||
|
|
||
| // Atualização e deleção: bloqueadas para usuários comuns (apenas admin via console) | ||
| allow update, delete: if false; | ||
| } | ||
|
|
||
| match /test/connection { | ||
| allow read: if true; | ||
| } | ||
|
|
@@ -110,15 +143,15 @@ service cloud.firestore { | |
| && profileId == request.auth.uid | ||
| && isValidProfile(incoming()) | ||
| && incoming().createdAt == request.time | ||
| && incoming().keys().hasOnly(['userId', 'name', 'photoURL', 'github', 'linkedin', 'bio', 'primaryRole', 'secondaryRoles', 'skills', 'canvas', 'status', 'squadId', 'eventId', 'roast', 'roastBrutal', 'roastMild', 'createdAt', 'updatedAt', 'visibility']); | ||
| && incoming().keys().hasOnly(['userId', 'name', 'photoURL', 'github', 'linkedin', 'bio', 'primaryRole', 'secondaryRoles', 'skills', 'canvas', 'status', 'squadId', 'eventId', 'roast', 'roastBrutal', 'roastMild', 'createdAt', 'updatedAt', 'visibility', 'extraTagsByCategory']); | ||
|
|
||
| allow update: if isSignedIn() | ||
| && isValidId(profileId) | ||
| && isValidProfile(incoming()) | ||
| && incoming().userId == existing().userId | ||
| && incoming().createdAt == existing().createdAt | ||
| && ( | ||
| (incoming().diff(existing()).affectedKeys().hasOnly(['skills', 'canvas', 'name', 'photoURL', 'github', 'linkedin', 'bio', 'primaryRole', 'secondaryRoles', 'status', 'squadId', 'eventId', 'updatedAt', 'roast', 'roastBrutal', 'roastMild', 'visibility'])) | ||
| (incoming().diff(existing()).affectedKeys().hasOnly(['skills', 'canvas', 'name', 'photoURL', 'github', 'linkedin', 'bio', 'primaryRole', 'secondaryRoles', 'status', 'squadId', 'eventId', 'updatedAt', 'roast', 'roastBrutal', 'roastMild', 'visibility', 'extraTagsByCategory'])) | ||
|
Comment on lines
+146
to
+154
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Don't whitelist These lines allow 🤖 Prompt for AI Agents |
||
| || | ||
| false | ||
| ); | ||
|
|
@@ -171,7 +204,6 @@ service cloud.firestore { | |
| && isValidMessage(incoming()) | ||
| && incoming().createdAt == request.time; | ||
|
|
||
| // Allow listing for conversation thread queries (by conversationId, senderId or receiverId) | ||
| allow list: if isSignedIn() | ||
| && ( | ||
| resource.data.receiverId == request.auth.uid | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import "dotenv/config"; | ||
| import * as admin from "firebase-admin"; | ||
|
|
||
| const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT!); | ||
| const dbId = process.env.VITE_FIREBASE_FIRESTORE_DATABASE_ID!; | ||
|
|
||
| admin.initializeApp({ | ||
| credential: admin.credential.cert(serviceAccount), | ||
| }); | ||
|
Comment on lines
+4
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win Guard env parsing and app init inside the A missing or malformed 🤖 Prompt for AI Agents |
||
|
|
||
| async function run() { | ||
| const securityRules = admin.securityRules(); | ||
|
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🌐 Web query:
💡 Result: Yes, firebase-admin 14.1.0 provides a top-level securityRules API that allows you to access the SecurityRules service for managing and retrieving Firestore security rules [1][2][3]. You can access this service by calling admin.securityRules [2][3]. Once you have the SecurityRules instance, you can use the getFirestoreRuleset method to retrieve the ruleset currently applied to Cloud Firestore [4][5][6]. Example usage: const admin = require('firebase-admin'); admin.initializeApp; // Retrieve the currently applied Firestore ruleset admin.securityRules.getFirestoreRuleset.then((ruleset) => { console.log('Current Firestore ruleset:', ruleset); }).catch((error) => { console.error('Error retrieving ruleset:', error); }); This API was originally introduced in earlier versions of the SDK [1][7] and remains available in version 14.1.0 [8][9]. Citations:
🏁 Script executed: #!/bin/bash
set -euo pipefail
# Locate and inspect the target file.
git ls-files | rg '^get-rules\.ts$|/get-rules\.ts$|^.*get-rules\.ts$' || true
if [ -f get-rules.ts ]; then
wc -l get-rules.ts
cat -n get-rules.ts
fi
# Check the firebase-admin version declared in package files, if present.
rg -n '"firebase-admin"|firebase-admin' package.json package-lock.json pnpm-lock.yaml yarn.lock --no-heading || true
# Look for other uses of securityRules in the repo.
rg -n 'securityRules\(' . --no-heading || trueRepository: MatchDock/match-tech Length of output: 2302 🌐 Web query:
💡 Result: In the Firebase Admin SDK, Citations:
Call a ruleset method on the returned service 🧰 Tools🪛 ESLint[error] 12-12: 'securityRules' is assigned a value but never used. ( 🤖 Prompt for AI Agents |
||
| try { | ||
| // The Rules API handles generic rules, let's try to get Firestore rules | ||
| // Using the REST API directly is easier since the SDK might not expose getRules for specific DBs easily. | ||
| console.log("Database ID from env:", dbId); | ||
| } catch(e) { | ||
| console.error(e); | ||
| } | ||
| } | ||
|
|
||
| run(); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Validate the contents of
extraTagsByCategory, not just that it is a map.The PR contract here is category → list of user-created skill names, but this rule accepts any nested structure. Malformed profile data can persist numbers or objects under a category and then break the onboarding code that reads these values as string arrays.
🤖 Prompt for AI Agents