diff --git a/.github/workflows/firebase_actions.yml b/.github/workflows/firebase_actions.yml index e26115ec4..8af6a6fe7 100644 --- a/.github/workflows/firebase_actions.yml +++ b/.github/workflows/firebase_actions.yml @@ -47,7 +47,7 @@ jobs: working-directory: metrics/firebase/functions/ - name: Run Firestore security rules tests - run: firebase emulators:exec --only firestore "npm run test" + run: firebase use default && firebase emulators:exec --only firestore "npm run test" working-directory: metrics/firebase/ - name: Deploy Cloud Functions and Firestore security rules diff --git a/metrics/firebase/firestore/rules/firestore.rules b/metrics/firebase/firestore/rules/firestore.rules index a28ba5eaf..629d1b5c2 100644 --- a/metrics/firebase/firestore/rules/firestore.rules +++ b/metrics/firebase/firestore/rules/firestore.rules @@ -3,30 +3,33 @@ service cloud.firestore { match /databases/{database}/documents { match /project_groups/{projectGroupId} { - allow read, delete: if isAccessAuthorized(database); - allow create, update: if isAccessAuthorized(database) && isProjectGroupValid(); + allow read: if isSignedIn(database) || isPublicDashbordAnonymousAccess(database); + allow delete: if isSignedIn(database); + allow create, update: if isSignedIn(database) && isProjectGroupValid(); } match /projects/{projectId} { - allow read: if isAccessAuthorized(database); - allow create, update: if isAccessAuthorized(database) && isProjectValid(); + allow read: if isSignedIn(database) || isPublicDashbordAnonymousAccess(database); + allow create, update: if isSignedIn(database) && isProjectValid(); allow delete: if false; } match /build/{buildId} { - allow read: if isAccessAuthorized(database); - allow create, update: if isAccessAuthorized(database) && isBuildValid(database); + allow read: if isSignedIn(database) || isPublicDashbordAnonymousAccess(database); + allow create, update: if isSignedIn(database) && isBuildValid(database); allow delete: if false; } match /build_days/{buildDayId} { - allow read: if isAccessAuthorized(database); + allow read: if isSignedIn(database) || isPublicDashbordAnonymousAccess(database); allow write: if false; } match /user_profiles/{userProfileId} { - allow get: if isAccessAuthorized(database) && isDocumentOwner(userProfileId); - allow write: if isAccessAuthorized(database) && isDocumentOwner(userProfileId) && isUserProfileValid(database); + allow get: if (isSignedIn(database) || isPublicDashbordAnonymousAccess(database)) && + isDocumentOwner(userProfileId); + allow write: if (isSignedIn(database) || isPublicDashbordAnonymousAccess(database)) && + isDocumentOwner(userProfileId) && isUserProfileValid(database); allow list: if false; allow delete: if false; } @@ -46,8 +49,8 @@ service cloud.firestore { } /// Checks if a user access is authorized. - function isAccessAuthorized(database) { - return request.auth.uid != null && isEmailValid(database) + function isSignedIn(database) { + return request.auth.uid != null && isEmailValid(database); } /// Checks if the request is from a user with a valid email. @@ -68,11 +71,31 @@ service cloud.firestore { return isEmailDomainExists; } + /// Checks if the sign in provider from the request equals to the given parameter. + function checkSignInProvider(signInProvider) { + let authToken = request.auth.token; + + return authToken.firebase.sign_in_provider == signInProvider; + } + /// Checks if the sign in provider from the request is a password. function isSignInProviderPassword() { - let authToken = request.auth.token; + return checkSignInProvider('password'); + } + + /// Checks if the sign in provider from request is anonymous and public dashboard feature is enabled + function isPublicDashbordAnonymousAccess(database) { + return isSignInProviderAnonymous(database) && isPublicDashboardEnabled(database); + } + + /// Checks if the sign in provider from the request is an anonymous. + function isSignInProviderAnonymous(database) { + return checkSignInProvider('anonymous'); + } - return authToken.firebase.sign_in_provider == 'password'; + /// Checks if the public dashboard feature is enabled + function isPublicDashboardEnabled(database) { + return get(/databases/$(database)/documents/feature_config/feature_config).data.isPublicDashboardEnabled; } /// Checks whether project group data from the request is valid. @@ -192,7 +215,7 @@ service cloud.firestore { "workflowName", "url", "apiUrl", - "coverage", + "coverage" ]); } @@ -274,7 +297,7 @@ service cloud.firestore { let requestData = request.resource.data; return requestData.keys().hasOnly([ - "selectedTheme", + "selectedTheme" ]); } } diff --git a/metrics/firebase/test/firestore/rules/allowed-email-domains-test.js b/metrics/firebase/test/firestore/rules/allowed-email-domains-test.js index 611e01a30..9d5661968 100644 --- a/metrics/firebase/test/firestore/rules/allowed-email-domains-test.js +++ b/metrics/firebase/test/firestore/rules/allowed-email-domains-test.js @@ -1,200 +1,203 @@ -// Use of this source code is governed by the Apache License, Version 2.0 +// Use of this source code is governed by the Apache License, Version 2.0 // that can be found in the LICENSE file. const async = require('async'); + const { assertFails } = require("@firebase/rules-unit-testing"); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown, } = require("./test_utils/test-app-utils"); + const { - allowedEmailDomains, getAllowedEmailUser, passwordSignInProviderId, - getDeniedEmailUser, googleSignInProviderId + allowedEmailDomains, getAllowedEmailUser, passwordSignInProviderId, + getDeniedEmailUser, googleSignInProviderId } = require("./test_utils/test-data"); describe("", async () => { - const collection = "allowed_email_domains"; - const domain = { "test.com": {} }; - - const users = [ - { - 'describe': 'Authenticated with a password and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': await getApplicationWith(null), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - ]; - - before(async () => { - await setupTestDatabaseWith(allowedEmailDomains); - }); - - describe("Allowed email domains collection rules", () => { - async.forEach(users, (user, callback) => { - describe(user.describe, function () { - let canCreateDescription = user.can.create ? - "allows to create an allowed email domain" : - "does not allow creating an allowed email domain"; - let canReadDescription = user.can.read ? - "allows reading allowed email domains" : - "does not allow reading an allowed email domains"; - let canUpdateDescription = user.can.update ? - "allows to update an allowed email domain" : - "does not allow updating an allowed email domain"; - let canDeleteDescription = user.can.delete ? - "allows to delete an allowed email domain" : - "does not allow deleting an allowed email domain"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).add(domain); - - if (user.can.create) { - await assertSucceeds(createPromise) - } else { - await assertFails(createPromise) - } - }); + const collection = "allowed_email_domains"; + const domain = { "test.com": {} }; - it(canReadDescription, async () => { - const readPromise = user.app.collection(collection).get(); + const users = [ + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': await getApplicationWith(null), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; - if (user.can.read) { - await assertSucceeds(readPromise) - } else { - await assertFails(readPromise) - } - }); + before(async () => { + await setupTestDatabaseWith(allowedEmailDomains); + }); - it(canUpdateDescription, async () => { - const updatePromise = user.app - .collection(collection) - .doc("gmail.com") - .update({ test: "updated" }); - - if (user.can.update) { - await assertSucceeds(updatePromise) - } else { - await assertFails(updatePromise) - } - }); + describe("Allowed email domains collection rules", () => { + async.forEach(users, (user, callback) => { + describe(user.describe, function () { + let canCreateDescription = user.can.create ? + "allows to create an allowed email domain" : + "does not allow creating an allowed email domain"; + let canReadDescription = user.can.read ? + "allows reading allowed email domains" : + "does not allow reading an allowed email domains"; + let canUpdateDescription = user.can.update ? + "allows to update an allowed email domain" : + "does not allow updating an allowed email domain"; + let canDeleteDescription = user.can.delete ? + "allows to delete an allowed email domain" : + "does not allow deleting an allowed email domain"; - it(canDeleteDescription, async () => { - const deletePromise = - user.app.collection(collection).doc("gmail.com").delete(); + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).add(domain); - if (user.can.delete) { - await assertSucceeds(deletePromise) - } else { - await assertFails(deletePromise) - } + if (user.can.create) { + await assertSucceeds(createPromise) + } else { + await assertFails(createPromise) + } + }); + + it(canReadDescription, async () => { + const readPromise = user.app.collection(collection).get(); + + if (user.can.read) { + await assertSucceeds(readPromise) + } else { + await assertFails(readPromise) + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = user.app + .collection(collection) + .doc("gmail.com") + .update({ test: "updated" }); + + if (user.can.update) { + await assertSucceeds(updatePromise) + } else { + await assertFails(updatePromise) + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = + user.app.collection(collection).doc("gmail.com").delete(); + + if (user.can.delete) { + await assertSucceeds(deletePromise) + } else { + await assertFails(deletePromise) + } + }); + }); + callback(); }); - }); - callback(); }); - }); - after(async () => { - await tearDown(); - }); + after(async () => { + await tearDown(); + }); }); diff --git a/metrics/firebase/test/firestore/rules/build-days-test.js b/metrics/firebase/test/firestore/rules/build-days-test.js index 5ca621fb1..3b32b91af 100644 --- a/metrics/firebase/test/firestore/rules/build-days-test.js +++ b/metrics/firebase/test/firestore/rules/build-days-test.js @@ -2,197 +2,355 @@ // that can be found in the LICENSE file. const async = require('async'); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown, } = require("./test_utils/test-app-utils"); -const { assertFails, assertSucceeds } = require("@firebase/rules-unit-testing"); + +const {assertFails, assertSucceeds} = require("@firebase/rules-unit-testing"); + +function test(users) { + async.forEach(users, (user, callback) => { + describe(user.describe, () => { + let canCreateDescription = user.can.create ? + "allows creating a build day" : "does not allow creating a build day"; + let canReadDescription = user.can.read ? + "allows reading build days" : "does not allow reading build days"; + let canUpdateDescription = user.can.update ? + "allows updating a build day" : "does not allow updating a build day"; + let canDeleteDescription = user.can.delete ? + "allows deleting a build day" : "does not allow deleting a build day"; + + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).add(getBuildDay()); + + if (user.can.create) { + await assertSucceeds(createPromise) + } else { + await assertFails(createPromise) + } + }); + + it(canReadDescription, async () => { + const readPromise = user.app.collection(collection).get(); + + if (user.can.read) { + await assertSucceeds(readPromise) + } else { + await assertFails(readPromise) + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = + user.app.collection(collection).doc("1").update({projectId: "3"}); + + if (user.can.update) { + await assertSucceeds(updatePromise) + } else { + await assertFails(updatePromise) + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = + user.app.collection(collection).doc("1").delete(); + + if (user.can.delete) { + await assertSucceeds(deletePromise) + } else { + await assertFails(deletePromise) + } + }); + }); + callback(); + }); +} + const { - passwordSignInProviderId, - googleSignInProviderId, - getAllowedEmailUser, - getDeniedEmailUser, - buildDays, - getBuildDay, - allowedEmailDomains, + passwordSignInProviderId, + googleSignInProviderId, + getAllowedEmailUser, + getDeniedEmailUser, + buildDays, + getBuildDay, + allowedEmailDomains, + getAnonymousUser, + featureConfigEnabled, + featureConfigDisabled } = require("./test_utils/test-data"); +const collection = "build_days"; + describe("", async () => { - const collection = "build_days"; - - const users = [ - { - 'describe': 'Authenticated with a password and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': await getApplicationWith(null), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - ]; - - before(async () => { - await setupTestDatabaseWith(Object.assign({}, buildDays, allowedEmailDomains)); - }); - - describe("Build days collection rules", () => { - async.forEach(users, (user, callback) => { - describe(user.describe, () => { - let canCreateDescription = user.can.create ? - "allows creating a build day" : "does not allow creating a build day"; - let canReadDescription = user.can.read ? - "allows reading build days" : "does not allow reading build days"; - let canUpdateDescription = user.can.update ? - "allows updating a build day" : "does not allow updating a build day"; - let canDeleteDescription = user.can.delete ? - "allows deleting a build day" : "does not allow deleting a build day"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).add(getBuildDay()); - - if (user.can.create) { - await assertSucceeds(createPromise) - } else { - await assertFails(createPromise) - } - }); + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); - it(canReadDescription, async () => { - const readPromise = user.app.collection(collection).get(); + const users = [ + { + 'describe': 'Authenticated as an anonymous user, public dashboard is enabled', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': await getApplicationWith(null), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; - if (user.can.read) { - await assertSucceeds(readPromise) - } else { - await assertFails(readPromise) - } + describe("Build days collection rules, public dashboard is enabled", () => { + before(async () => { + await setupTestDatabaseWith(Object.assign({}, buildDays, allowedEmailDomains, featureConfigEnabled)); }); - it(canUpdateDescription, async () => { - const updatePromise = - user.app.collection(collection).doc("1").update({ projectId: "3" }); + test(users); + }); - if (user.can.update) { - await assertSucceeds(updatePromise) - } else { - await assertFails(updatePromise) - } - }); + after(async () => { + await tearDown(); + }); +}); + +describe("", async () => { + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); - it(canDeleteDescription, async () => { - const deletePromise = - user.app.collection(collection).doc("1").delete(); + const users = [ + { + 'describe': 'Authenticated as an anonymous user, public dashboard is disabled', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': await getApplicationWith(null), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; - if (user.can.delete) { - await assertSucceeds(deletePromise) - } else { - await assertFails(deletePromise) - } + describe("Build days collection rules, public dashboard is disabled", () => { + before(async () => { + await setupTestDatabaseWith(Object.assign({}, buildDays, allowedEmailDomains, featureConfigDisabled)); }); - }); - callback(); + + test(users); + }); + + after(async () => { + await tearDown(); }); - }); - after(async () => { - await tearDown(); - }); }); diff --git a/metrics/firebase/test/firestore/rules/builds-test.js b/metrics/firebase/test/firestore/rules/builds-test.js index 324c05e5c..efb9f6294 100644 --- a/metrics/firebase/test/firestore/rules/builds-test.js +++ b/metrics/firebase/test/firestore/rules/builds-test.js @@ -2,536 +2,699 @@ // that can be found in the LICENSE file. const async = require('async'); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown, } = require("./test_utils/test-app-utils"); -const { assertFails, assertSucceeds } = require("@firebase/rules-unit-testing"); + +const {assertFails, assertSucceeds} = require("@firebase/rules-unit-testing"); + const { - passwordSignInProviderId, - googleSignInProviderId, - getAllowedEmailUser, - getDeniedEmailUser, - builds, - getBuild, - allowedEmailDomains, - projects, + passwordSignInProviderId, + googleSignInProviderId, + getAllowedEmailUser, + getDeniedEmailUser, + builds, + getBuild, + allowedEmailDomains, + projects, + getAnonymousUser, + featureConfigEnabled, + featureConfigDisabled } = require("./test_utils/test-data"); + const firestore = require("firebase").firestore; +const collection = "build"; -describe("", async () => { - const passwordProviderAllowedEmailApp = await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ); - const unauthenticatedApp = await getApplicationWith(null); - const collection = "build"; - - const users = [ - { - 'describe': 'Authenticated with a password and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': unauthenticatedApp, - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - ]; - - before(async () => { - await setupTestDatabaseWith(Object.assign({}, builds, allowedEmailDomains, projects)); - }); - - describe("Build collection rules", () => { +async function test(users, passwordProviderAllowedEmailApp) { it("does not allow creating a build with not allowed fields", async () => { - let build = getBuild(); - build.test = "test"; + let build = getBuild(); + build.test = "test"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build with not existing project id", async () => { - let build = getBuild(); - build.projectId = "non-existing-id"; + let build = getBuild(); + build.projectId = "non-existing-id"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build with null projectId", async () => { - let build = getBuild(); - build.projectId = null; + let build = getBuild(); + build.projectId = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build when projectId is not a string", async () => { - let build = getBuild(); - build.projectId = 2; + let build = getBuild(); + build.projectId = 2; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build if the startedAt is null", async () => { - let build = getBuild(); - build.startedAt = null; + let build = getBuild(); + build.startedAt = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build if the startedAt is not a timestamp", async () => { - const build = getBuild(); - build.startedAt = Date(); + const build = getBuild(); + build.startedAt = Date(); - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds if the startedAt value is after the current timestamp", async () => { - let date = new Date(); - date.setDate(date.getDate() + 1); + let date = new Date(); + date.setDate(date.getDate() + 1); - let build = getBuild(); - build.startedAt = firestore.Timestamp.fromDate(date); + let build = getBuild(); + build.startedAt = firestore.Timestamp.fromDate(date); - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating builds with a successful build status and non-null integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.successful"; - build.duration = 10; + let build = getBuild(); + build.buildStatus = "BuildStatus.successful"; + build.duration = 10; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating builds with a failed build status and non-null integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.failed"; - build.duration = 10; + let build = getBuild(); + build.buildStatus = "BuildStatus.failed"; + build.duration = 10; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating builds with an unknown build status and non-null integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.unknown"; - build.duration = 10; + let build = getBuild(); + build.buildStatus = "BuildStatus.unknown"; + build.duration = 10; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating builds with a null build status and an integer duration", async () => { - let build = getBuild(); - build.buildStatus = null; - build.duration = 10; + let build = getBuild(); + build.buildStatus = null; + build.duration = 10; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with a successful build status and a null duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.successful"; - build.duration = null; + let build = getBuild(); + build.buildStatus = "BuildStatus.successful"; + build.duration = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with a failed build status and a null duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.failed"; - build.duration = null; + let build = getBuild(); + build.buildStatus = "BuildStatus.failed"; + build.duration = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with an unknown build status and a null duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.unknown"; - build.duration = null; + let build = getBuild(); + build.buildStatus = "BuildStatus.unknown"; + build.duration = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with a null build status and a null duration", async () => { - let build = getBuild(); - build.buildStatus = null; - build.duration = null; + let build = getBuild(); + build.buildStatus = null; + build.duration = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with a successful build status and a non integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.successful"; - build.duration = "123"; + let build = getBuild(); + build.buildStatus = "BuildStatus.successful"; + build.duration = "123"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with a failed build status and a non integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.failed"; - build.duration = "123"; + let build = getBuild(); + build.buildStatus = "BuildStatus.failed"; + build.duration = "123"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with an unknown build status and a non integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.unknown"; - build.duration = "123"; + let build = getBuild(); + build.buildStatus = "BuildStatus.unknown"; + build.duration = "123"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with a null build status and a non-integer duration", async () => { - let build = getBuild(); - build.buildStatus = null; - build.duration = "123"; + let build = getBuild(); + build.buildStatus = null; + build.duration = "123"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating builds with an in-progress build status and a null duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.inProgress"; - build.duration = null; + let build = getBuild(); + build.buildStatus = "BuildStatus.inProgress"; + build.duration = null; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with an in-progress build status and an integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.inProgress"; - build.duration = 10; + let build = getBuild(); + build.buildStatus = "BuildStatus.inProgress"; + build.duration = 10; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating builds with an in-progress build status and a non-integer duration", async () => { - let build = getBuild(); - build.buildStatus = "BuildStatus.inProgress"; - build.duration = "test"; + let build = getBuild(); + build.buildStatus = "BuildStatus.inProgress"; + build.duration = "test"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build if the url is null", async () => { - let build = getBuild(); - build.url = null; + let build = getBuild(); + build.url = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build if the url is not a string", async () => { - let build = getBuild(); - build.url = 2; + let build = getBuild(); + build.url = 2; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating a build if the api url is null", async () => { - let build = getBuild(); - build.apiUrl = null; + let build = getBuild(); + build.apiUrl = null; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build if the api url is not a string", async () => { - let build = getBuild(); - build.apiUrl = 2; + let build = getBuild(); + build.apiUrl = 2; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build if the build number is not an int", async () => { - let build = getBuild(); - build.buildNumber = "2"; + let build = getBuild(); + build.buildNumber = "2"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build if the build number is null", async () => { - let build = getBuild(); - build.buildNumber = null; + let build = getBuild(); + build.buildNumber = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build with not valid build status value", async () => { - let build = getBuild(); - build.buildStatus = "test"; + let build = getBuild(); + build.buildStatus = "test"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating a build with null build status", async () => { - let build = getBuild(); - build.buildStatus = null; + let build = getBuild(); + build.buildStatus = null; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build when workflow name is not a string", async () => { - let build = getBuild(); - build.workflowName = 2; + let build = getBuild(); + build.workflowName = 2; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating a build when workflow name is null", async () => { - let build = getBuild(); - build.workflowName = null; + let build = getBuild(); + build.workflowName = null; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build when the coverage is grater then 1.0", async () => { - let build = getBuild(); - build.coverage = 1.1; + let build = getBuild(); + build.coverage = 1.1; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("does not allow creating a build when the coverage is less then 0.0", async () => { - let build = getBuild(); - build.coverage = -1.0; + let build = getBuild(); + build.coverage = -1.0; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); it("allows creating a build when the coverage is null", async () => { - let build = getBuild(); - build.coverage = null; + let build = getBuild(); + build.coverage = null; - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add(build) - ); + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add(build) + ); }); async.forEach(users, (user, callback) => { - describe(user.describe, () => { - let canCreateDescription = user.can.create ? - "allows creating a build" : "does not allow creating a build"; - let canReadDescription = user.can.read ? - "allows reading builds" : "does not allow reading builds"; - let canUpdateDescription = user.can.update ? - "allows updating a build" : "does not allow updating a build"; - let canDeleteDescription = user.can.delete ? - "allows deleting a build" : "does not allow deleting a build"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).add(getBuild()); - - if (user.can.create) { - await assertSucceeds(createPromise) - } else { - await assertFails(createPromise) - } + describe(user.describe, () => { + let canCreateDescription = user.can.create ? + "allows creating a build" : "does not allow creating a build"; + let canReadDescription = user.can.read ? + "allows reading builds" : "does not allow reading builds"; + let canUpdateDescription = user.can.update ? + "allows updating a build" : "does not allow updating a build"; + let canDeleteDescription = user.can.delete ? + "allows deleting a build" : "does not allow deleting a build"; + + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).add(getBuild()); + + if (user.can.create) { + await assertSucceeds(createPromise) + } else { + await assertFails(createPromise) + } + }); + + it(canReadDescription, async () => { + const readPromise = user.app.collection(collection).get(); + + if (user.can.read) { + await assertSucceeds(readPromise) + } else { + await assertFails(readPromise) + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = + user.app.collection(collection).doc("1").update({url: "updated"}); + + if (user.can.update) { + await assertSucceeds(updatePromise) + } else { + await assertFails(updatePromise) + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = + user.app.collection(collection).doc("1").delete(); + + if (user.can.delete) { + await assertSucceeds(deletePromise) + } else { + await assertFails(deletePromise) + } + }); }); + callback(); + }); +} - it(canReadDescription, async () => { - const readPromise = user.app.collection(collection).get(); - - if (user.can.read) { - await assertSucceeds(readPromise) - } else { - await assertFails(readPromise) - } +describe("", async () => { + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ); + const unauthenticatedApp = await getApplicationWith(null); + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); + + const users = [ + { + 'describe': 'Authenticated as an anonymous user, public dashboard is enabled', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': unauthenticatedApp, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; + + + describe("Build collection rules, public dashboard is enabled", () => { + before(async () => { + await setupTestDatabaseWith( + Object.assign({}, builds, allowedEmailDomains, projects, featureConfigEnabled)); }); - it(canUpdateDescription, async () => { - const updatePromise = - user.app.collection(collection).doc("1").update({ url: "updated" }); - - if (user.can.update) { - await assertSucceeds(updatePromise) - } else { - await assertFails(updatePromise) - } - }); + test(users, passwordProviderAllowedEmailApp); + }); - it(canDeleteDescription, async () => { - const deletePromise = - user.app.collection(collection).doc("1").delete(); + after(async () => { + await tearDown(); + }); +}); - if (user.can.delete) { - await assertSucceeds(deletePromise) - } else { - await assertFails(deletePromise) - } +describe("", async () => { + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ); + const unauthenticatedApp = await getApplicationWith(null); + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); + + const users = [ + { + 'describe': 'Authenticated as an anonymous user, public dashboard is disabled', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': unauthenticatedApp, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; + + describe("Build collection rules, public dashboard is disabled", () => { + before(async () => { + await setupTestDatabaseWith(Object.assign({}, builds, allowedEmailDomains, projects, featureConfigDisabled)); }); - }); - callback(); + + test(users, passwordProviderAllowedEmailApp); }); - }); - after(async () => { - await tearDown(); - }); + after(async () => { + await tearDown(); + }); }); diff --git a/metrics/firebase/test/firestore/rules/feature-config-test.js b/metrics/firebase/test/firestore/rules/feature-config-test.js index 484a592d6..4c8874923 100644 --- a/metrics/firebase/test/firestore/rules/feature-config-test.js +++ b/metrics/firebase/test/firestore/rules/feature-config-test.js @@ -2,213 +2,215 @@ // that can be found in the LICENSE file. const async = require("async"); -const { assertFails, assertSucceeds } = require("@firebase/rules-unit-testing"); + +const {assertFails, assertSucceeds} = require("@firebase/rules-unit-testing"); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown, } = require("./test_utils/test-app-utils"); const { - featureConfig, - allowedEmailDomains, - passwordSignInProviderId, - googleSignInProviderId, - getAllowedEmailUser, - getDeniedEmailUser, + featureConfigEnabled, + allowedEmailDomains, + passwordSignInProviderId, + googleSignInProviderId, + getAllowedEmailUser, + getDeniedEmailUser, } = require("./test_utils/test-data"); describe("", async () => { - const unauthenticatedApp = await getApplicationWith(null); - const collection = "feature_config"; - const config = { config: {} }; - - const users = [ - { - 'describe': 'Authenticated with a password and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': unauthenticatedApp, - 'can': { - 'create': false, - 'read': true, - 'update': false, - 'delete': false, - } - }, - ]; - - before(async () => { - await setupTestDatabaseWith( - Object.assign({}, featureConfig, allowedEmailDomains) - ); - }); - - describe("Feature config collection rules", () => { - async.forEach(users, (user, callback) => { - describe(user.describe, function () { - let canCreateDescription = user.can.create - ? "allows creating a feature config" - : "does not allow creating a feature config"; - let canReadDescription = user.can.read - ? "allows reading a feature config" - : "does not allow reading a feature configs"; - let canUpdateDescription = user.can.update - ? "allows updating a feature config" - : "does not allow updating a feature config"; - let canDeleteDescription = user.can.delete - ? "allows deleting a feature config" - : "does not allow deleting a feature config"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).add(config); - - if (user.can.create) { - await assertSucceeds(createPromise); - } else { - await assertFails(createPromise); - } - }); - - it(canReadDescription, async () => { - const getPromise = user.app - .collection(collection) - .doc(collection) - .get(); - - if (user.can.read) { - await assertSucceeds(getPromise); - } else { - await assertFails(getPromise); - } - }); - - it(canUpdateDescription, async () => { - const updatePromise = user.app - .collection(collection) - .doc(collection) - .update(config); - - if (user.can.update) { - await assertSucceeds(updatePromise); - } else { - await assertFails(updatePromise); - } - }); + const unauthenticatedApp = await getApplicationWith(null); + const collection = "feature_config"; + const config = {config: {}}; + + const users = [ + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': unauthenticatedApp, + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + ]; + + before(async () => { + await setupTestDatabaseWith( + Object.assign({}, featureConfigEnabled, allowedEmailDomains) + ); + }); - it(canDeleteDescription, async () => { - const deletePromise = user.app - .collection(collection) - .doc(collection) - .delete(); - - if (user.can.delete) { - await assertSucceeds(deletePromise); - } else { - await assertFails(deletePromise); - } + describe("Feature config collection rules", () => { + async.forEach(users, (user, callback) => { + describe(user.describe, function () { + let canCreateDescription = user.can.create + ? "allows creating a feature config" + : "does not allow creating a feature config"; + let canReadDescription = user.can.read + ? "allows reading a feature config" + : "does not allow reading a feature configs"; + let canUpdateDescription = user.can.update + ? "allows updating a feature config" + : "does not allow updating a feature config"; + let canDeleteDescription = user.can.delete + ? "allows deleting a feature config" + : "does not allow deleting a feature config"; + + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).add(config); + + if (user.can.create) { + await assertSucceeds(createPromise); + } else { + await assertFails(createPromise); + } + }); + + it(canReadDescription, async () => { + const getPromise = user.app + .collection(collection) + .doc(collection) + .get(); + + if (user.can.read) { + await assertSucceeds(getPromise); + } else { + await assertFails(getPromise); + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = user.app + .collection(collection) + .doc(collection) + .update(config); + + if (user.can.update) { + await assertSucceeds(updatePromise); + } else { + await assertFails(updatePromise); + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = user.app + .collection(collection) + .doc(collection) + .delete(); + + if (user.can.delete) { + await assertSucceeds(deletePromise); + } else { + await assertFails(deletePromise); + } + }); + }); + + callback(); }); - }); - - callback(); }); - }); - after(async () => { - await tearDown(); - }); + after(async () => { + await tearDown(); + }); }); diff --git a/metrics/firebase/test/firestore/rules/project-groups-test.js b/metrics/firebase/test/firestore/rules/project-groups-test.js index 94fd89135..dfd785f01 100644 --- a/metrics/firebase/test/firestore/rules/project-groups-test.js +++ b/metrics/firebase/test/firestore/rules/project-groups-test.js @@ -2,333 +2,497 @@ // that can be found in the LICENSE file. const async = require('async'); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown, } = require("./test_utils/test-app-utils"); -const { assertFails, assertSucceeds } = require("@firebase/rules-unit-testing"); + +const {assertFails, assertSucceeds} = require("@firebase/rules-unit-testing"); + const { - projectGroups, - getAllowedEmailUser, - getDeniedEmailUser, - googleSignInProviderId, - passwordSignInProviderId, - allowedEmailDomains, - getProjectGroup, + projectGroups, + getAllowedEmailUser, + getDeniedEmailUser, + googleSignInProviderId, + passwordSignInProviderId, + allowedEmailDomains, + getProjectGroup, + getAnonymousUser, + featureConfigEnabled, + featureConfigDisabled } = require("./test_utils/test-data"); -describe("", async function () { - const passwordProviderAllowedEmailApp = await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ); - const unauthenticatedApp = await getApplicationWith(null); - const collection = "project_groups"; - - const users = [ - { - 'describe': 'Authenticated with a password and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': true, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': true, - } - }, - { - 'describe': 'Authenticated with a password and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': true, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': true, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': true, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': unauthenticatedApp, - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - ]; - - before(async () => { - await setupTestDatabaseWith( - Object.assign({}, projectGroups, allowedEmailDomains) - ); - }); +const collection = "project_groups"; - describe("Project groups collection rules", () => { +function test(users, passwordProviderAllowedEmailApp) { it("does not allow creating a project group with not allowed fields", async () => { - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add({ - name: "name", - projectIds: [], - notAllowedField: "test", - }) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add({ + name: "name", + projectIds: [], + notAllowedField: "test", + }) + ); }); it("does not allow creating a project group without a name", async () => { - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add({ - projectIds: [], - }) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add({ + projectIds: [], + }) + ); }); it("does not allow creating a project group with a name having other than a string value", async () => { - let names = [false, 123, []]; - - names.forEach(async (name) => { - await assertFails( - passwordProviderAllowedEmailApp - .collection(collection) - .add({ name, projectIds: [] }) - ); - }); + let names = [false, 123, []]; + + names.forEach(async (name) => { + await assertFails( + passwordProviderAllowedEmailApp + .collection(collection) + .add({name, projectIds: []}) + ); + }); }); it("does not allow creating a project group with a projectIds having other than a list value", () => { - let projectIdsValues = [123, false, "test"]; - - projectIdsValues.forEach(async (projectIds) => { - await assertFails( - passwordProviderAllowedEmailApp - .collection(collection) - .add({ name: "test", projectIds }) - ); - }); + let projectIdsValues = [123, false, "test"]; + + projectIdsValues.forEach(async (projectIds) => { + await assertFails( + passwordProviderAllowedEmailApp + .collection(collection) + .add({name: "test", projectIds}) + ); + }); }); it("allows to update a project group with name size less or equal than 255", async () => { - const testName = "testName"; - - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ - name: testName, - projectIds: [], - }) - ); + const testName = "testName"; + + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ + name: testName, + projectIds: [], + }) + ); }); it("allows to update a project group with project ids length less or equal than 20", async () => { - const testProjectIds = ["1", "2"]; - - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ - name: "name", - projectIds: testProjectIds, - }) - ); + const testProjectIds = ["1", "2"]; + + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ + name: "name", + projectIds: testProjectIds, + }) + ); }); it("allows to create a project group with name size less or equal than 255", async () => { - const testName = "testName"; - - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add({ - name: testName, - projectIds: [], - }) - ); + const testName = "testName"; + + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add({ + name: testName, + projectIds: [], + }) + ); }); it("allows to create a project group with project ids length less or equal than 20", async () => { - const testProjectIds = ["1", "2"]; - - await assertSucceeds( - passwordProviderAllowedEmailApp.collection(collection).add({ - name: "name", - projectIds: testProjectIds, - }) - ); + const testProjectIds = ["1", "2"]; + + await assertSucceeds( + passwordProviderAllowedEmailApp.collection(collection).add({ + name: "name", + projectIds: testProjectIds, + }) + ); }); it("does not allow updating a project group with name size greater than 255", async () => { - const testName = "a".repeat(256); - - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ - name: testName, - projectIds: [], - }) - ); + const testName = "a".repeat(256); + + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ + name: testName, + projectIds: [], + }) + ); }); it("does not allow updating a project group with project ids length greater than 20", async () => { - const testProjectIds = [...Array(21)].map((_, i) => `${i}`); - - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ - name: "name", - projectIds: testProjectIds, - }) - ); + const testProjectIds = [...Array(21)].map((_, i) => `${i}`); + + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).doc("2").update({ + name: "name", + projectIds: testProjectIds, + }) + ); }); it("does not allow creating a project group with name size greater than 255", async () => { - const testName = "a".repeat(256); - - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add({ - name: testName, - projectIds: [], - }) - ); + const testName = "a".repeat(256); + + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add({ + name: testName, + projectIds: [], + }) + ); }); it("does not allow creating a project group with project ids length greater than 20", async () => { - const testProjectIds = [...Array(21)].map((_, i) => `${i}`); - - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add({ - name: "name", - projectIds: testProjectIds, - }) - ); + const testProjectIds = [...Array(21)].map((_, i) => `${i}`); + + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add({ + name: "name", + projectIds: testProjectIds, + }) + ); }); async.forEach(users, (user, callback) => { - describe(user.describe, () => { - let canCreateDescription = user.can.create ? - "allows to create a project group" : "does not allow creating a project group"; - let canReadDescription = user.can.read ? - "allows reading project groups" : "does not allow reading project groups"; - let canUpdateDescription = user.can.update ? - "allows to update a project group" : "does not allow updating a project group"; - let canDeleteDescription = user.can.delete ? - "allows to delete a project group" : "does not allow deleting a project group"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).add(getProjectGroup()); - - if (user.can.create) { - await assertSucceeds(createPromise) - } else { - await assertFails(createPromise) - } + describe(user.describe, () => { + let canCreateDescription = user.can.create ? + "allows to create a project group" : "does not allow creating a project group"; + let canReadDescription = user.can.read ? + "allows reading project groups" : "does not allow reading project groups"; + let canUpdateDescription = user.can.update ? + "allows to update a project group" : "does not allow updating a project group"; + let canDeleteDescription = user.can.delete ? + "allows to delete a project group" : "does not allow deleting a project group"; + + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).add(getProjectGroup()); + + if (user.can.create) { + await assertSucceeds(createPromise) + } else { + await assertFails(createPromise) + } + }); + + it(canReadDescription, async () => { + const readPromise = user.app.collection(collection).get(); + + if (user.can.read) { + await assertSucceeds(readPromise) + } else { + await assertFails(readPromise) + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = user.app.collection(collection) + .doc("2") + .update(getProjectGroup()); + + if (user.can.update) { + await assertSucceeds(updatePromise) + } else { + await assertFails(updatePromise) + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = user.app.collection(collection).doc("1").delete(); + + if (user.can.delete) { + await assertSucceeds(deletePromise) + } else { + await assertFails(deletePromise) + } + }); }); + callback(); + }); +} - it(canReadDescription, async () => { - const readPromise = user.app.collection(collection).get(); - - if (user.can.read) { - await assertSucceeds(readPromise) - } else { - await assertFails(readPromise) - } +describe("", async function () { + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ); + const unauthenticatedApp = await getApplicationWith(null); + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); + + const users = [ + { + 'describe': 'Authenticated as an anonymous user', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': unauthenticatedApp, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; + + describe("Project groups collection rules, public dashboard is enabled", () => { + before(async () => { + await setupTestDatabaseWith( + Object.assign({}, projectGroups, allowedEmailDomains, featureConfigEnabled) + ); }); - it(canUpdateDescription, async () => { - const updatePromise = user.app.collection(collection) - .doc("2") - .update(getProjectGroup()); - - if (user.can.update) { - await assertSucceeds(updatePromise) - } else { - await assertFails(updatePromise) - } - }); + test(users, passwordProviderAllowedEmailApp); + }); - it(canDeleteDescription, async () => { - const deletePromise = user.app.collection(collection).doc("1").delete(); + after(async () => { + await tearDown(); + }); +}); - if (user.can.delete) { - await assertSucceeds(deletePromise) - } else { - await assertFails(deletePromise) - } +describe("", async function () { + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ); + const unauthenticatedApp = await getApplicationWith(null); + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); + + const users = [ + { + 'describe': 'Authenticated as an anonymous user', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': true, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': unauthenticatedApp, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; + + describe("Project groups collection rules, public dashboard is disabled", () => { + before(async () => { + await setupTestDatabaseWith( + Object.assign({}, projectGroups, allowedEmailDomains, featureConfigDisabled) + ); }); - }); - callback(); + + test(users, passwordProviderAllowedEmailApp); }); - }); - after(async () => { - await tearDown(); - }); + after(async () => { + await tearDown(); + }); }); + diff --git a/metrics/firebase/test/firestore/rules/projects-test.js b/metrics/firebase/test/firestore/rules/projects-test.js index 07da8bed6..d24f579cc 100644 --- a/metrics/firebase/test/firestore/rules/projects-test.js +++ b/metrics/firebase/test/firestore/rules/projects-test.js @@ -2,212 +2,373 @@ // that can be found in the LICENSE file. const async = require('async'); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown, } = require("./test_utils/test-app-utils"); -const { assertFails, assertSucceeds } = require("@firebase/rules-unit-testing"); + +const {assertFails, assertSucceeds} = require("@firebase/rules-unit-testing"); + const { - project, - projects, - getAllowedEmailUser, - getDeniedEmailUser, - passwordSignInProviderId, - googleSignInProviderId, - allowedEmailDomains, + project, + projects, + getAllowedEmailUser, + getDeniedEmailUser, + passwordSignInProviderId, + googleSignInProviderId, + allowedEmailDomains, + getAnonymousUser, + featureConfigEnabled, + featureConfigDisabled, } = require("./test_utils/test-data"); -describe("", async function () { - const unauthenticatedApp = await getApplicationWith(null); - const passwordProviderAllowedEmailApp = await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ); - const collection = "projects"; - - const users = [ - { - 'describe': 'Authenticated with a password and allowed email domain user with a verified email', - 'app': passwordProviderAllowedEmailApp, - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': true, - 'read': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': unauthenticatedApp, - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - ]; - - before(async () => { - await setupTestDatabaseWith( - Object.assign({}, projects, allowedEmailDomains) - ); - }); +const collection = "projects"; - describe("Projects collection rules", () => { +function test(users, unauthenticatedApp, passwordProviderAllowedEmailApp) { it("does not allow creating a project with not allowed fields", async () => { - await assertFails( - unauthenticatedApp.collection(collection).add({ - name: "name", - test: "test", - }) - ); + await assertFails( + unauthenticatedApp.collection(collection).add({ + name: "name", + test: "test", + }) + ); }); it("does not allow creating a project without a name", async () => { - await assertFails(passwordProviderAllowedEmailApp.collection(collection).add({})); + await assertFails(passwordProviderAllowedEmailApp.collection(collection).add({})); }); async.forEach(users, (user, callback) => { - describe(user.describe, () => { - let canCreateDescription = user.can.create ? - "allows to create a project" : "does not allow creating a project"; - let canReadDescription = user.can.read ? - "allows reading projects" : "does not allow reading projects"; - let canUpdateDescription = user.can.update ? - "allows to update a project" : "does not allow updating a project"; - let canDeleteDescription = user.can.delete ? - "allows to delete a project" : "does not allow deleting a project"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).add(project); - - if (user.can.create) { - await assertSucceeds(createPromise) - } else { - await assertFails(createPromise) - } - }); + describe(user.describe, () => { + let canCreateDescription = user.can.create ? + "allows to create a project" : "does not allow creating a project"; + let canReadDescription = user.can.read ? + "allows reading projects" : "does not allow reading projects"; + let canUpdateDescription = user.can.update ? + "allows to update a project" : "does not allow updating a project"; + let canDeleteDescription = user.can.delete ? + "allows to delete a project" : "does not allow deleting a project"; + + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).add(project); - it(canReadDescription, async () => { - const readPromise = user.app.collection(collection).get(); + if (user.can.create) { + await assertSucceeds(createPromise) + } else { + await assertFails(createPromise) + } + }); - if (user.can.read) { - await assertSucceeds(readPromise) - } else { - await assertFails(readPromise) - } + it(canReadDescription, async () => { + const readPromise = user.app.collection(collection).get(); + + if (user.can.read) { + await assertSucceeds(readPromise) + } else { + await assertFails(readPromise) + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = user.app.collection(collection).doc("1").update(project); + + if (user.can.update) { + await assertSucceeds(updatePromise) + } else { + await assertFails(updatePromise) + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = user.app.collection(collection).doc("1").delete(); + + if (user.can.delete) { + await assertSucceeds(deletePromise) + } else { + await assertFails(deletePromise) + } + }); }); + callback(); + }); +} - it(canUpdateDescription, async () => { - const updatePromise = user.app.collection(collection).doc("1").update(project); +describe("", async function () { + const unauthenticatedApp = await getApplicationWith(null); + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ); + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); - if (user.can.update) { - await assertSucceeds(updatePromise) - } else { - await assertFails(updatePromise) - } + const users = [ + { + 'describe': 'Authenticated as an anonymous user', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': true, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': passwordProviderAllowedEmailApp, + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': unauthenticatedApp, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; + + describe("Projects collection rules, public dashboard is enabled", () => { + before(async () => { + await setupTestDatabaseWith( + Object.assign({}, projects, allowedEmailDomains, featureConfigEnabled) + ); }); - it(canDeleteDescription, async () => { - const deletePromise = user.app.collection(collection).doc("1").delete(); + test(users, unauthenticatedApp, passwordProviderAllowedEmailApp); + }); + + after(async () => { + await tearDown(); + }); +}); - if (user.can.delete) { - await assertSucceeds(deletePromise) - } else { - await assertFails(deletePromise) - } +describe("", async function () { + const unauthenticatedApp = await getApplicationWith(null); + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ); + const anonymousSignIn = await getApplicationWith(getAnonymousUser()); + + const users = [ + { + 'describe': 'Authenticated as an anonymous user', + 'app': anonymousSignIn, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': passwordProviderAllowedEmailApp, + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': true, + 'read': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': unauthenticatedApp, + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; + + describe("Projects collection rules, public dashboard is disabled", () => { + before(async () => { + await setupTestDatabaseWith( + Object.assign({}, projects, allowedEmailDomains, featureConfigDisabled) + ); }); - }); - callback(); + + test(users, unauthenticatedApp, passwordProviderAllowedEmailApp); }); - }); - after(async () => { - await tearDown(); - }); + after(async () => { + await tearDown(); + }); }); diff --git a/metrics/firebase/test/firestore/rules/tasks-test.js b/metrics/firebase/test/firestore/rules/tasks-test.js index ca72663fa..0c0d64a99 100644 --- a/metrics/firebase/test/firestore/rules/tasks-test.js +++ b/metrics/firebase/test/firestore/rules/tasks-test.js @@ -2,198 +2,203 @@ // that can be found in the LICENSE file. const async = require('async'); -const { assertFails } = require("@firebase/rules-unit-testing"); + +const {assertFails, assertSucceeds} = require("@firebase/rules-unit-testing"); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown } = require("./test_utils/test-app-utils"); + const { - allowedEmailDomains, getAllowedEmailUser, passwordSignInProviderId, - getDeniedEmailUser, googleSignInProviderId, tasks, getTask + allowedEmailDomains, getAllowedEmailUser, passwordSignInProviderId, + getDeniedEmailUser, googleSignInProviderId, tasks, getTask, + featureConfigEnabled } = require("./test_utils/test-data"); describe("", async () => { - const collection = "tasks"; - - const users = [ - { - 'describe': 'Authenticated with a password and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with a verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with a verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and allowed email domain user with not verified email', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with google and not allowed email domain user with not verified email', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': await getApplicationWith(null), - 'can': { - 'create': false, - 'read': false, - 'update': false, - 'delete': false, - } - }, - ]; - - before(async () => { - await setupTestDatabaseWith(Object.assign({}, tasks, allowedEmailDomains)); - }); - - describe("Tasks collection rules", () => { - async.forEach(users, (user, callback) => { - describe(user.describe, function () { - let canCreateDescription = user.can.create ? - "allows creating a task" : - "does not allow creating a task"; - let canReadDescription = user.can.read ? - "allows reading tasks" : - "does not allow reading tasks"; - let canUpdateDescription = user.can.update ? - "allows updating a task" : - "does not allow updating a task"; - let canDeleteDescription = user.can.delete ? - "allows deleting a task" : - "does not allow deleting a task"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).add(getTask()); - - if (user.can.create) { - await assertSucceeds(createPromise) - } else { - await assertFails(createPromise) - } - }); + const collection = "tasks"; - it(canReadDescription, async () => { - const readPromise = user.app.collection(collection).get(); + const users = [ + { + 'describe': 'Authenticated with a password and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with a verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with a verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and allowed email domain user with not verified email', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with google and not allowed email domain user with not verified email', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': await getApplicationWith(null), + 'can': { + 'create': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + ]; - if (user.can.read) { - await assertSucceeds(readPromise) - } else { - await assertFails(readPromise) - } + describe("Tasks collection rules, public dashboard is enabled", () => { + before(async () => { + await setupTestDatabaseWith( + Object.assign({}, tasks, allowedEmailDomains, featureConfigEnabled)); }); - it(canUpdateDescription, async () => { - const updatePromise = user.app - .collection(collection) - .doc("1") - .update({ context: "updated" }); - - if (user.can.update) { - await assertSucceeds(updatePromise) - } else { - await assertFails(updatePromise) - } - }); + async.forEach(users, (user, callback) => { + describe(user.describe, function () { + let canCreateDescription = user.can.create ? + "allows creating a task" : + "does not allow creating a task"; + let canReadDescription = user.can.read ? + "allows reading tasks" : + "does not allow reading tasks"; + let canUpdateDescription = user.can.update ? + "allows updating a task" : + "does not allow updating a task"; + let canDeleteDescription = user.can.delete ? + "allows deleting a task" : + "does not allow deleting a task"; + + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).add(getTask()); - it(canDeleteDescription, async () => { - const deletePromise = - user.app.collection(collection).doc("1").delete(); + if (user.can.create) { + await assertSucceeds(createPromise) + } else { + await assertFails(createPromise) + } + }); - if (user.can.delete) { - await assertSucceeds(deletePromise) - } else { - await assertFails(deletePromise) - } + it(canReadDescription, async () => { + const readPromise = user.app.collection(collection).get(); + + if (user.can.read) { + await assertSucceeds(readPromise) + } else { + await assertFails(readPromise) + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = user.app + .collection(collection) + .doc("1") + .update({context: "updated"}); + + if (user.can.update) { + await assertSucceeds(updatePromise) + } else { + await assertFails(updatePromise) + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = + user.app.collection(collection).doc("1").delete(); + + if (user.can.delete) { + await assertSucceeds(deletePromise) + } else { + await assertFails(deletePromise) + } + }); + }); + callback(); }); - }); - callback(); }); - }); - after(async () => { - await tearDown(); - }); + after(async () => { + await tearDown(); + }); }); diff --git a/metrics/firebase/test/firestore/rules/test_utils/test-data.js b/metrics/firebase/test/firestore/rules/test_utils/test-data.js index 9aa26aac5..a73b58c4c 100644 --- a/metrics/firebase/test/firestore/rules/test_utils/test-data.js +++ b/metrics/firebase/test/firestore/rules/test_utils/test-data.js @@ -1,4 +1,4 @@ -// Use of this source code is governed by the Apache License, Version 2.0 +// Use of this source code is governed by the Apache License, Version 2.0 // that can be found in the LICENSE file. const cloneDeep = require("clone-deep"); @@ -80,9 +80,18 @@ const allowedEmailDomains = { "allowed_email_domains/gmail.com": {}, }; -/** A test data for the feature config collection */ -const featureConfig = { - "feature_config/feature_config": {}, +/** A test data for the feature config collection with enabled public dashboard*/ +const featureConfigEnabled = { + "feature_config/feature_config": { + "isPublicDashboardEnabled": true + }, +}; + +/** A test data for the feature config collection with disabled public dashboard*/ +const featureConfigDisabled = { + "feature_config/feature_config": { + "isPublicDashboardEnabled": false + }, }; const allowedEmail = "test@gmail.com"; @@ -140,9 +149,13 @@ exports.builds = builds; exports.buildDays = buildDays; exports.userProfiles = userProfiles; exports.allowedEmailDomains = allowedEmailDomains; -exports.featureConfig = featureConfig; +exports.featureConfigDisabled = featureConfigDisabled; +exports.featureConfigEnabled = featureConfigEnabled; exports.tasks = tasks; +/** An anonymous sign in provider identifier */ +exports.anonymousSignInProviderId = "anonymous"; + /** An email and password sign in provider identifier */ exports.passwordSignInProviderId = "password"; @@ -154,11 +167,16 @@ exports.getAllowedEmailUser = function (signInProviderId, emailVerified, uid = " return getUser(allowedEmail, signInProviderId, emailVerified, uid); }; -/** Provides a firebase user with not allowed email, sign-in provider identifier, and uid*/ +/** Provides a firebase user with not allowed email, sign-in provider identifier, and uid */ exports.getDeniedEmailUser = function (signInProviderId, emailVerified, uid = "uid") { return getUser(deniedEmail, signInProviderId, emailVerified, uid); }; +/** Provides a firebase anonymous user with the given uid */ +exports.getAnonymousUser = function (uid = "uid") { + return getUser(null, "anonymous", null, uid); +}; + /** Get a test project group */ exports.getProjectGroup = function () { return cloneDeep(projectGroups["project_groups/1"]); diff --git a/metrics/firebase/test/firestore/rules/user-profiles-test.js b/metrics/firebase/test/firestore/rules/user-profiles-test.js index 6976ee8cb..65ef87170 100644 --- a/metrics/firebase/test/firestore/rules/user-profiles-test.js +++ b/metrics/firebase/test/firestore/rules/user-profiles-test.js @@ -2,353 +2,646 @@ // that can be found in the LICENSE file. const async = require('async'); + const { - setupTestDatabaseWith, - getApplicationWith, - tearDown, + setupTestDatabaseWith, + getApplicationWith, + tearDown, } = require("./test_utils/test-app-utils"); -const { assertFails, assertSucceeds } = require("@firebase/rules-unit-testing"); + +const {assertFails, assertSucceeds} = require("@firebase/rules-unit-testing"); + const { - passwordSignInProviderId, - googleSignInProviderId, - getAllowedEmailUser, - getDeniedEmailUser, - userProfiles, - getUserProfile, - allowedEmailDomains, + passwordSignInProviderId, + googleSignInProviderId, + getAllowedEmailUser, + getDeniedEmailUser, + userProfiles, + getUserProfile, + allowedEmailDomains, + getAnonymousUser, featureConfigDisabled, featureConfigEnabled, } = require("./test_utils/test-data"); -describe("", async () => { - const uid = "1"; - const collection = "user_profiles"; - const passwordProviderAllowedEmailApp = await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true, uid) - ) - - const users = [ - { - 'describe': 'Authenticated with a password, allowed email domain, and not a verified email user who is not an owner of the user profile', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password, allowed email domain, and not a verified email user who is an owner of the user profile', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, false, uid) - ), - 'can': { - 'create': true, - 'list': false, - 'get': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password, allowed email domain, and a verified email user who is not an owner of the user profile', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password, not allowed email domain, and not verified email user who is an owner of the user profile', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false, uid) - ), - 'can': { - 'create': true, - 'list': false, - 'get': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password, not allowed email domain, and a verified email user who is not an owner of the user profile', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password, not allowed email domain, and not a verified email user who is not an owner of the user profile', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, false) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password, allowed email domain, and a verified email user who is an owner of the user profile', - 'app': await getApplicationWith( - getAllowedEmailUser(passwordSignInProviderId, true, uid) - ), - 'can': { - 'create': true, - 'list': false, - 'get': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a password, not allowed email domain, and a verified email user who is an owner of the user profile', - 'app': await getApplicationWith( - getDeniedEmailUser(passwordSignInProviderId, true, uid) - ), - 'can': { - 'create': true, - 'list': false, - 'get': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, allowed email domain, and not a verified email user who is not an owner of the profile', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, allowed email domain, and not a verified email user who is an owner of the profile', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, false, uid) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, allowed email domain, and a verified email user who is not an owner of the profile', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, not allowed email domain, and not verified email user who is an owner of the profile', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false, uid) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, not allowed email domain, and a verified email user who is not an owner of the profile', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, not allowed email domain, and not a verified email user who is not an owner of the profile', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, false) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, allowed email domain, and a verified email user who is an owner of the profile', - 'app': await getApplicationWith( - getAllowedEmailUser(googleSignInProviderId, true, uid) - ), - 'can': { - 'create': true, - 'list': false, - 'get': true, - 'update': true, - 'delete': false, - } - }, - { - 'describe': 'Authenticated with a google, not allowed email domain, and a verified email user who is an owner of the profile', - 'app': await getApplicationWith( - getDeniedEmailUser(googleSignInProviderId, true, uid) - ), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - }, - { - 'describe': 'Unauthenticated user', - 'app': await getApplicationWith(null), - 'can': { - 'create': false, - 'list': false, - 'get': false, - 'update': false, - 'delete': false, - } - } - ]; - - before(async () => { - await setupTestDatabaseWith(Object.assign({}, userProfiles, allowedEmailDomains)); - }); - - describe("Profile collection rules", () => { +const uid = "1"; +const collection = "user_profiles"; + +function test(users, passwordProviderAllowedEmailApp) { it("does not allow creating a user profile with not allowed fields", async () => { - let userProfile = getUserProfile(); - userProfile.test = "test"; + let userProfile = getUserProfile(); + userProfile.test = "test"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(userProfile) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(userProfile) + ); }); it("does not allow creating a user profile with not valid selected theme value", async () => { - let userProfile = getUserProfile(); - userProfile.selectedTheme = "test"; + let userProfile = getUserProfile(); + userProfile.selectedTheme = "test"; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(userProfile) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(userProfile) + ); }); it("does not allow to create a user profile with null selected theme value", async () => { - let userProfile = getUserProfile(); - userProfile.selectedTheme = null; + let userProfile = getUserProfile(); + userProfile.selectedTheme = null; - await assertFails( - passwordProviderAllowedEmailApp.collection(collection).add(userProfile) - ); + await assertFails( + passwordProviderAllowedEmailApp.collection(collection).add(userProfile) + ); }); - }); - - async.forEach(users, (user, callback) => { - describe(user.describe, () => { - let canCreateDescription = user.can.create ? - "allows to create a user profile" : "does not allow creating a user profile"; - let canListDescription = user.can.list ? - "allows reading user profiles" : "does not allow reading user profiles"; - let canGetDescription = user.can.get ? - "allows reading own user profile" : "does not allow reading own user profile"; - let canUpdateDescription = user.can.update ? - "allows to update a user profile" : "does not allow updating a user profile"; - let canDeleteDescription = user.can.delete ? - "allows to delete a user profile" : "does not allow deleting a user profile"; - - it(canCreateDescription, async () => { - const createPromise = user.app.collection(collection).doc(uid).set(getUserProfile()); - - if (user.can.create) { - await assertSucceeds(createPromise) - } else { - await assertFails(createPromise) - } - }); - it(canListDescription, async () => { - const readPromise = user.app.collection(collection).get(); + async.forEach(users, (user, callback) => { + describe(user.describe, () => { + let canCreateDescription = user.can.create ? + "allows to create a user profile" : "does not allow creating a user profile"; + let canListDescription = user.can.list ? + "allows reading user profiles" : "does not allow reading user profiles"; + let canGetDescription = user.can.get ? + "allows reading own user profile" : "does not allow reading own user profile"; + let canUpdateDescription = user.can.update ? + "allows to update a user profile" : "does not allow updating a user profile"; + let canDeleteDescription = user.can.delete ? + "allows to delete a user profile" : "does not allow deleting a user profile"; - if (user.can.list) { - await assertSucceeds(readPromise) - } else { - await assertFails(readPromise) - } - }); + it(canCreateDescription, async () => { + const createPromise = user.app.collection(collection).doc(uid).set(getUserProfile()); - it(canGetDescription, async () => { - const readOwnPromise = user.app.collection(collection).doc(uid).get(); + if (user.can.create) { + await assertSucceeds(createPromise) + } else { + await assertFails(createPromise) + } + }); - if (user.can.get) { - await assertSucceeds(readOwnPromise) - } else { - await assertFails(readOwnPromise) - } - }); + it(canListDescription, async () => { + const readPromise = user.app.collection(collection).get(); + + if (user.can.list) { + await assertSucceeds(readPromise) + } else { + await assertFails(readPromise) + } + }); + + it(canGetDescription, async () => { + const readOwnPromise = user.app.collection(collection).doc(uid).get(); + + if (user.can.get) { + await assertSucceeds(readOwnPromise) + } else { + await assertFails(readOwnPromise) + } + }); + + it(canUpdateDescription, async () => { + const updatePromise = + user.app.collection(collection).doc(uid).update({selectedTheme: "ThemeType.light"}); + + if (user.can.update) { + await assertSucceeds(updatePromise) + } else { + await assertFails(updatePromise) + } + }); + + it(canDeleteDescription, async () => { + const deletePromise = + user.app.collection(collection).doc(uid).delete(); - it(canUpdateDescription, async () => { - const updatePromise = - user.app.collection(collection).doc(uid).update({ selectedTheme: "ThemeType.light" }); + if (user.can.delete) { + await assertSucceeds(deletePromise) + } else { + await assertFails(deletePromise) + } + }); + }); + callback(); + }); +} + +describe("", async () => { + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true, uid) + ); - if (user.can.update) { - await assertSucceeds(updatePromise) - } else { - await assertFails(updatePromise) + const users = [ + { + 'describe': 'Authenticated as an anonymous user who is not an owner of the user profile', + 'app': await getApplicationWith(getAnonymousUser()), + 'can': { + 'create': false, + 'list': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated as an anonymous user who is an owner of the user profile', + 'app': await getApplicationWith(getAnonymousUser(uid)), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and not a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and not a verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and not verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and not a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and a verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and a verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and not a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and not a verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false, uid) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and not verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false, uid) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and not a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and a verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and a verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true, uid) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': await getApplicationWith(null), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } } - }); + ]; - it(canDeleteDescription, async () => { - const deletePromise = - user.app.collection(collection).doc(uid).delete(); + describe("Profile collection rules, public dashboard is enabled", () => { + before(async () => { + await setupTestDatabaseWith(Object.assign({}, userProfiles, allowedEmailDomains, featureConfigEnabled)); + }); - if (user.can.delete) { - await assertSucceeds(deletePromise) - } else { - await assertFails(deletePromise) + test(users, passwordProviderAllowedEmailApp); + }); + + after(async () => { + await tearDown(); + }); +}); + +describe("", async () => { + const passwordProviderAllowedEmailApp = await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true, uid) + ); + + const users = [ + { + 'describe': 'Authenticated as an anonymous user who is not an owner of the user profile', + 'app': await getApplicationWith(getAnonymousUser()), + 'can': { + 'create': false, + 'list': false, + 'read': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated as an anonymous user who is an owner of the user profile', + 'app': await getApplicationWith(getAnonymousUser(uid)), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and not a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and not a verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, false, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and not verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and not a verified email user who is not an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, allowed email domain, and a verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getAllowedEmailUser(passwordSignInProviderId, true, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a password, not allowed email domain, and a verified email user who is an owner of the user profile', + 'app': await getApplicationWith( + getDeniedEmailUser(passwordSignInProviderId, true, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and not a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and not a verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, false, uid) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and not verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false, uid) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and not a verified email user who is not an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, false) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, allowed email domain, and a verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getAllowedEmailUser(googleSignInProviderId, true, uid) + ), + 'can': { + 'create': true, + 'list': false, + 'get': true, + 'update': true, + 'delete': false, + } + }, + { + 'describe': 'Authenticated with a google, not allowed email domain, and a verified email user who is an owner of the profile', + 'app': await getApplicationWith( + getDeniedEmailUser(googleSignInProviderId, true, uid) + ), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } + }, + { + 'describe': 'Unauthenticated user', + 'app': await getApplicationWith(null), + 'can': { + 'create': false, + 'list': false, + 'get': false, + 'update': false, + 'delete': false, + } } - }); + ]; + + describe("Profile collection rules, public dashboard is disabled", () => { + before(async () => { + await setupTestDatabaseWith(Object.assign({}, userProfiles, allowedEmailDomains, featureConfigDisabled)); + }); + + test(users, passwordProviderAllowedEmailApp); }); - callback(); - }); - after(async () => { - await tearDown(); - }); + after(async () => { + await tearDown(); + }); });