Skip to content

Commit 5ae86d8

Browse files
committed
feat: class administrators and also number of students
1 parent 781f5ae commit 5ae86d8

13 files changed

+3187
-28
lines changed

.firebaserc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "usaco-guide"
4+
}
5+
}

firebase.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"functions": {
3+
"predeploy": [
4+
"npm --prefix \"$RESOURCE_DIR\" run lint",
5+
"npm --prefix \"$RESOURCE_DIR\" run build"
6+
]
7+
}
8+
}

functions/.eslintrc.js

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
module.exports = {
2+
env: {
3+
browser: true,
4+
es6: true,
5+
node: true,
6+
},
7+
extends: [
8+
'plugin:import/errors',
9+
'plugin:import/warnings',
10+
'plugin:import/typescript',
11+
],
12+
parser: '@typescript-eslint/parser',
13+
parserOptions: {
14+
project: 'tsconfig.json',
15+
sourceType: 'module',
16+
},
17+
plugins: ['@typescript-eslint', 'import'],
18+
rules: {
19+
'@typescript-eslint/adjacent-overload-signatures': 'error',
20+
'@typescript-eslint/no-empty-function': 'error',
21+
'@typescript-eslint/no-empty-interface': 'warn',
22+
'@typescript-eslint/no-floating-promises': 'error',
23+
'@typescript-eslint/no-namespace': 'error',
24+
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
25+
'@typescript-eslint/prefer-for-of': 'warn',
26+
'@typescript-eslint/triple-slash-reference': 'error',
27+
'@typescript-eslint/unified-signatures': 'warn',
28+
'comma-dangle': 'warn',
29+
'constructor-super': 'error',
30+
eqeqeq: ['warn', 'always'],
31+
'import/no-deprecated': 'warn',
32+
'import/no-extraneous-dependencies': 'error',
33+
'import/no-unassigned-import': 'warn',
34+
'no-cond-assign': 'error',
35+
'no-duplicate-case': 'error',
36+
'no-duplicate-imports': 'error',
37+
'no-empty': [
38+
'error',
39+
{
40+
allowEmptyCatch: true,
41+
},
42+
],
43+
'no-invalid-this': 'error',
44+
'no-new-wrappers': 'error',
45+
'no-param-reassign': 'error',
46+
'no-redeclare': 'error',
47+
'no-sequences': 'error',
48+
'no-shadow': [
49+
'error',
50+
{
51+
hoist: 'all',
52+
},
53+
],
54+
'no-throw-literal': 'error',
55+
'no-unsafe-finally': 'error',
56+
'no-unused-labels': 'error',
57+
'no-var': 'warn',
58+
'no-void': 'error',
59+
'prefer-const': 'warn',
60+
},
61+
settings: {
62+
jsdoc: {
63+
tagNamePreference: {
64+
returns: 'return',
65+
},
66+
},
67+
},
68+
};

functions/.gitignore

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Compiled JavaScript files
2+
**/*.js
3+
**/*.js.map
4+
5+
# Except the ESLint config file
6+
!.eslintrc.js
7+
8+
# TypeScript v1 declaration files
9+
typings/
10+
11+
# Node.js dependency directory
12+
node_modules/

functions/package.json

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "functions",
3+
"scripts": {
4+
"lint": "eslint \"src/**/*\"",
5+
"build": "tsc",
6+
"serve": "npm run build && firebase emulators:start --only functions",
7+
"shell": "npm run build && firebase functions:shell",
8+
"start": "npm run shell",
9+
"deploy": "firebase deploy --only functions",
10+
"logs": "firebase functions:log"
11+
},
12+
"engines": {
13+
"node": "12"
14+
},
15+
"main": "lib/index.js",
16+
"dependencies": {
17+
"@types/vfile-message": "^2.0.0",
18+
"firebase-admin": "^9.2.0",
19+
"firebase-functions": "^3.11.0"
20+
},
21+
"devDependencies": {
22+
"@typescript-eslint/eslint-plugin": "^3.9.1",
23+
"@typescript-eslint/parser": "^3.8.0",
24+
"eslint": "^7.6.0",
25+
"eslint-plugin-import": "^2.22.0",
26+
"firebase-functions-test": "^0.2.0",
27+
"typescript": "^3.8.0"
28+
},
29+
"private": true
30+
}

functions/src/index.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import * as functions from 'firebase-functions';
2+
import admin from 'firebase-admin';
3+
admin.initializeApp();
4+
5+
export const getUsers = functions.https.onCall(
6+
(
7+
data: {
8+
users: ({ uid: string } | { email: string })[];
9+
},
10+
context
11+
) => {
12+
const { users } = data;
13+
const callerUid = context.auth?.uid;
14+
15+
if (!callerUid || !users || users.length === 0) {
16+
throw new functions.https.HttpsError(
17+
'invalid-argument',
18+
'The function was not called with the correct data, or the caller is not logged in.'
19+
);
20+
}
21+
return admin
22+
.firestore()
23+
.collection('classes')
24+
.doc('permissions')
25+
.get()
26+
.then(snapshot => snapshot.data())
27+
.then(permissions => {
28+
if (
29+
!permissions?.admins?.includes(callerUid) &&
30+
!permissions?.instructors?.includes(callerUid)
31+
) {
32+
throw new functions.https.HttpsError(
33+
'permission-denied',
34+
'Caller is not an admin or instructor.'
35+
);
36+
} else {
37+
return admin.auth().getUsers(users);
38+
}
39+
});
40+
}
41+
);

functions/tsconfig.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"compilerOptions": {
3+
"module": "commonjs",
4+
"noImplicitReturns": true,
5+
"noUnusedLocals": true,
6+
"outDir": "lib",
7+
"sourceMap": true,
8+
"target": "es2017",
9+
10+
"esModuleInterop": true
11+
},
12+
"compileOnSave": true,
13+
"include": ["src"]
14+
}

0 commit comments

Comments
 (0)