Remove deprecated endpoints

This commit is contained in:
Jordan Eldredge 2025-06-04 21:05:54 -07:00
parent 71f754f9f9
commit 2a055064a1
6 changed files with 1 additions and 494 deletions

View file

@ -4,7 +4,6 @@ import request from "supertest"; // supertest is a framework that allows to easi
import { createApp } from "../app";
import SkinModel from "../../data/SkinModel";
import * as S3 from "../../s3";
import * as Auth from "../auth";
import { processUserUploads } from "../processUserUploads";
import UserContext from "../../data/UserContext";
import { searchIndex } from "../../algolia";
@ -106,37 +105,6 @@ describe(".me", () => {
});
});
// TODO: The redirect_uri is different on github
test("/auth", async () => {
const { body } = await request(app).get("/auth").expect(302);
// TODO: The redirect_uri is different on github
// .expect(
// "Location",
// "https://discord.com/api/oauth2/authorize?client_id=%3CDUMMY_DISCORD_CLIENT_ID%3E&redirect_uri=https%3A%2F%2Fapi.webampskins.org%2Fauth%2Fdiscord&response_type=code&scope=identify%20guilds"
// );
expect(body).toEqual({});
});
describe("/auth/discord", () => {
test("valid code", async () => {
const response = await request(app)
.get("/auth/discord")
.query({ code: "<A_FAKE_CODE>" })
.expect(302);
// TODO: The location is different on github
// .expect("Location", "https://skins.webamp.org/review/");
// TODO: Assert that we get cookie headers. I think that will not work now
// because express does not think it's secure in a test env.
expect(Auth.auth).toHaveBeenCalledWith("<A_FAKE_CODE>");
expect(response.body).toEqual({});
});
test("missing code", async () => {
const { body } = await request(app).get("/auth/discord").expect(400);
expect(Auth.auth).not.toHaveBeenCalled();
expect(body).toEqual({ message: "Expected to get a code" });
});
});
describe("Query.skins", () => {
test("no query params", async () => {
const { data } = await graphQLRequest(

View file

@ -1,381 +0,0 @@
import { Application } from "express";
import { knex } from "../../db";
import request from "supertest"; // supertest is a framework that allows to easily test web apis
import { createApp } from "../app";
import SkinModel from "../../data/SkinModel";
import * as S3 from "../../s3";
import * as Auth from "../auth";
import { processUserUploads } from "../processUserUploads";
import UserContext from "../../data/UserContext";
import { searchIndex } from "../../algolia";
jest.mock("../../s3");
jest.mock("../../algolia");
jest.mock("../processUserUploads");
jest.mock("../auth");
let app: Application;
const handler = jest.fn();
const log = jest.fn();
const logError = jest.fn();
let username: string | undefined;
beforeEach(async () => {
jest.clearAllMocks();
username = "<MOCKED>";
app = createApp({
eventHandler: handler,
extraMiddleware: (req, res, next) => {
req.session.username = username;
next();
},
logger: { log, logError },
});
await knex.migrate.latest();
await knex.seed.run();
});
describe("/authed", () => {
test("logged in ", async () => {
const { body } = await request(app).get("/authed").expect(200);
expect(body).toEqual({ username: "<MOCKED>" });
});
test("not logged in", async () => {
username = undefined;
const { body } = await request(app).get("/authed").expect(200);
expect(body).toEqual({ username: null });
});
});
test.skip("/auth", async () => {
const { body } = await request(app)
.get("/auth")
.expect(302)
.expect(
"Location",
"https://discord.com/api/oauth2/authorize?client_id=%3CDUMMY_DISCORD_CLIENT_ID%3E&redirect_uri=https%3A%2F%2Fapi.webampskins.org%2Fauth%2Fdiscord&response_type=code&scope=identify%20guilds"
);
expect(body).toEqual({});
});
describe.skip("/auth/discord", () => {
test("valid code", async () => {
const response = await request(app)
.get("/auth/discord")
.query({ code: "<A_FAKE_CODE>" })
.expect(302)
.expect("Location", "https://skins.webamp.org/review/");
// TODO: Assert that we get cookie headers. I think that will not work now
// because express does not think it's secure in a test env.
expect(Auth.auth).toHaveBeenCalledWith("<A_FAKE_CODE>");
expect(response.body).toEqual({});
});
test("missing code", async () => {
const { body } = await request(app).get("/auth/discord").expect(400);
expect(Auth.auth).not.toHaveBeenCalled();
expect(body).toEqual({ message: "Expected to get a code" });
});
});
describe("/skins/", () => {
test("no query params", async () => {
const { body } = await request(app).get("/skins/");
expect(body).toMatchInlineSnapshot(`
Object {
"skinCount": 6,
"skins": Array [
Object {
"fileName": "tweeted.wsz",
"md5": "a_tweeted_md5",
"nsfw": false,
},
Object {
"fileName": "Zelda_Amp_3.wsz",
"md5": "48bbdbbeb03d347e59b1eebda4d352d0",
"nsfw": false,
},
Object {
"fileName": "path.wsz",
"md5": "a_fake_md5",
"nsfw": false,
},
Object {
"fileName": "approved.wsz",
"md5": "an_approved_md5",
"nsfw": false,
},
Object {
"fileName": "rejected.wsz",
"md5": "a_rejected_md5",
"nsfw": false,
},
Object {
"fileName": "nsfw.wsz",
"md5": "a_nsfw_md5",
"nsfw": true,
},
],
}
`);
});
test("first and offset", async () => {
const { body } = await request(app)
.get("/skins/")
.query({ first: 2, offset: 1 });
expect(body).toMatchInlineSnapshot(`
Object {
"skinCount": 6,
"skins": Array [
Object {
"fileName": "Zelda_Amp_3.wsz",
"md5": "48bbdbbeb03d347e59b1eebda4d352d0",
"nsfw": false,
},
Object {
"fileName": "path.wsz",
"md5": "a_fake_md5",
"nsfw": false,
},
],
}
`);
});
});
// This is deprecated and fails in CI due to printing as localize date string.
test.skip("/skins/a_fake_md5/debug", async () => {
const { body } = await request(app)
.get("/skins/a_fake_md5/debug")
.expect(200);
expect(body).toMatchSnapshot();
});
test("/skins/a_fake_md5/report", async () => {
const { body } = await request(app)
.post("/skins/a_fake_md5/report")
.expect(200);
expect(handler).toHaveBeenCalledWith({
type: "REVIEW_REQUESTED",
md5: "a_fake_md5",
});
expect(body).toEqual({}); // TODO: Where does the text response go?
});
test("/skins/a_fake_md5/approve", async () => {
const ctx = new UserContext();
const { body } = await request(app)
.post("/skins/a_fake_md5/approve")
.expect(200);
expect(handler).toHaveBeenCalledWith({
type: "APPROVED_SKIN",
md5: "a_fake_md5",
});
expect(body).toEqual({ message: "The skin has been approved." });
const skin = await SkinModel.fromMd5(ctx, "a_fake_md5");
expect(await skin?.getTweetStatus()).toEqual("APPROVED");
});
describe("/to_review", () => {
test("logged in ", async () => {
const { body } = await request(app).get("/to_review").expect(200);
expect(body).toEqual({
filename: expect.any(String),
md5: expect.any(String),
});
});
test("not logged in ", async () => {
username = undefined;
const { body } = await request(app).get("/to_review").expect(403);
expect(body).toEqual({ message: "You must be logged in" });
});
});
test("/skins/a_md5_that_does_not_exist/approve (404)", async () => {
const { body } = await request(app)
.post("/skins/a_md5_that_does_not_exist/approve")
.expect(404);
expect(body).toEqual({});
expect(handler).not.toHaveBeenCalled();
});
test("/skins/a_fake_md5/reject", async () => {
const ctx = new UserContext();
const { body } = await request(app)
.post("/skins/a_fake_md5/reject")
.expect(200);
expect(handler).toHaveBeenCalledWith({
type: "REJECTED_SKIN",
md5: "a_fake_md5",
});
expect(body).toEqual({ message: "The skin has been rejected." }); // TODO: Where does the text response go?
const skin = await SkinModel.fromMd5(ctx, "a_fake_md5");
expect(await skin?.getTweetStatus()).toEqual("REJECTED");
});
test("/skins/a_md5_that_does_not_exist/reject (404)", async () => {
const { body } = await request(app)
.post("/skins/a_md5_that_does_not_exist/reject")
.expect(404);
expect(body).toEqual({});
expect(handler).not.toHaveBeenCalled();
});
test("/skins/a_fake_md5/nsfw", async () => {
const ctx = new UserContext();
const { body } = await request(app)
.post("/skins/a_fake_md5/nsfw")
.expect(200);
expect(handler).toHaveBeenCalledWith({
type: "MARKED_SKIN_NSFW",
md5: "a_fake_md5",
});
expect(searchIndex.partialUpdateObjects).toHaveBeenCalledWith([
{ nsfw: true, objectID: "a_fake_md5" },
]);
expect(body).toEqual({ message: "The skin has been marked as NSFW." });
const skin = await SkinModel.fromMd5(ctx, "a_fake_md5");
expect(await skin?.getTweetStatus()).toEqual("NSFW");
});
// TODO: Actually upload some skins?
test("/skins/status", async () => {
const { body } = await request(app)
.post("/skins/status")
.send({ hashes: ["a_fake_md5", "a_missing_md5"] });
expect(body).toEqual({});
});
test("/approved", async () => {
const { body } = await request(app).get("/approved").expect(200);
expect(body).toEqual(["an_approved_md5", "a_tweeted_md5"]);
});
test("/skins/a_fake_md5", async () => {
let response = await request(app).get("/skins/a_fake_md5");
expect(response.body).toEqual({
fileName: "path.wsz",
md5: "a_fake_md5",
nsfw: false,
});
response = await request(app).get("/skins/a_nsfw_md5");
expect(response.body).toEqual({
fileName: "nsfw.wsz",
md5: "a_nsfw_md5",
nsfw: true,
});
await request(app).get("/skins/does_not_exist_md5").expect(404);
});
test("/skins/get_upload_urls", async () => {
const { body } = await request(app)
.post("/skins/get_upload_urls")
.send({
skins: {
"3b73bcd43c30b85d4cad3083e8ac9695": "a_fake_new_file.wsz",
"48bbdbbeb03d347e59b1eebda4d352d0":
"a_new_name_for_a_file_that_exists.wsz",
},
});
expect(S3.getSkinUploadUrl).toHaveBeenCalledWith(
"3b73bcd43c30b85d4cad3083e8ac9695",
expect.any(Number)
);
expect(body).toEqual({
"3b73bcd43c30b85d4cad3083e8ac9695": {
id: expect.any(Number),
url: "<MOCK_S3_UPLOAD_URL>",
},
});
});
test("An Upload Flow", async () => {
// Request an upload URL
const md5 = "3b73bcd43c30b85d4cad3083e8ac9695";
const filename = "a_fake_new_file.wsz";
const skins = { [md5]: filename };
const getUrlsResponse = await request(app)
.post("/skins/get_upload_urls")
.send({ skins });
const id = getUrlsResponse.body[md5].id;
expect(getUrlsResponse.body).toEqual({
[md5]: { id: expect.any(Number), url: "<MOCK_S3_UPLOAD_URL>" },
});
const requestedUpload = await knex("skin_uploads").where({ id }).first();
expect(requestedUpload).toEqual({
filename,
id,
skin_md5: md5,
status: "URL_REQUESTED",
});
// Report that we've uploaded the skin to S3 (we lie)
const uploadedResponse = await request(app)
.post(`/skins/${md5}/uploaded`)
.query({ id })
.send({ skins });
expect(uploadedResponse.body).toEqual({ done: true });
expect(processUserUploads).toHaveBeenCalled();
const reportedUpload = await knex("skin_uploads").where({ id }).first();
expect(reportedUpload).toEqual({
filename,
id,
skin_md5: md5,
status: "UPLOAD_REPORTED",
});
});
test("/stylegan.json", async () => {
const response = await request(app).get("/stylegan.json");
expect(response.body).toMatchInlineSnapshot(`
Array [
Object {
"fileName": "Zelda_Amp_3.wsz",
"md5": "48bbdbbeb03d347e59b1eebda4d352d0",
"nsfw": false,
"url": "https://r2.webampskins.org/screenshots/48bbdbbeb03d347e59b1eebda4d352d0.png",
},
Object {
"fileName": "path.wsz",
"md5": "a_fake_md5",
"nsfw": false,
"url": "https://r2.webampskins.org/screenshots/a_fake_md5.png",
},
Object {
"fileName": "nsfw.wsz",
"md5": "a_nsfw_md5",
"nsfw": true,
"url": "https://r2.webampskins.org/screenshots/a_nsfw_md5.png",
},
Object {
"fileName": "rejected.wsz",
"md5": "a_rejected_md5",
"nsfw": false,
"url": "https://r2.webampskins.org/screenshots/a_rejected_md5.png",
},
Object {
"fileName": "tweeted.wsz",
"md5": "a_tweeted_md5",
"nsfw": false,
"url": "https://r2.webampskins.org/screenshots/a_tweeted_md5.png",
},
Object {
"fileName": "approved.wsz",
"md5": "an_approved_md5",
"nsfw": false,
"url": "https://r2.webampskins.org/screenshots/an_approved_md5.png",
},
]
`);
});

View file

@ -1,7 +1,5 @@
import router from "./router";
import graphql from "./graphql";
import cors, { CorsOptions } from "cors";
import bodyParser from "body-parser";
import Sentry from "@sentry/node";
import expressSitemapXml from "express-sitemap-xml";
import * as Skins from "../data/skins";
@ -139,17 +137,10 @@ export function createApp({ eventHandler, extraMiddleware, logger }: Options) {
app.use(cors(corsOptions));
app.options("*", cors(corsOptions));
// Configure json output
app.set("json spaces", 2);
// parse application/json
app.use(bodyParser.json() as RequestHandler);
// Configure sitemap
app.use(expressSitemapXml(getSitemapUrls, "https://skins.webamp.org"));
// Add routes
app.use("/", router);
app.use("/graphql", graphql);
// The error handler must be before any other error middleware and after all controllers

View file

@ -1,48 +0,0 @@
import { Router } from "express";
import asyncHandler from "express-async-handler";
import {
DISCORD_CLIENT_ID,
DISCORD_REDIRECT_URL,
LOGIN_REDIRECT_URL,
} from "../config";
import { auth } from "./auth";
const router = Router();
// Purposefully REST
router.get(
"/auth/",
asyncHandler(async (req, res) => {
res.redirect(
302,
`https://discord.com/api/oauth2/authorize?client_id=${encodeURIComponent(
DISCORD_CLIENT_ID
)}&redirect_uri=${encodeURIComponent(
DISCORD_REDIRECT_URL
)}&response_type=code&scope=identify%20guilds`
);
})
);
// Purposefully REST
router.get(
"/auth/discord",
asyncHandler(async (req, res) => {
const code = req.query.code as string | undefined;
if (code == null) {
res.status(400).send({ message: "Expected to get a code" });
return;
}
const username = await auth(code);
if (username == null) {
res.status(400).send({ message: "Invalid code" });
return;
}
req.session.username = username;
// TODO: What about dev?
res.redirect(302, LOGIN_REDIRECT_URL);
})
);
export default router;

View file

@ -56,7 +56,6 @@
"prettier": {},
"devDependencies": {
"@babel/preset-typescript": "^7.10.1",
"@types/body-parser": "^1.19.5",
"@types/cookie-session": "^2.0.48",
"@types/cors": "^2.8.17",
"@types/express": "4.17.9",

View file

@ -5925,7 +5925,7 @@
dependencies:
"@babel/types" "^7.20.7"
"@types/body-parser@*", "@types/body-parser@^1.19.5":
"@types/body-parser@*":
version "1.19.5"
resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz"
integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==
@ -5940,13 +5940,6 @@
dependencies:
"@types/node" "*"
"@types/busboy@*":
version "1.5.3"
resolved "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.3.tgz"
integrity sha512-YMBLFN/xBD8bnqywIlGyYqsNFXu6bsiY7h3Ae0kO17qEuTjsqeyYMRPSUDacIKIquws2Y6KjmxAyNx8xB3xQbw==
dependencies:
"@types/node" "*"
"@types/cacheable-request@^6.0.1":
version "6.0.3"
resolved "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz"
@ -6080,14 +6073,6 @@
resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz"
integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==
"@types/express-fileupload@^1.4.4":
version "1.5.0"
resolved "https://registry.npmjs.org/@types/express-fileupload/-/express-fileupload-1.5.0.tgz"
integrity sha512-Y9v88IC5ItAxkKwfnyIi1y0jSZwTMY4jqXUQLZ3jFhYJlLdRnN919bKBNM8jbVVD2cxywA/uEC1kNNpZQGwx7Q==
dependencies:
"@types/busboy" "*"
"@types/express" "*"
"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33":
version "4.17.43"
resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz"
@ -13642,13 +13627,6 @@ express-async-handler@^1.1.4:
resolved "https://registry.npmjs.org/express-async-handler/-/express-async-handler-1.2.0.tgz"
integrity sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==
express-fileupload@^1.1.7-alpha.3:
version "1.5.0"
resolved "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.0.tgz"
integrity sha512-jSW3w9evqM37VWkEPkL2Ck5wUo2a8qa03MH+Ou/0ZSTpNlQFBvSLjU12k2nYcHhaMPv4JVvv6+Ac1OuLgUZb7w==
dependencies:
busboy "^1.6.0"
express-graphql@^0.12.0:
version "0.12.0"
resolved "https://registry.npmjs.org/express-graphql/-/express-graphql-0.12.0.tgz"