Skip to content

Commit

Permalink
sync vatsim data
Browse files Browse the repository at this point in the history
  • Loading branch information
ngoerlitz committed Aug 31, 2023
1 parent 5b217eb commit dc33fea
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 27 deletions.
3 changes: 3 additions & 0 deletions src/Router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import UserCourseAdminController from "./controllers/user/UserCourseAdminControl
import SessionController from "./controllers/login/SessionController";
import UserSettingsController from "./controllers/user/UserSettingsController";
import CourseAdministrationController from "./controllers/course/CourseAdministrationController";
import { UserData } from "./models/UserData";

const routerGroup = (callback: (router: Router) => void) => {
const router = Router();
Expand All @@ -55,6 +56,8 @@ router.use(
routerGroup((r: Router) => {
r.use(authMiddleware);

r.get("/user/update", LoginController.updateUserData);

r.patch("/settings", UserSettingsController.updateSettings);

r.get("/sessions", SessionController.getUserSessions);
Expand Down
14 changes: 14 additions & 0 deletions src/controllers/login/LoginController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import SessionLibrary, { removeSessionToken } from "../../libraries/session/Sess
import { User } from "../../models/User";
import { Role } from "../../models/Role";
import UserSessionLibrary from "../../libraries/session/UserSessionLibrary";
import dayjs from "dayjs";
import axios, { HttpStatusCode } from "axios";

// We can ignore all errors, since we are validating the .env
const connect_options: ConnectOptions = {
Expand Down Expand Up @@ -109,6 +111,17 @@ async function getUserData(request: Request, response: Response) {
response.send(user);
}

async function updateUserData(request: Request, response: Response) {
const user: User = request.body.user;
if (dayjs.utc().diff(user.updatedAt, "minutes") < 30) {
response.sendStatus(HttpStatusCode.BadRequest);
return;
}

let vatsimConnectLibrary = new VatsimConnectLibrary(connect_options);
await vatsimConnectLibrary.updateUserData(request, response);
}

async function validateSessionToken(request: Request, response: Response) {
response.send((await SessionLibrary.validateSessionToken(request)) != null);
}
Expand All @@ -119,4 +132,5 @@ export default {
logout,
getUserData,
validateSessionToken,
updateUserData,
};
2 changes: 1 addition & 1 deletion src/exceptions/VatsimConnectException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class VatsimConnectException extends Error {
return;

default:
response.status(500).send({ code: "ERR", message: "An unknown error occured" });
response.status(500).send({ code: "ERR", message: "An unknown error occurred" });
}
}
}
125 changes: 99 additions & 26 deletions src/libraries/vatsim/ConnectLibrary.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axios, { Axios, AxiosResponse } from "axios";
import axios, { Axios, AxiosResponse, HttpStatusCode } from "axios";
import { Request, Response } from "express";
import { VatsimOauthToken, VatsimScopes, VatsimUserData } from "./ConnectTypes";
import { ConnectLibraryErrors, VatsimConnectException } from "../../exceptions/VatsimConnectException";
Expand All @@ -9,6 +9,8 @@ import { UserData } from "../../models/UserData";
import { User } from "../../models/User";
import { Role } from "../../models/Role";
import { UserSettings } from "../../models/UserSettings";
import dayjs from "dayjs";
import { Config } from "../../core/Config";

export type ConnectOptions = {
client_id: string;
Expand All @@ -32,14 +34,14 @@ export class VatsimConnectLibrary {
private m_response: Response | undefined = undefined;
private m_request: Request | undefined = undefined;

constructor(connectOptions: ConnectOptions, remember: boolean) {
constructor(connectOptions?: ConnectOptions, remember?: boolean) {
this.m_connectOptions = connectOptions;
this.m_remember = remember;
this.m_remember = remember ?? false;

if (connectOptions == null) throw new VatsimConnectException();

this.m_axiosInstance = axios.create({
baseURL: this.m_connectOptions.base_uri,
baseURL: this.m_connectOptions?.base_uri ?? Config.CONNECT_CONFIG.BASE_URL,
timeout: 5000,
headers: { "Accept-Encoding": "gzip,deflate,compress" },
});
Expand Down Expand Up @@ -96,16 +98,10 @@ export class VatsimConnectLibrary {
Accept: "application/json",
},
});
} catch (e) {
throw new VatsimConnectException(ConnectLibraryErrors.ERR_AXIOS_TIMEOUT);
}
} catch (e) {}

const user_response_data: VatsimUserData | undefined = user_response?.data as VatsimUserData;

if (user_response_data == null) {
throw new VatsimConnectException();
}

this.m_userData = user_response_data;
return user_response_data;
}
Expand Down Expand Up @@ -164,21 +160,7 @@ export class VatsimConnectLibrary {
return this.m_userData;
}

/**
* Handle the login flow
* @throws VatsimConnectException
*/
public async login(request: Request, response: Response, code: string | undefined) {
if (code == null) throw new VatsimConnectException(ConnectLibraryErrors.ERR_NO_CODE);

this.m_response = response;
this.m_request = request;

await this.queryAccessTokens(code);
await this.queryUserData();
await this.validateSuppliedScopes();
await this.checkIsUserSuspended();

private async updateDatabase() {
if (this.m_userData == null) throw new VatsimConnectException();

const tokenValid = this.m_userData.data.oauth.token_valid?.toLowerCase() === "true";
Expand Down Expand Up @@ -206,6 +188,33 @@ export class VatsimConnectLibrary {
subdivision_name: this.m_userData.data.vatsim.subdivision.name,
subdivision_code: this.m_userData.data.vatsim.subdivision.id,
});
}

/**
* Handle the login flow
* @throws VatsimConnectException
*/
public async login(request: Request, response: Response, code: string | undefined) {
if (code == null) throw new VatsimConnectException(ConnectLibraryErrors.ERR_NO_CODE);

this.m_response = response;
this.m_request = request;

await this.queryAccessTokens(code);
await this.queryUserData();

if (this.m_userData == null) {
response.sendStatus(HttpStatusCode.InternalServerError);
return;
}

this.validateSuppliedScopes();
await this.checkIsUserSuspended();

if (this.m_userData == null) throw new VatsimConnectException();

// Create database entries
await this.updateDatabase();

await UserSettings.findOrCreate({
where: {
Expand Down Expand Up @@ -257,4 +266,68 @@ export class VatsimConnectLibrary {

throw new VatsimConnectException(ConnectLibraryErrors.ERR_UNABLE_CREATE_SESSION);
}

public async updateUserData(request: Request, response: Response) {
const user: User = request.body.user;

const userWithAccessToken = await User.scope("internal").findOne({
where: {
id: user.id,
},
});

if (userWithAccessToken == null) {
response.sendStatus(HttpStatusCode.InternalServerError);
return;
}

this.m_accessToken = userWithAccessToken.access_token ?? undefined;
this.m_refreshToken = userWithAccessToken.refresh_token ?? undefined;

const newUserData = await this.queryUserData();
if (newUserData == null) {
response.sendStatus(HttpStatusCode.InternalServerError);
return;
}

// Create database entries
await this.updateDatabase();

const newUser = await User.scope("sensitive").findOne({
where: {
id: this.m_userData?.data.cid,
},
include: [
{
association: User.associations.user_data,
as: "user_data",
},
{
association: User.associations.user_settings,
as: "user_settings",
},
{
association: User.associations.roles,
as: "roles",
attributes: ["name"],
through: { attributes: [] },

include: [
{
association: Role.associations.permissions,
attributes: ["name"],
through: { attributes: [] },
},
],
},
],
});

if (newUser == null) {
response.sendStatus(HttpStatusCode.InternalServerError);
return;
}

response.send(newUser);
}
}
5 changes: 5 additions & 0 deletions src/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ User.init(
exclude: ["access_token", "refresh_token"],
},
},
internal: {
attributes: {
exclude: [],
},
},
},
}
);

0 comments on commit dc33fea

Please sign in to comment.