Skip to content

Commit

Permalink
Login and Sign In/Out now functional using the new API client
Browse files Browse the repository at this point in the history
  • Loading branch information
malee31 committed Dec 26, 2024
1 parent 0c3817f commit 7b9d831
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 39 deletions.
4 changes: 2 additions & 2 deletions components/pages/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function Home({ navigation }) {
}
setLoading(true);
if(!userWritable.userInfo.signedIn) {
signIn(userWritable.userInfo.apiKey)
signIn()
.then(result => {
if(result.ok) {
userWritable.updateData({
Expand All @@ -42,7 +42,7 @@ export default function Home({ navigation }) {
setLoading(false);
});
} else {
signOut(userWritable.userInfo.apiKey)
signOut()
.then(result => {
if(result.ok) {
userWritable.updateData({
Expand Down
35 changes: 31 additions & 4 deletions components/pages/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import useModal from "../parts/ContextProviders/ModalProvider";
import { login } from "../parts/utils/serverClientWrapper";
import config from "../../config.json";
import { useNavigation } from "@react-navigation/native";
import { client, getStatus } from "../parts/utils/serverClient";

const colors = config.colors;

Expand Down Expand Up @@ -66,13 +67,39 @@ export default function Login() {
const handleLogin = () => {
modal.showMessage("Verifying that you exist...");
Keyboard.dismiss();
login(userWritable, passwordInput)
.then(message => {
modal.showMessage(message);

// Prevents client from doing things that the server can handle, but should not be allowed for the site
if(!passwordInput) {
modal.showMessage("Password cannot be empty");
return;
} else if(userWritable.userInfo.signedIn) {
modal.showMessage("Cannot switch users while signed in");
return;
}

client.login(passwordInput)
.then(async (valid) => {
if(!valid) {
modal.showMessage("Incorrect password");
return;
}

const result = await getStatus();
if(!result.ok || !result.data.verified) {
throw new Error(result.messages.join("\n"));
}

userWritable.updateData({
loggedIn: true,
name: result.data.user.name,
apiKey: result.data.user.apiKey,
signedIn: result.data.user.signedIn
});
modal.showMessage(`Successfully Logged In as ${result.data.user.name}`);

// noinspection JSCheckFunctionSignatures
navigation.navigate("Home");
})
.catch(err => modal.showMessage(err.message));
}

return (
Expand Down
13 changes: 6 additions & 7 deletions components/parts/ContextProviders/UserInfoProvider.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { createContext, useContext, useEffect, useState } from "react";
import { getApiKey } from "../utils/storageManager";
import { client, getLeaderboard, verifyApiKey } from "../utils/serverClient";
import { client } from "../utils/serverClient";

/**
* @typedef UserInfoWritable
Expand Down Expand Up @@ -58,23 +57,23 @@ export function UserInfoProvider({ children }) {
return;
}

const user = await client.request("GET", "/user/status");
const { user } = await client.request("GET", "/user/status");

// Update the following: loggedIn, name, apiKey (deprecated)
updatedData.loggedIn = true;
updatedData.name = `${user.first_name} ${user.last_name}`;
updatedData.apiKey = client.apiKey; // TODO: Remove after transitioning all fetch() to client.request()

// Gets signed in status and time
const clockedIn = user.signedIn;
if(Boolean(user.signedIn) !== Boolean(userInfo.signedIn)) {
const clockedIn = (user.session && !user.session.endTime) ? user.session.startTime : 0;
if(Boolean(userInfo.signedIn) !== Boolean(clockedIn)) {
// console.log("RESYNC");
if(user.signedIn) {
if(clockedIn) {
updatedData.signedIn = clockedIn;
} else {
updatedData.signedIn = 0;
}
} else if(user.signedIn && Math.abs(userInfo.signedIn - clockedIn) > 2000 /* 2 second desync tolerance */) {
} else if(clockedIn && Math.abs(userInfo.signedIn - clockedIn) > 2000 /* 2 second desync tolerance */) {
// console.log(`Resync gap: ${Math.abs(userInfo.signedIn - clockedIn)}`);
updatedData.signedIn = clockedIn;
}
Expand Down
40 changes: 14 additions & 26 deletions components/parts/utils/serverClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ class Client {
apiKey: credential
});

return response.ok;
// User is authorized if it has both an 'ok' response and a user id
return response.ok && response.id;
}

// Call to attempt a login with an admin or user password.
Expand Down Expand Up @@ -229,7 +230,7 @@ export async function verifyPassword(password) {
signedIn: null
};

const userResult = await verifyApiKey(apiKey);
const userResult = await getStatus();

if(!userResult.ok) {
result.messages.push(...userResult.messages);
Expand All @@ -239,7 +240,7 @@ export async function verifyPassword(password) {
return userResult;
}

export async function verifyApiKey(apiKey) {
export async function getStatus() {
const result = {
ok: false,
messages: [],
Expand All @@ -251,12 +252,7 @@ export async function verifyApiKey(apiKey) {

let res;
try {
res = await fetch(`${SERVER_URL}${endpoints.getUserStatus}`, {
method: "GET",
headers: {
"Authorization": `Bearer ${apiKey}`
}
});
res = await client.request("GET", endpoints.getUserStatus);
} catch(err) {
result.messages.push(`Unable to fetch status. Are you connected to the internet?`);
return result;
Expand All @@ -267,13 +263,12 @@ export async function verifyApiKey(apiKey) {
return result;
}

const tokenJsonResponse = await res.json();
const user = tokenJsonResponse.user;
const user = res.user;
result.ok = true;
result.data.verified = true;
result.data.user = {
name: `${user.first_name} ${user.last_name}`,
apiKey: apiKey,
apiKey: client.apiKey,
// Is 0 if signed out. Otherwise, the actual sign in time is set
signedIn: (!user.session || user.session.endTime) ? 0 : user.session.startTime
};
Expand All @@ -283,12 +278,10 @@ export async function verifyApiKey(apiKey) {

/**
* Signs a user in or out
* @param {string} apiKey API key of the user to sign in or out
* @param {boolean} signInMode If set to false, will sign the user out instead
* @return {Promise<Object>} Resolves after a response is received from the server and parsed
*/
async function signInOut(apiKey, signInMode) {
const url = `${SERVER_URL}${endpoints.signIn}`;
async function signInOut(signInMode) {
const result = {
ok: false,
messages: [],
Expand All @@ -297,12 +290,7 @@ async function signInOut(apiKey, signInMode) {

let res;
try {
res = await fetch(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
res = await client.request("PATCH", endpoints.signIn, {
body: JSON.stringify({
method: signInMode ? "sign_in" : "sign_out"
})
Expand All @@ -323,7 +311,7 @@ async function signInOut(apiKey, signInMode) {
return result;
}

const verified = await verifyApiKey(apiKey);
const verified = await getStatus();
result.ok = verified.ok && verified.data.verified;
if(result.ok) {
result.data = verified.data.user;
Expand All @@ -332,12 +320,12 @@ async function signInOut(apiKey, signInMode) {
return result;
}

export function signIn(apiKey) {
return signInOut(apiKey, true);
export function signIn() {
return signInOut(true);
}

export function signOut(apiKey) {
return signInOut(apiKey, false);
export function signOut() {
return signInOut(false);
}

export function getLeaderboard() {
Expand Down

0 comments on commit 7b9d831

Please sign in to comment.