working login handling

This commit is contained in:
lukew3 2021-05-14 16:16:06 -04:00
parent 3978b7a106
commit 45c612c746
4 changed files with 97 additions and 184 deletions

View file

@ -3,12 +3,44 @@ const Schema = mongoose.Schema;
const userSchema = new Schema(
{
name: String,
email: String,
password: String,
emailVerified: Boolean,
results: [{ type: Schema.Types.Mixed, default: {} }],
personalBests: {
custom: { type: Schema.Types.Mixed, default: {} },
time: { type: Schema.Types.Mixed, default: {} },
words: { type: Schema.Types.Mixed, default: {} },
zen: { type: Schema.Types.Mixed, default: {} },
},
name: { type: String, required: true },
presets: [{ type: Schema.Types.Mixed, default: {} }],
tags: [{ type: Schema.Types.Mixed, default: {} }],
favouriteThemes: [],
refactored: { type: Boolean, default: false },
banned: { type: Boolean, default: false },
verified: { type: Boolean, default: false }, //what's the difference between verified and email verified
emailVerified: { type: Boolean, default: false },
lbMemory: {
//short for leaderboard memory
time15: {
global: { type: Number, default: 0 }, //might not be an Number, I'm not sure
daily: { type: Number, default: 0 },
},
time60: {
global: { type: Number, default: 0 },
daily: { type: Number, default: 0 },
},
},
globalStats: {
time: { type: Number, default: 0 },
started: { type: Number, default: 0 }, //number of started tests
completed: { type: Number, default: 0 },
},
email: { type: String, required: true },
password: { type: String, required: true },
},
{ timestamps: true }
{
timestamps: true,
minimize: false, //allows empty objects to be saved to mongodb
}
);
const User = mongoose.model("User", userSchema);

View file

@ -153,18 +153,23 @@ app.post("/api/passwordReset", (req, res) => {
res.sendStatus(200);
});
app.get("/api/fetchSnapshot", (req, res) => {
const uid = req.body.uid;
const token = req.body.token; //should be passed through header authentication
//return a list of tags
//return list of presets
//return user data
//tags and presets should be included
res.sendStatus(200);
app.get("/api/fetchSnapshot", authenticateToken, (req, res) => {
/* Takes token and returns snap */
//this is called in init snapshot
User.findOne({ name: req.name }, (err, user) => {
if (err) res.status(500).send({ error: err });
//populate snap object with data from user document
let snap = user;
delete snap.password;
//return user data
res.json({ snap: snap });
});
});
app.get("/api/userResults", (req, res) => {
const uid = req.body.uid; //might not need uid if token is given
app.get("/api/userResults", authenticateToken, (req, res) => {
User.findOne({ name: req.name }, (err, user) => {
if (err) res.status(500).send({ error: err });
});
//return list of results
res.sendStatus(200);
});

View file

@ -32,9 +32,15 @@ export function signIn() {
if ($(".pageLogin .login #rememberMe input").prop("checked")) {
// TODO: set user login cookie that persists after session
Cookies.set("accessToken", response.data.accessToken);
Cookies.set("uid", response.data.user._id);
Cookies.set("displayName", response.data.user.name);
Cookies.set("email", response.data.user.email);
} else {
//set user login cookie to persist only as long as the session lives
Cookies.set("accessToken", response.data.accessToken);
Cookies.set("uid", response.data.user._id);
Cookies.set("displayName", response.data.user.name);
Cookies.set("email", response.data.user.email);
}
userStateChanged(response.data.user);
})
@ -98,25 +104,18 @@ export function linkWithGoogle() {
}
export function signOut() {
const uid = DB.currentUser().uid;
axios
.post("/api/signOut", {
uid: uid,
//should there be a token necessary to sign out?
//if you send the token, that would eliminate the need to send uid
})
.then(() => {
Notifications.add("Signed out", 0, 2);
AllTimeStats.clear();
Settings.hideAccountSection();
AccountButton.update();
UI.changePage("login");
DB.setSnapshot(null);
userStateChanged(null);
})
.catch((error) => {
Notifications.add(error.message, -1);
});
//don't think I need an axios request here if I'm using jwt
Cookies.remove("accessToken");
Cookies.remove("uid");
Cookies.remove("displayName");
Cookies.remove("email");
Notifications.add("Signed out", 0, 2);
AllTimeStats.clear();
Settings.hideAccountSection();
AccountButton.update();
UI.changePage("login");
DB.setSnapshot(null);
userStateChanged(null);
}
function signUp() {
@ -143,6 +142,9 @@ function signUp() {
.then((response) => {
let usr = response.data.user;
Cookies.set("accessToken", response.data.accessToken);
Cookies.set("uid", usr._id);
Cookies.set("displayName", usr.name);
Cookies.set("email", usr.email);
//Cookies.set('refreshToken', response.data.refreshToken);
AllTimeStats.clear();
Notifications.add("Account created", 1, 3);

View file

@ -36,160 +36,34 @@ export function setSnapshot(newSnapshot) {
export function currentUser() {
const token = Cookies.get("accessToken");
//probably don't need to request the server every time
//uid, email, and displayName could be stored in cookies
//however, this method proves that the token is valid
//might not be important
axios
.get("/api/currentUser", {
headers: { Authorization: `Bearer ${token}` },
})
.then((response) => {
return response.data.user;
})
.catch(() => {
return null;
});
if (token) {
const user = {
uid: Cookies.get("uid"),
displayName: Cookies.get("displayName"),
email: Cookies.get("email"),
};
return user;
} else {
return null;
}
}
export async function initSnapshot() {
//get identity and token
//send api request with token that returns tags, presets, and data needed for snap
/*
let user = currentUser();
if (user == null) return false;
let snap = {
results: undefined,
personalBests: {},
name: undefined,
presets: [],
tags: [],
favouriteThemes: [],
refactored: false,
banned: undefined,
verified: undefined,
emailVerified: undefined,
lbMemory: {
time15: {
global: null,
daily: null,
},
time60: {
global: null,
daily: null,
},
},
globalStats: {
time: 0,
started: 0,
completed: 0,
},
};
axios.get('/api/fetchSnapshot', {
uid: user.uid,
//not sure how I'm going to pass tokens right now
//token: user.token
}).then((response) => {
//set snapshot equal to response.data.snap or whatever I call it
})
try {
//add tags to snap tags list
await db
.collection(`users/${user.uid}/tags/`)
.get()
.then((data) => {
data.docs.forEach((doc) => {
let tag = doc.data();
tag.id = doc.id;
if (tag.personalBests === undefined) {
tag.personalBests = {};
}
snap.tags.push(tag);
});
snap.tags = snap.tags.sort((a, b) => {
if (a.name > b.name) {
return 1;
} else if (a.name < b.name) {
return -1;
} else {
return 0;
}
});
})
.catch((e) => {
throw e;
});
//set presets? Not sure what this is at the moment
await db
.collection(`users/${user.uid}/presets/`)
.get()
.then((data) => {
data.docs.forEach((doc) => {
// console.log(doc);
let preset = doc.data();
preset.id = doc.id;
snap.presets.push(preset);
});
snap.presets = snap.presets.sort((a, b) => {
if (a.name > b.name) {
return 1;
} else if (a.name < b.name) {
return -1;
} else {
return 0;
}
});
})
.catch((e) => {
throw e;
});
//set snap data to the data found in the database
await db
.collection("users")
.doc(user.uid)
.get()
.then((res) => {
let data = res.data();
if (data === undefined) return;
if (data.personalBests !== undefined) {
snap.personalBests = data.personalBests;
}
snap.name = data.name;
snap.discordId = data.discordId;
snap.pairingCode =
data.discordPairingCode == null ? undefined : data.discordPairingCode;
snap.config = data.config;
snap.favouriteThemes =
data.favouriteThemes === undefined ? [] : data.favouriteThemes;
snap.refactored = data.refactored === true ? true : false;
snap.globalStats = {
time: data.timeTyping,
started: data.startedTests,
completed: data.completedTests,
};
snap.banned = data.banned;
snap.verified = data.verified;
snap.emailVerified = user.emailVerified;
try {
if (data.lbMemory.time15 !== undefined) {
snap.lbMemory.time15 = data.lbMemory.time15;
}
if (data.lbMemory.time60 !== undefined) {
snap.lbMemory.time60 = data.lbMemory.time60;
}
} catch {}
})
.catch((e) => {
throw e;
});
// console.log(snap.presets);
dbSnapshot = snap;
} catch (e) {
console.error(e);
}
loadTags(dbSnapshot.tags);
return dbSnapshot;
*/
if (currentUser() == null) return false;
const token = Cookies.get("accessToken");
await axios
.get("/api/fetchSnapshot", {
headers: { Authorization: `Bearer ${token}` },
})
.then((response) => {
dbSnapshot = response.data.snap;
loadTags(dbSnapshot.tags);
return dbSnapshot;
})
.catch((e) => {
console.error(e);
});
}
export async function getUserResults() {