mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-10-26 00:37:37 +08:00
working login handling
This commit is contained in:
parent
3978b7a106
commit
45c612c746
4 changed files with 97 additions and 184 deletions
42
models.js
42
models.js
|
|
@ -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);
|
||||
|
|
|
|||
25
server.js
25
server.js
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
174
src/js/db.js
174
src/js/db.js
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue