From 56db418521094bd9f3f1a91254bbf017742cbad5 Mon Sep 17 00:00:00 2001 From: Adam Richie-Halford Date: Thu, 3 Oct 2024 10:13:07 -0700 Subject: [PATCH] Add archived: false to queries for users and orgs (#790) * Add archived: false to queries for users and orgs * Add archived: false to queries for users and orgs * Update roar-admin firestore indexes * Add indexes for groups and families * WIP: query users by archived status * Use assignment doc for administration info rather than seperate administration call * Add archived: false to queries for users and orgs * Update roar-admin firestore indexes * Add indexes for groups and families * WIP: query users by archived status * Change Clever signin back to redirect * Use assignment doc for administration info rather than seperate administration call * Remove data-cy from speed dial and use name in admin greeting * Use firekit method to get administrations * Remove unused computed properties * Update firekit * npm run lint * Refactor administrations fetcher to use cloud function that grabs only IDs * Remove console warning * Update firekit * Remove console.log statements * UpdateUserData should not use logged in user's ID * Update firestore rules * Use roarUid instead of uid for fetchDocById with collection = users * Add archived: false to queries for users and orgs * Update roar-admin firestore indexes * Add indexes for groups and families * WIP: query users by archived status * Change Clever signin back to redirect * Use assignment doc for administration info rather than seperate administration call * Remove data-cy from speed dial and use name in admin greeting * Use firekit method to get administrations * Update firekit * npm run lint * Refactor administrations fetcher to use cloud function that grabs only IDs * Remove console warning * Update firekit * Remove console.log statements * Update firestore rules * WIP: query users by archived status * UpdateUserData should not use logged in user's ID * Use roarUid instead of uid for fetchDocById with collection = users * Ensure fresh copy of assignment info * Update firestore indexes for admin project * Update firestore indexes * Fix administration query and ordering/filtering * Fix TOS race condition for administrators * Fix participant assent/consent * Remove default sort for score report * Add secondary sort for score report table * adding some minor error handling * fixing localeCompare on ScoreReport * Remove space between user display name and exclamation point * solving cypress test * making signInWIthcleverRedirect default * Add 'direct report' classes under districts in tree table orgs * Resolve legalDocs.some error * Add direct report classes to a special 'direct report' school * Add TODO comment --------- Co-authored-by: Elijah Kelly Co-authored-by: emily-ejag --- firebase/LEVANTE/admin/firestore.rules | 15 +- firebase/LEVANTE/assessment/firestore.rules | 15 +- firebase/admin/firestore.indexes.json | 866 ++++++++++++++++++-- firebase/admin/firestore.rules | 15 +- firebase/assessment/firestore.rules | 15 +- package-lock.json | 36 +- package.json | 2 +- src/App.vue | 6 +- src/components/CardAdministration.vue | 137 +++- src/components/ListUsers.vue | 8 +- src/components/NavBar.vue | 7 +- src/helpers/query/administrations.js | 335 ++------ src/helpers/query/assignments.js | 90 +- src/helpers/query/orgs.js | 97 +-- src/helpers/query/users.js | 48 +- src/helpers/query/utils.js | 2 +- src/pages/HomeAdministrator.vue | 47 +- src/pages/HomeParticipant.vue | 50 +- src/pages/HomeSelector.vue | 18 +- src/pages/ScoreReport.vue | 53 +- src/pages/SignIn.vue | 20 +- 21 files changed, 1179 insertions(+), 703 deletions(-) diff --git a/firebase/LEVANTE/admin/firestore.rules b/firebase/LEVANTE/admin/firestore.rules index 2e10245ce..f74e9b0e0 100644 --- a/firebase/LEVANTE/admin/firestore.rules +++ b/firebase/LEVANTE/admin/firestore.rules @@ -67,12 +67,13 @@ service cloud.firestore { allow read, write: if request.auth.uid == uid; } - function isUserAdmin() { - let districts = resource.data.get(['districts', 'current'], []); - let schools = resource.data.get(['schools', 'current'], []); - let classes = resource.data.get(['classes', 'current'], []); - let groups = resource.data.get(['groups', 'current'], []); - let families = resource.data.get(['families', 'current'], []); + function isUserAdmin(requireCurrent) { + let orgStatus = requireCurrent ? 'current' : 'all'; + let districts = resource.data.get(['districts', orgStatus], []); + let schools = resource.data.get(['schools', orgStatus], []); + let classes = resource.data.get(['classes', orgStatus], []); + let groups = resource.data.get(['groups', orgStatus], []); + let families = resource.data.get(['families', orgStatus], []); let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {}); return districts.hasAny(adminOrgs.get('districts', ['..'])) || schools.hasAny(adminOrgs.get('schools', ['..'])) @@ -82,7 +83,7 @@ service cloud.firestore { } function canReadExistingUser() { - return myData() || isUserAdmin(); + return myData() || isUserAdmin(false) || isUserAdmin(true); } allow read: if canReadExistingUser(); diff --git a/firebase/LEVANTE/assessment/firestore.rules b/firebase/LEVANTE/assessment/firestore.rules index 067f11b6d..2f6848964 100644 --- a/firebase/LEVANTE/assessment/firestore.rules +++ b/firebase/LEVANTE/assessment/firestore.rules @@ -55,12 +55,13 @@ service cloud.firestore { return uid == roarUid(); } - function isUserAdmin() { - let districts = resource.data.get(['districts', 'current'], []); - let schools = resource.data.get(['schools', 'current'], []); - let classes = resource.data.get(['classes', 'current'], []); - let groups = resource.data.get(['groups', 'current'], []); - let families = resource.data.get(['families', 'current'], []); + function isUserAdmin(requireCurrent) { + let orgStatus = requireCurrent ? 'current' : 'all'; + let districts = resource.data.get(['districts', orgStatus], []); + let schools = resource.data.get(['schools', orgStatus], []); + let classes = resource.data.get(['classes', orgStatus], []); + let groups = resource.data.get(['groups', orgStatus], []); + let families = resource.data.get(['families', orgStatus], []); let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {}); return districts.hasAny(adminOrgs.get('districts', ['..'])) || schools.hasAny(adminOrgs.get('schools', ['..'])) @@ -70,7 +71,7 @@ service cloud.firestore { } function canReadExistingUser() { - return myData() || isUserAdmin(); + return myData() || isUserAdmin(false) || isUserAdmin(true); } allow read: if canReadExistingUser(); diff --git a/firebase/admin/firestore.indexes.json b/firebase/admin/firestore.indexes.json index 289ecbee9..199db5dd3 100644 --- a/firebase/admin/firestore.indexes.json +++ b/firebase/admin/firestore.indexes.json @@ -2,11 +2,25 @@ "indexes": [ { "collectionGroup": "administrations", - "queryScope": "COLLECTION_GROUP", + "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "testData", + "fieldPath": "districts", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "dateClosed", "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "administrations", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "readOrgs.classes", + "arrayConfig": "CONTAINS" }, { "fieldPath": "name", @@ -19,7 +33,7 @@ "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "readOrgs.classes", + "fieldPath": "readOrgs.districts", "arrayConfig": "CONTAINS" }, { @@ -36,6 +50,10 @@ "fieldPath": "readOrgs.districts", "arrayConfig": "CONTAINS" }, + { + "fieldPath": "testData", + "order": "ASCENDING" + }, { "fieldPath": "name", "order": "ASCENDING" @@ -70,6 +88,24 @@ } ] }, + { + "collectionGroup": "administrations", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "readOrgs.groups", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "testData", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "administrations", "queryScope": "COLLECTION", @@ -84,6 +120,80 @@ } ] }, + { + "collectionGroup": "administrations", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "schools", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "dateClosed", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "administrations", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "testData", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "assignedOrgs", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "orgId", + "order": "ASCENDING" + }, + { + "fieldPath": "dateClosed", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "assignedOrgs", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "orgId", + "order": "ASCENDING" + }, + { + "fieldPath": "testData", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "assignedOrgs", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "orgId", + "order": "ASCENDING" + }, + { + "fieldPath": "testData", + "order": "ASCENDING" + }, + { + "fieldPath": "dateClosed", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "assignments", "queryScope": "COLLECTION_GROUP", @@ -2998,6 +3108,10 @@ "collectionGroup": "classes", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "schoolId", "order": "ASCENDING" @@ -3012,6 +3126,10 @@ "collectionGroup": "classes", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "schoolId", "order": "ASCENDING" @@ -3023,7 +3141,7 @@ ] }, { - "collectionGroup": "schools", + "collectionGroup": "classes", "queryScope": "COLLECTION", "fields": [ { @@ -3031,59 +3149,59 @@ "order": "ASCENDING" }, { - "fieldPath": "abbreviation", + "fieldPath": "lastRoarSync", "order": "ASCENDING" } ] }, { - "collectionGroup": "schools", + "collectionGroup": "classes", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "districtId", + "fieldPath": "schoolId", "order": "ASCENDING" }, { - "fieldPath": "abbreviation", - "order": "DESCENDING" + "fieldPath": "name", + "order": "ASCENDING" } ] }, { - "collectionGroup": "schools", + "collectionGroup": "classes", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "districtId", + "fieldPath": "schoolId", "order": "ASCENDING" }, { - "fieldPath": "address", - "order": "ASCENDING" + "fieldPath": "name", + "order": "DESCENDING" } ] }, { - "collectionGroup": "schools", + "collectionGroup": "districts", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "districtId", + "fieldPath": "archived", "order": "ASCENDING" }, { - "fieldPath": "address", - "order": "DESCENDING" + "fieldPath": "name", + "order": "ASCENDING" } ] }, { - "collectionGroup": "schools", + "collectionGroup": "families", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "districtId", + "fieldPath": "archived", "order": "ASCENDING" }, { @@ -3093,187 +3211,623 @@ ] }, { - "collectionGroup": "schools", + "collectionGroup": "groups", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "districtId", + "fieldPath": "archived", "order": "ASCENDING" }, { "fieldPath": "name", - "order": "DESCENDING" + "order": "ASCENDING" } ] }, { - "collectionGroup": "users", - "queryScope": "COLLECTION", + "collectionGroup": "readOrgs", + "queryScope": "COLLECTION_GROUP", "fields": [ { - "fieldPath": "assigningOrgs.districts", - "arrayConfig": "CONTAINS" - }, - { - "fieldPath": "schoolName", + "fieldPath": "orgId", "order": "ASCENDING" }, { - "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW", + "fieldPath": "dateClosed", "order": "ASCENDING" } ] }, { - "collectionGroup": "users", - "queryScope": "COLLECTION", + "collectionGroup": "readOrgs", + "queryScope": "COLLECTION_GROUP", "fields": [ { - "fieldPath": "assigningOrgs.districts", - "arrayConfig": "CONTAINS" - }, - { - "fieldPath": "studentData.grade", + "fieldPath": "orgId", "order": "ASCENDING" }, { - "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW", + "fieldPath": "testData", "order": "ASCENDING" } ] }, { - "collectionGroup": "users", - "queryScope": "COLLECTION", + "collectionGroup": "readOrgs", + "queryScope": "COLLECTION_GROUP", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "orgId", + "order": "ASCENDING" }, { - "fieldPath": "name", + "fieldPath": "testData", + "order": "ASCENDING" + }, + { + "fieldPath": "dateClosed", "order": "ASCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "archived", + "order": "ASCENDING" }, { - "fieldPath": "name.first", + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "abbreviation", "order": "ASCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "archived", + "order": "ASCENDING" }, { - "fieldPath": "name.first", + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "abbreviation", "order": "DESCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "archived", + "order": "ASCENDING" }, { - "fieldPath": "name.last", + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "address", "order": "ASCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "archived", + "order": "ASCENDING" }, { - "fieldPath": "name.last", + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "address", "order": "DESCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "archived", + "order": "ASCENDING" }, { - "fieldPath": "studentData.dob", + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", "order": "ASCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "archived", + "order": "ASCENDING" }, { - "fieldPath": "studentData.dob", + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", "order": "DESCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "districtId", + "order": "ASCENDING" }, { - "fieldPath": "studentData.gender", + "fieldPath": "abbreviation", "order": "ASCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", - "arrayConfig": "CONTAINS" + "fieldPath": "districtId", + "order": "ASCENDING" }, { - "fieldPath": "studentData.gender", + "fieldPath": "abbreviation", "order": "DESCENDING" } ] }, { - "collectionGroup": "users", + "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "classes.current", + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "address", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "address", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "lastRoarSync", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "abbreviation", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "abbreviation", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "address", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "address", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "lastRoarSync", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "districts.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "families.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "groups.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "schools.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "assigningOrgs.districts", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "schoolName", + "order": "ASCENDING" + }, + { + "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "assigningOrgs.districts", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "studentData.grade", + "order": "ASCENDING" + }, + { + "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name.first", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name.first", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name.last", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "name.last", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "studentData.dob", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "studentData.dob", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "studentData.gender", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "studentData.gender", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "classes.current", "arrayConfig": "CONTAINS" }, { @@ -3352,6 +3906,20 @@ } ] }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districts.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "archived", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "users", "queryScope": "COLLECTION", @@ -3366,6 +3934,20 @@ } ] }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districts.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "lastRoarSync", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "users", "queryScope": "COLLECTION", @@ -4218,46 +4800,88 @@ "collectionGroup": "administrations", "fieldPath": "classes", "ttl": false, + "indexes": [] + }, + { + "collectionGroup": "administrations", + "fieldPath": "createdBy", + "ttl": false, "indexes": [ { - "arrayConfig": "CONTAINS", + "order": "ASCENDING", "queryScope": "COLLECTION" } ] }, { "collectionGroup": "administrations", - "fieldPath": "districts", + "fieldPath": "dateClosed", "ttl": false, "indexes": [ { - "arrayConfig": "CONTAINS", + "order": "ASCENDING", + "queryScope": "COLLECTION" + }, + { + "order": "DESCENDING", "queryScope": "COLLECTION" } ] }, { "collectionGroup": "administrations", - "fieldPath": "families", + "fieldPath": "dateCreated", "ttl": false, "indexes": [ { - "arrayConfig": "CONTAINS", + "order": "ASCENDING", + "queryScope": "COLLECTION" + }, + { + "order": "DESCENDING", "queryScope": "COLLECTION" } ] }, { "collectionGroup": "administrations", - "fieldPath": "groups", + "fieldPath": "dateOpened", "ttl": false, "indexes": [ { - "arrayConfig": "CONTAINS", + "order": "ASCENDING", + "queryScope": "COLLECTION" + }, + { + "order": "DESCENDING", "queryScope": "COLLECTION" } ] }, + { + "collectionGroup": "administrations", + "fieldPath": "districts", + "ttl": false, + "indexes": [] + }, + { + "collectionGroup": "administrations", + "fieldPath": "families", + "ttl": false, + "indexes": [] + }, + { + "collectionGroup": "administrations", + "fieldPath": "groups", + "ttl": false, + "indexes": [] + }, + { + "collectionGroup": "administrations", + "fieldPath": "minimalOrgs", + "ttl": false, + "indexes": [] + }, { "collectionGroup": "administrations", "fieldPath": "name", @@ -4274,10 +4898,6 @@ { "arrayConfig": "CONTAINS", "queryScope": "COLLECTION" - }, - { - "order": "ASCENDING", - "queryScope": "COLLECTION_GROUP" } ] }, @@ -4346,16 +4966,40 @@ "collectionGroup": "administrations", "fieldPath": "schools", "ttl": false, + "indexes": [] + }, + { + "collectionGroup": "administrations", + "fieldPath": "sequential", + "ttl": false, + "indexes": [] + }, + { + "collectionGroup": "administrations", + "fieldPath": "testData", + "ttl": false, "indexes": [ + { + "order": "ASCENDING", + "queryScope": "COLLECTION" + }, + { + "order": "DESCENDING", + "queryScope": "COLLECTION" + }, { "arrayConfig": "CONTAINS", "queryScope": "COLLECTION" + }, + { + "order": "ASCENDING", + "queryScope": "COLLECTION_GROUP" } ] }, { - "collectionGroup": "administrations", - "fieldPath": "testData", + "collectionGroup": "assignedOrgs", + "fieldPath": "orgId", "ttl": false, "indexes": [ { @@ -4376,6 +5020,25 @@ } ] }, + { + "collectionGroup": "assignments", + "fieldPath": "assessments", + "ttl": false, + "indexes": [ + { + "order": "ASCENDING", + "queryScope": "COLLECTION" + }, + { + "order": "DESCENDING", + "queryScope": "COLLECTION" + }, + { + "arrayConfig": "CONTAINS", + "queryScope": "COLLECTION" + } + ] + }, { "collectionGroup": "assignments", "fieldPath": "assigningOrgs", @@ -4432,6 +5095,29 @@ "ttl": false, "indexes": [] }, + { + "collectionGroup": "readOrgs", + "fieldPath": "orgId", + "ttl": false, + "indexes": [ + { + "order": "ASCENDING", + "queryScope": "COLLECTION" + }, + { + "order": "DESCENDING", + "queryScope": "COLLECTION" + }, + { + "arrayConfig": "CONTAINS", + "queryScope": "COLLECTION" + }, + { + "order": "ASCENDING", + "queryScope": "COLLECTION_GROUP" + } + ] + }, { "collectionGroup": "status", "fieldPath": "completion", diff --git a/firebase/admin/firestore.rules b/firebase/admin/firestore.rules index 284b25c27..2a36db6a1 100644 --- a/firebase/admin/firestore.rules +++ b/firebase/admin/firestore.rules @@ -74,12 +74,13 @@ service cloud.firestore { return uid == roarUid(); } - function isUserAdmin() { - let districts = resource.data.get(['districts', 'current'], []); - let schools = resource.data.get(['schools', 'current'], []); - let classes = resource.data.get(['classes', 'current'], []); - let groups = resource.data.get(['groups', 'current'], []); - let families = resource.data.get(['families', 'current'], []); + function isUserAdmin(requireCurrent) { + let orgStatus = requireCurrent ? 'current' : 'all'; + let districts = resource.data.get(['districts', orgStatus], []); + let schools = resource.data.get(['schools', orgStatus], []); + let classes = resource.data.get(['classes', orgStatus], []); + let groups = resource.data.get(['groups', orgStatus], []); + let families = resource.data.get(['families', orgStatus], []); let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {}); return districts.hasAny(adminOrgs.get('districts', ['..'])) || schools.hasAny(adminOrgs.get('schools', ['..'])) @@ -89,7 +90,7 @@ service cloud.firestore { } function canReadExistingUser() { - return myData() || isUserAdmin(); + return myData() || isUserAdmin(false) || isUserAdmin(true); } allow read: if canReadExistingUser(); diff --git a/firebase/assessment/firestore.rules b/firebase/assessment/firestore.rules index ea0b52863..70a609805 100644 --- a/firebase/assessment/firestore.rules +++ b/firebase/assessment/firestore.rules @@ -57,12 +57,13 @@ service cloud.firestore { return uid == roarUid(); } - function isUserAdmin() { - let districts = resource.data.get(['districts', 'current'], []); - let schools = resource.data.get(['schools', 'current'], []); - let classes = resource.data.get(['classes', 'current'], []); - let groups = resource.data.get(['groups', 'current'], []); - let families = resource.data.get(['families', 'current'], []); + function isUserAdmin(requireCurrent) { + let orgStatus = requireCurrent ? 'current' : 'all'; + let districts = resource.data.get(['districts', orgStatus], []); + let schools = resource.data.get(['schools', orgStatus], []); + let classes = resource.data.get(['classes', orgStatus], []); + let groups = resource.data.get(['groups', orgStatus], []); + let families = resource.data.get(['families', orgStatus], []); let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {}); return districts.hasAny(adminOrgs.get('districts', ['..'])) || schools.hasAny(adminOrgs.get('schools', ['..'])) @@ -72,7 +73,7 @@ service cloud.firestore { } function canReadExistingUser() { - return myData() || isUserAdmin(); + return myData() || isUserAdmin(false) || isUserAdmin(true); } allow read: if canReadExistingUser(); diff --git a/package-lock.json b/package-lock.json index 59ce71c39..057e6f2f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.11.18", "dependencies": { "@bdelab/roam-fluency": "1.11.26", - "@bdelab/roar-firekit": "^8.0.8", + "@bdelab/roar-firekit": "^9.0.1", "@bdelab/roar-letter": "1.11.8", "@bdelab/roar-multichoice": "^1.11.3", "@bdelab/roar-pa": "2.2.4", @@ -1848,9 +1848,9 @@ } }, "node_modules/@bdelab/roar-firekit": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.8.tgz", - "integrity": "sha512-L69a3uQff8OYHFUP9i036N1NGon3y2YR0SLYbHwtNyulkXemtZqNbPxvJPokdupOOAsuw+MRMUxPJPJrxX8ocQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-9.0.1.tgz", + "integrity": "sha512-MscBltVjx0V1BsTP+n5/3Afwtp76DDe67CgeqrnCTClXgqUyq2KWzB9cndppVhr2Fk6XZWPbk5rrnAvjZpN6fw==", "license": "ISC", "dependencies": { "@bdelab/roar-firekit": "^4.1.1", @@ -24790,7 +24790,6 @@ }, "node_modules/npm/node_modules/lodash._baseindexof": { "version": "3.1.0", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -24815,19 +24814,16 @@ }, "node_modules/npm/node_modules/lodash._bindcallback": { "version": "3.0.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._cacheindexof": { "version": "3.0.2", - "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._createcache": { "version": "3.1.2", - "extraneous": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -24836,7 +24832,6 @@ }, "node_modules/npm/node_modules/lodash._getnative": { "version": "3.9.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -24847,7 +24842,6 @@ }, "node_modules/npm/node_modules/lodash.restparam": { "version": "3.6.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -38988,9 +38982,9 @@ } }, "@bdelab/roar-firekit": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.8.tgz", - "integrity": "sha512-L69a3uQff8OYHFUP9i036N1NGon3y2YR0SLYbHwtNyulkXemtZqNbPxvJPokdupOOAsuw+MRMUxPJPJrxX8ocQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-9.0.1.tgz", + "integrity": "sha512-MscBltVjx0V1BsTP+n5/3Afwtp76DDe67CgeqrnCTClXgqUyq2KWzB9cndppVhr2Fk6XZWPbk5rrnAvjZpN6fw==", "requires": { "@bdelab/roar-firekit": "^4.1.1", "crc-32": "^1.2.2", @@ -56414,8 +56408,7 @@ }, "lodash._baseindexof": { "version": "3.1.0", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash._baseuniq": { "version": "4.6.0", @@ -56437,26 +56430,22 @@ }, "lodash._bindcallback": { "version": "3.0.1", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash._cacheindexof": { "version": "3.0.2", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash._createcache": { "version": "3.1.2", "bundled": true, - "extraneous": true, "requires": { "lodash._getnative": "^3.0.0" } }, "lodash._getnative": { "version": "3.9.1", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash.clonedeep": { "version": "4.5.0", @@ -56464,8 +56453,7 @@ }, "lodash.restparam": { "version": "3.6.1", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash.union": { "version": "4.6.0", diff --git a/package.json b/package.json index 96e0f1565..9af767ae2 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@bdelab/roam-fluency": "1.11.26", - "@bdelab/roar-firekit": "^8.0.8", + "@bdelab/roar-firekit": "^9.0.1", "@bdelab/roar-letter": "1.11.8", "@bdelab/roar-multichoice": "^1.11.3", "@bdelab/roar-pa": "2.2.4", diff --git a/src/App.vue b/src/App.vue index ae4ad4dfa..7316fa2a9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -88,11 +88,13 @@ onBeforeMount(async () => { authStore.setUser(); await authStore.initStateFromRedirect().then(async () => { if (authStore.uid) { - const userData = await fetchDocById('users', authStore.uid); const userClaims = await fetchDocById('userClaims', authStore.uid); - authStore.userData = userData; authStore.userClaims = userClaims; } + if (authStore.roarUid) { + const userData = await fetchDocById('users', authStore.roarUid); + authStore.userData = userData; + } }); isAuthStoreReady.value = true; }); diff --git a/src/components/CardAdministration.vue b/src/components/CardAdministration.vue index 51cedd077..e87afe53d 100644 --- a/src/components/CardAdministration.vue +++ b/src/components/CardAdministration.vue @@ -19,7 +19,6 @@ button-class="p-button-outlined p-button-sm w-3rem h-3rem border-primary border-1 border-circle bg-transparent hover:surface-300" :tooltip-options="{ position: 'top' }" :pt="{ button: { size: 'small' } }" - data-cy="button-speed-dial" /> @@ -94,7 +93,7 @@