Skip to content

Commit

Permalink
Merge pull request #364 from The-Purple-Warehouse/main
Browse files Browse the repository at this point in the history
[staging deploy] Add team management page
  • Loading branch information
CMEONE authored Oct 26, 2024
2 parents 21af65c + b2a2dad commit ec21b31
Show file tree
Hide file tree
Showing 18 changed files with 7,430 additions and 47 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules/
build/
.idea/
config/secret.json
**/accuracy.ts
**/accuracy.ts
**/adminHelpers.ts
3 changes: 2 additions & 1 deletion config/development.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const config: Config = {
scoutingInternal: {
teamNumber: "admin",
accessToken: "admin"
}
},
adminTokens: secret.development.auth.adminTokens
},
features: ["scouting", "resources", "tps"],
year: 2024
Expand Down
1 change: 1 addition & 0 deletions config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface Config {
teamNumber: string;
accessToken: string;
};
adminTokens: any;
};
features: string[];
year: number;
Expand Down
3 changes: 1 addition & 2 deletions config/scouting/2024/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1471,8 +1471,7 @@ async function syncPredictCache(event, redTeamNumbers, blueTeamNumbers) {
)
.toString()
);
let predictionRed =
prediction.red / (prediction.red + prediction.blue);
let predictionRed = prediction.red / (prediction.red + prediction.blue);
let predictionBlue =
prediction.blue / (prediction.blue + prediction.red);
if (predictionRed > 0.85) {
Expand Down
19 changes: 17 additions & 2 deletions helpers/apiKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { APIKeyType } from "../models/apiKey";
import * as crypto from "crypto";

function ensureType(data: any): any {
console.log(data);
if (data == null || typeof data !== "object") {
return {};
}
Expand All @@ -14,7 +13,8 @@ function ensureType(data: any): any {
typeof data.app !== "string" ||
!Array.isArray(data.scopes) ||
typeof data.expiration !== "number" ||
typeof data.source !== "string"
typeof data.source !== "string" ||
typeof data.limit !== "number"
) {
return {};
}
Expand All @@ -26,6 +26,7 @@ function ensureType(data: any): any {
obj.scopes = data.scopes;
obj.expiration = data.expiration;
obj.source = data.source;
obj.limit = data.limit;
return obj;
}

Expand Down Expand Up @@ -53,6 +54,7 @@ export async function addAPIKey(rawOptions: any) {
options.hashType = "sha256";
options.apiKey = hashKey(unhashed, options.hashType);
options.apiIdentifier = generateAPIIdentifier();
options.limit = options.limit || 2500; // a default character limit
options.name =
options.name ||
`${options.app} (${options.apiIdentifier.split("-")[0]})`;
Expand Down Expand Up @@ -136,3 +138,16 @@ export function removeAll() {
export async function getAll() {
return await APIKey.find({}).lean();
}

/**
* Retrive the rate limit and team number for a given API key.
* @param apiKey the API key to verify
* @returns the team number and rate limit for the given API key
*/
export async function retrieveRateLimit(apiKey) {
const info = await verifyAPIKey(apiKey, null, null, null, [], []); // verification already happened, just retrieve the team # + rate limit
if (!info.verified) {
return { teamNumber: "", rateLimit: 0 };
}
return { teamNumber: info.key.team, rateLimit: info.key.rateLimit };
}
14 changes: 14 additions & 0 deletions helpers/tba.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,17 @@ export async function getMatchesFull(event) {
}
return cache.matchesFull[event].value;
}

export async function getTeam(teamNumber) {
try {
let team = await (
await fetch(
`https://www.thebluealliance.com/api/v3/team/frc${encodeURIComponent(
teamNumber
)}/simple?X-TBA-Auth-Key=${encodeURIComponent(config.auth.tba)}`
)
).json();
return team;
} catch (err) {}
return {};
}
4 changes: 4 additions & 0 deletions helpers/teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export function getTeamByNumber(teamNumber: string) {
return Team.findOne({ teamNumber });
}

export function getAllTeams() {
return Team.find().lean();
}

export async function teamExistsByNumber(teamNumber: string) {
return (await getTeamByNumber(teamNumber)) != null;
}
Expand Down
9 changes: 8 additions & 1 deletion helpers/tps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,19 @@ export async function addEntry(
data: any,
privacy: any,
threshold: number,
maxLength: number,
serverTimestamp: number
) {
const serialized = sortedStringify(data);
if (serialized.length > maxLength) {
throw new Error(`Given data exceeds the maximum length of ${maxLength} characters!`);
}

let hash = crypto
.createHash("sha256")
.update(sortedStringify(data))
.update(serialized)
.digest("hex");

let entry = (await getEntryByHash(hash)) as any;
if (entry == null) {
data.privacy = privacy;
Expand Down
25 changes: 25 additions & 0 deletions middleware/rateLimiter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { RateLimit, Stores } from 'koa2-ratelimit';
import mongoose from "../db";

import { retrieveRateLimit } from "../helpers/apiKey"

const mongo = new Stores.Mongodb(mongoose.connection, {
collectionName: 'ratelimits',
collectionAbuseName: 'ratelimitsabuses',
});

export const rateLimiter = RateLimit.middleware({
interval: { sec: 1 }, // 1 second
max: async (ctx) => {
const apiKey = ctx.query.key;
const rateInfo = await retrieveRateLimit(apiKey);
return rateInfo.rateLimit; // max requests per second per team
},
keyGenerator: async (ctx) => {
const apiKey = ctx.query.key;
const rateInfo = await retrieveRateLimit(apiKey);
return `teamid:${rateInfo.teamNumber}`; // team number as key
},
store: mongo,
message: "Exceeded the rate limit. Try again later."
});
5 changes: 5 additions & 0 deletions models/apiKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface APIKeyType {
username: string;
team: string;
app: string;
limit: number; // in characters
scopes: string[];
expiration: number;
creation: number;
Expand Down Expand Up @@ -42,6 +43,10 @@ export default mongoose.model(
required: true,
type: String
},
limit: {
required: true,
type: Number
},
scopes: {
required: true,
type: Array
Expand Down
1 change: 1 addition & 0 deletions models/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default mongoose.model(
new mongoose.Schema({
teamName: String,
teamNumber: String,
rateLimit: Number, // in requests per second
accessToken: String,
country: String,
state: String
Expand Down
Loading

0 comments on commit ec21b31

Please sign in to comment.