-
Notifications
You must be signed in to change notification settings - Fork 0
/
firebase.api.js
173 lines (148 loc) · 5.45 KB
/
firebase.api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Firebase Ver. 8
/**
* Using Admin SDK (with serviceAccount key obtained from our firebase project, we can bypass Cloud Firestore security rule when we make request from our NodeJs backend server!
* https://firebase.google.com/docs/admin/setup
* https://medium.com/feedflood/write-to-cloud-firestore-using-node-js-server-c84859fefb86
**/
const firebase = require("firebase-admin");
const { applicationDefault } = require("firebase-admin/app");
// const serviceAccount = require(process.env.GOOGLE_APPLICATION_CREDENTIALS);
// initialize admin SDK using serciceAccountKey.
firebase.initializeApp({
credential: applicationDefault(), // look for GOOGLE_APPLICATION_CREDENTIALS env variable
// credential: firebase.credential.cert(serviceAccount),
});
const db = firebase.firestore();
////////////////////////////////////////////////////////////////////////////////////////////
const tokenize = require("./encode"); // use to generate the JWT for creating confirmationCode
// create new user document in database and return it. if the document exists, just return it
const createUserDocument = async (req, res) => {
const userRef = db.doc(`users/${req.body.params.uid}`);
let snapShot;
try {
snapShot = await userRef.get();
} catch (err) {
console.log(err);
}
if (!snapShot.exists) {
const { displayName, email, signInWithGoogle } = req.body.params;
const createdAt = new Date();
const confirmationCode = tokenize(email, process.env.JWT_SECRET);
/**
* Default value of status is pending. It will be updated to active when the user clicked the link in the email which they will receive.
* When the user signs in with Email and Password, only the one with status of active will be signed in.
* When user signs in with Google, the status will always be `active` but the user will automatically be signed in anyway so this doesn't matter
*/
const status = signInWithGoogle ? "active" : "pending";
const newDocument = {
displayName,
email,
createdAt,
confirmationCode,
status,
};
try {
await userRef.set(newDocument);
res.status(200).send(newDocument);
} catch (err) {
console.log(err);
res.status(500).send({
message: "Error creating the user document in Firestore database!",
});
}
} else {
const id = snapShot.id;
res.status(200).send({ id, ...snapShot.data() });
}
};
const updateUserContactInfo = async (req, res) => {
const { userName, email, message, createdAt } = req.body.params;
const id = email + "_" + createdAt;
const contactInfoRef = db.doc(`contactinfo/${id}`);
try {
await contactInfoRef.set({ createdAt, userName, email, message });
res.status(200).send("Successfully saved user contact info to database!");
} catch (err) {
console.log(err);
res.status(500).send({
message: "Error creating the user document in Firestore database!",
});
}
};
// verify if the user has confirmed their email. if yes, return the user document.
const verifyUser = async (req, res) => {
try {
const userRef = db.doc(`users/${req.body.params.uid}`);
const snapShot = await userRef.get();
if (!snapShot) {
res.status(401).send({
message: "User doesn't exist or password is incorrect",
});
}
if (snapShot.data().status == "active") {
const id = snapShot.id;
res.status(200).send({ id, ...snapShot.data() });
} else {
res.status(401).send({
message: "Pending Account. Please Verify Your Email!",
});
}
} catch (err) {
res.status(500).send({
message: "failed to verify user",
err,
});
}
};
// activate user when they clicked the link in the confirmation email
const activateUser = async (req, res) => {
const usersRef = await db.collection("users");
// const userCollection = await usersRef.get();
// const allDocsSnapshot = await userCollection.docs;
// const allDocs = allDocsSnapshot.map((snapshot) => snapshot.data());
// console.log(allDocs);
let userId, userDocument;
try {
// query for the document with confirmationCode in the collection `users`
const query = await usersRef.where(
"confirmationCode",
"==",
req.body.params.confirmationCode
);
const querySnapshot = await query.get(); // querySnapshot is an object of documentSnapshot(s)
// Note: firestore's querySnapshot object has a method also called `forEach`: https://firebase.google.com/docs/reference/node/firebase.firestore.QuerySnapshot
querySnapshot.forEach((doc) => {
// console.log(doc.id, " => ", doc.data()); // doc.data() is never undefined for query doc snapshots
userId = doc.id;
userDocument = doc.data(); // there is only one found userDocument
});
} catch (err) {
console.log(err);
res.status(500).send({
message: "Error querying for the user with the provided confirmationCode",
});
}
// activate the user
userDocument.status = "active";
const userRef = db.doc(`users/${userId}`);
// write the new userDocument back to firestore
try {
await userRef.set(userDocument);
res
.status(200)
.send(
"Your email has been confirmed. You can now login. Have fun shopping with us!"
);
} catch (err) {
console.log(err);
res.status(500).send({
message: "Error updating the newUser document in Firestore database!",
});
}
};
module.exports = {
createUserDocument,
verifyUser,
activateUser,
updateUserContactInfo,
};