Skip to content

Commit

Permalink
feat: clean DB after user delete
Browse files Browse the repository at this point in the history
  • Loading branch information
czabaj committed Aug 5, 2023
1 parent 8c939ac commit 29f8121
Show file tree
Hide file tree
Showing 9 changed files with 1,711 additions and 50 deletions.
4 changes: 1 addition & 3 deletions functions/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
"plugin:import/typescript",
"google",
"plugin:@typescript-eslint/recommended",
"prettier",
],
parser: "@typescript-eslint/parser",
parserOptions: {
Expand All @@ -25,10 +26,7 @@ module.exports = {
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": 0,
quotes: 0,
"import/no-unresolved": 0,
indent: ["error", 2],
"object-curly-spacing": 0,
"require-jsdoc": 0,
},
};
2 changes: 2 additions & 0 deletions functions/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ typings/

# Node.js dependency directory
node_modules/

/.parcel-cache/
37 changes: 21 additions & 16 deletions functions/package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
{
"name": "functions",
"scripts": {
"lint": "eslint --ext .js,.ts .",
"build": "tsc",
"build:watch": "tsc --watch",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "18"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^11.8.0",
"firebase-functions": "^4.3.1"
Expand All @@ -23,9 +8,29 @@
"@typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-import": "^2.25.4",
"firebase-functions-test": "^3.1.0",
"mocha": "^10.2.0",
"parcel": "^2.9.3",
"typescript": "^4.9.0"
},
"private": true
"engines": {
"node": "18"
},
"main": "lib/index.js",
"name": "functions",
"private": true,
"scripts": {
"build": "parcel build --no-content-hash",
"build:watch": "parcel watch",
"deploy": "firebase deploy --only functions",
"lint": "eslint --ext .js,.ts .",
"logs": "firebase functions:log",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"test": "mocha --reporter spec"
},
"source": "src/index.ts"
}
66 changes: 61 additions & 5 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
/**
* Import function triggers from their respective submodules:
*
* import {onCall} from "firebase-functions/v2/https";
* import {onDocumentWritten} from "firebase-functions/v2/firestore";
*
* See a full list of supported triggers at https://firebase.google.com/docs/functions
*/

import { initializeApp } from "firebase-admin/app";
import { Query, getFirestore } from "firebase-admin/firestore";
import {
type DocumentSnapshot,
FieldValue,
type Query,
getFirestore,
} from "firebase-admin/firestore";
import { auth } from "firebase-functions/v1";
import { firestore } from "firebase-functions/v2";
import * as logger from "firebase-functions/logger";

import type {
place as Place,
personsIndex as PersonsIndex,
} from "../../src/backend/FirestoreModels.gen";
import { UserRole } from "../../src/backend/UserRoles";

initializeApp();
const db = getFirestore();

Expand Down Expand Up @@ -61,3 +69,51 @@ export const deletePlaceSubcollection = firestore.onDocumentDeleted(
}
}
);

export const truncateUserInDb = auth.user().onDelete(async (user) => {
logger.info(`Delete user`, user);
const placesQuery = db
.collection("places")
.where(`users.${user.uid}`, `>=`, 0);
const placesToRole: Array<[string, number]> = [];
placesQuery
.stream()
.on(`data`, async (placeSnapshot: DocumentSnapshot<Place>) => {
const placeData = placeSnapshot.data() as Place;
const userRole = placeData.users[user.uid];
placesToRole.push([placeSnapshot.ref.id, userRole]);
if (userRole === UserRole.owner) {
placeSnapshot.ref.delete();
} else {
const placePersonsIndexRef = db.doc(
`places/${placeSnapshot.id}/personsIndex/1`
);
const placePersonsIndexSnapshot = await placePersonsIndexRef.get();
const placePersonsIndex =
placePersonsIndexSnapshot.data() as PersonsIndex;
const personEntry = Object.entries(placePersonsIndex.all).find(
([, personTuple]) => {
personTuple[3] === user.uid;
}
);
if (personEntry) {
const [personId, personTuple] = personEntry;
personTuple[3] = null;
placePersonsIndexRef.update({
[`all.${personId}`]: personTuple,
});
}
placeSnapshot.ref.update({
[`users.${user.uid}`]: FieldValue.delete(),
});
}
})
.on(`end`, () => {
logger.info(
`Delete user "${user.uid}" affected places:`,
placesToRole.length === 0
? `none deleted`
: Object.fromEntries(placesToRole)
);
});
});
5 changes: 2 additions & 3 deletions functions/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"compilerOptions": {
"jsx": "react",
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
Expand All @@ -9,7 +10,5 @@
"target": "es2017"
},
"compileOnSave": true,
"include": [
"src"
]
"include": ["src"]
}
Loading

0 comments on commit 29f8121

Please sign in to comment.