mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-30 10:58:07 +03:00
Refactor permissions for IRs
This commit is contained in:
@@ -33,11 +33,6 @@ t.test("#ConverterIRBarbatos", (t) => {
|
||||
playtype: "Single",
|
||||
levelNum: 10,
|
||||
level: "10",
|
||||
flags: {
|
||||
"IN BASE GAME": true,
|
||||
OMNIMIX: false,
|
||||
"N-1": false,
|
||||
},
|
||||
data: {
|
||||
inGameID: 1,
|
||||
},
|
||||
|
||||
@@ -158,22 +158,28 @@ export const RequirePermissions =
|
||||
return next();
|
||||
};
|
||||
|
||||
export const RequireNotGuest: RequestHandler = (req, res, next) => {
|
||||
if (!req[SYMBOL_TachiAPIAuth]) {
|
||||
logger.error(`RequirePermissions middleware was hit without any TachiAPIData?`);
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
description: "An internal error has occured.",
|
||||
});
|
||||
}
|
||||
const CreateRequireNotGuest =
|
||||
(errorKeyName: string): RequestHandler =>
|
||||
(req, res, next) => {
|
||||
if (!req[SYMBOL_TachiAPIAuth]) {
|
||||
logger.error(`RequirePermissions middleware was hit without any TachiAPIData?`);
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
description: "An internal error has occured.",
|
||||
});
|
||||
}
|
||||
|
||||
if (!req[SYMBOL_TachiAPIAuth].userID) {
|
||||
logger.info(`Request to ${req.method} ${req.url} was attempted by guest.`);
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
description: "This endpoint requires authentication.",
|
||||
});
|
||||
}
|
||||
if (req[SYMBOL_TachiAPIAuth].userID === null) {
|
||||
logger.info(`Request to ${req.method} ${req.url} was attempted by guest.`);
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
[errorKeyName]: "This endpoint requires authentication.",
|
||||
});
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
return next();
|
||||
};
|
||||
|
||||
export const RequireNotGuest: RequestHandler = CreateRequireNotGuest("description");
|
||||
|
||||
export const FervidexStyleRequireNotGuest: RequestHandler = CreateRequireNotGuest("error");
|
||||
|
||||
@@ -5,6 +5,7 @@ import CreateLogCtx, { KtLogger } from "lib/logger/logger";
|
||||
import { ExpressWrappedScoreImportMain } from "lib/score-import/framework/express-wrapper";
|
||||
import { ParseBeatorajaSingle } from "lib/score-import/import-types/ir/beatoraja/parser";
|
||||
import { ServerConfig } from "lib/setup/config";
|
||||
import { RequireNotGuest } from "server/middleware/auth";
|
||||
import { UpdateClassIfGreater } from "utils/class";
|
||||
import { GetUserWithIDGuaranteed } from "utils/user";
|
||||
import { ValidateIRClientVersion } from "./auth";
|
||||
@@ -21,7 +22,7 @@ router.use(ValidateIRClientVersion);
|
||||
*
|
||||
* @name POST /ir/beatoraja/submit-score
|
||||
*/
|
||||
router.post("/submit-score", async (req, res) => {
|
||||
router.post("/submit-score", RequireNotGuest, async (req, res) => {
|
||||
const userDoc = await GetUserWithIDGuaranteed(req[SYMBOL_TachiAPIAuth]!.userID!);
|
||||
|
||||
const ParserFunction = (logger: KtLogger) => ParseBeatorajaSingle(req.body, userDoc.id, logger);
|
||||
@@ -91,7 +92,7 @@ router.post("/submit-score", async (req, res) => {
|
||||
*
|
||||
* @name POST /ir/beatoraja/submit-course
|
||||
*/
|
||||
router.post("/submit-course", async (req, res) => {
|
||||
router.post("/submit-course", RequireNotGuest, async (req, res) => {
|
||||
const charts = req.body.course?.charts;
|
||||
|
||||
if (
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import t from "tap";
|
||||
import { InsertFakeTokenWithAllPerms } from "test-utils/fake-auth";
|
||||
import mockApi from "test-utils/mock-api";
|
||||
import ResetDBState from "test-utils/resets";
|
||||
import { TestingKsHookSV3CScore } from "test-utils/test-data";
|
||||
|
||||
t.test("POST /ir/kshook/sv3c/score/save", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
t.beforeEach(InsertFakeTokenWithAllPerms("mock_token"));
|
||||
|
||||
t.test("Should import a valid score to the database.", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/kshook/sv3c/score/save")
|
||||
.set("Authorization", "Bearer mock_token")
|
||||
.set("User-Agent", "kshook/0.1.0")
|
||||
.set("X-Software-Model", "QCV:J:C:A:2021100600")
|
||||
.send(TestingKsHookSV3CScore);
|
||||
|
||||
t.equal(res.status, 200);
|
||||
t.equal(res.body.success, true);
|
||||
t.equal(res.body.body.scoreIDs.length, 1, "Should import one score.");
|
||||
t.equal(res.body.body.errors.length, 0, "Should have 0 failed scores.");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should reject scores with invalid software models.", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/kshook/sv3c/score/save")
|
||||
.set("Authorization", "Bearer mock_token")
|
||||
.set("User-Agent", "kshook/0.1.0")
|
||||
.set("X-Software-Model", "LDJ:J:C:A:2021100600")
|
||||
.send(TestingKsHookSV3CScore);
|
||||
|
||||
t.equal(res.status, 400, "Should reject an import with invalid software model.");
|
||||
t.type(res.body.error, "string", "Should have an error message.");
|
||||
|
||||
const res2 = await mockApi
|
||||
.post("/ir/kshook/sv3c/score/save")
|
||||
.set("Authorization", "Bearer mock_token")
|
||||
.set("User-Agent", "kshook/0.1.0")
|
||||
.send(TestingKsHookSV3CScore);
|
||||
|
||||
t.equal(res2.status, 400, "Should reject an import with no software model.");
|
||||
t.type(res2.body.error, "string", "Should have an error message.");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should reject scores with invalid auth.", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/kshook/sv3c/score/save")
|
||||
.set("Authorization", "Bearer foo")
|
||||
.set("User-Agent", "kshook/0.1.0")
|
||||
.set("X-Software-Model", "QCV:J:C:A:2021100600")
|
||||
.send(TestingKsHookSV3CScore);
|
||||
|
||||
t.equal(res.status, 401, "Should reject an import with invalid authentication.");
|
||||
t.type(res.body.error, "string", "Should have an error message.");
|
||||
|
||||
const res2 = await mockApi
|
||||
.post("/ir/kshook/sv3c/score/save")
|
||||
.set("User-Agent", "kshook/0.1.0")
|
||||
.set("X-Software-Model", "QCV:J:C:A:2021100600")
|
||||
.send(TestingKsHookSV3CScore);
|
||||
|
||||
t.equal(res2.status, 401, "Should reject an import with no authentication.");
|
||||
t.type(res2.body.error, "string", "Should have an error message.");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -73,6 +73,8 @@ const ValidateHeaders: RequestHandler = (req, res, next) => {
|
||||
return next();
|
||||
};
|
||||
|
||||
router.use(ValidateHeaders);
|
||||
|
||||
/**
|
||||
* Saves a SDVX Konaste score.
|
||||
*
|
||||
|
||||
@@ -7,14 +7,19 @@ import uscIR from "./usc/router";
|
||||
import beatorajaIR from "./beatoraja/router";
|
||||
import ksHookIR from "./kshook/router";
|
||||
import { RequireBokutachi, RequireKamaitachi } from "../../middleware/type-require";
|
||||
import { SetFervidexStyleRequestPermissions, SetRequestPermissions } from "../../middleware/auth";
|
||||
import {
|
||||
FervidexStyleRequireNotGuest,
|
||||
RequireNotGuest,
|
||||
SetFervidexStyleRequestPermissions,
|
||||
SetRequestPermissions,
|
||||
} from "../../middleware/auth";
|
||||
|
||||
const router: Router = Router({ mergeParams: true });
|
||||
|
||||
// Common IRs
|
||||
|
||||
router.use("/direct-manual", SetRequestPermissions, directManualIR);
|
||||
router.use("/kshook", SetFervidexStyleRequestPermissions, ksHookIR);
|
||||
router.use("/direct-manual", SetRequestPermissions, RequireNotGuest, directManualIR);
|
||||
router.use("/kshook", SetFervidexStyleRequestPermissions, FervidexStyleRequireNotGuest, ksHookIR);
|
||||
|
||||
// Bokutachi IRs
|
||||
|
||||
@@ -26,8 +31,14 @@ router.use("/beatoraja", SetRequestPermissions, RequireBokutachi, beatorajaIR);
|
||||
|
||||
// Kamaitachi IRs
|
||||
|
||||
router.use("/barbatos", SetRequestPermissions, RequireKamaitachi, barbatosIR);
|
||||
router.use("/chunitachi", SetRequestPermissions, RequireKamaitachi, chunitachiIR);
|
||||
router.use("/fervidex", SetFervidexStyleRequestPermissions, RequireKamaitachi, fervidexIR);
|
||||
router.use("/barbatos", SetRequestPermissions, RequireNotGuest, RequireKamaitachi, barbatosIR);
|
||||
router.use("/chunitachi", SetRequestPermissions, RequireNotGuest, RequireKamaitachi, chunitachiIR);
|
||||
router.use(
|
||||
"/fervidex",
|
||||
SetFervidexStyleRequestPermissions,
|
||||
FervidexStyleRequireNotGuest,
|
||||
RequireKamaitachi,
|
||||
fervidexIR
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
[
|
||||
{
|
||||
"rgcID": null,
|
||||
"chartID": "5088a4d0e1ee9d0cc2f625934306e45b1a60699b",
|
||||
"difficulty": "ADV",
|
||||
"songID": 1,
|
||||
"playtype": "Single",
|
||||
"levelNum": 10,
|
||||
"level": "10",
|
||||
"flags": {
|
||||
"IN BASE GAME": true,
|
||||
"OMNIMIX": false,
|
||||
"N-1": false
|
||||
},
|
||||
"data": {
|
||||
"inGameID": 1,
|
||||
"uscEquiv": null,
|
||||
"arcChartID": "EOZ7FixCDpv"
|
||||
},
|
||||
"isPrimary": true,
|
||||
"versions": [
|
||||
"booth",
|
||||
"inf",
|
||||
"gw",
|
||||
"heaven",
|
||||
"vivid"
|
||||
]
|
||||
}
|
||||
{
|
||||
"rgcID": null,
|
||||
"chartID": "5088a4d0e1ee9d0cc2f625934306e45b1a60699b",
|
||||
"difficulty": "ADV",
|
||||
"songID": 1,
|
||||
"playtype": "Single",
|
||||
"levelNum": 10,
|
||||
"level": "10",
|
||||
"data": {
|
||||
"inGameID": 1,
|
||||
"arcChartID": "EOZ7FixCDpv"
|
||||
},
|
||||
"isPrimary": true,
|
||||
"versions": [
|
||||
"booth",
|
||||
"inf",
|
||||
"gw",
|
||||
"heaven",
|
||||
"vivid",
|
||||
"konaste"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import { DryScore } from "lib/score-import/framework/common/types";
|
||||
import { BarbatosScore } from "lib/score-import/import-types/ir/barbatos/types";
|
||||
import { USCClientScore } from "../server/router/ir/usc/types";
|
||||
import { KsHookSV3CScore } from "lib/score-import/import-types/ir/kshook-sv3c/types";
|
||||
|
||||
const file = (name: string) => path.join(__dirname, "/test-data", name);
|
||||
|
||||
@@ -38,6 +39,8 @@ export const TestingIIDXSPScore = GetKTDataJSON(
|
||||
"./tachi/iidx-score.json"
|
||||
) as ScoreDocument<"iidx:SP">;
|
||||
|
||||
export const TestingKsHookSV3CScore = GetKTDataJSON("./kshook-sv3c/base.json") as KsHookSV3CScore;
|
||||
|
||||
export const Testing511SPA = GetKTDataJSON("./tachi/iidx-511spa.json") as ChartDocument<"iidx:SP">;
|
||||
|
||||
export const Testing511Song = GetKTDataJSON("./tachi/iidx-511-song.json") as SongDocument<"iidx">;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"appeal_id": 2001,
|
||||
"btn_rate": 182,
|
||||
"clear": "CLEAR_EXCESSIVE",
|
||||
"critical": 1184,
|
||||
"difficulty": "DIFFICULTY_ADVANCED",
|
||||
"early": 36,
|
||||
"error": 30,
|
||||
"gauge": 71,
|
||||
"grade": "GRADE_AA_PLUS",
|
||||
"late": 10,
|
||||
"long_rate": 195,
|
||||
"max_chain": 158,
|
||||
"music_id": 1,
|
||||
"near": 46,
|
||||
"player_name": "EE",
|
||||
"rate": "RATE_EXCESSIVE",
|
||||
"score": 9579365,
|
||||
"skill_frame": "SKILL_FRAME_NONE",
|
||||
"skill_level": "SKILL_LEVEL_NONE",
|
||||
"skill_name": 5,
|
||||
"track_no": 0,
|
||||
"vol_rate": 193
|
||||
}
|
||||
@@ -1,27 +1,22 @@
|
||||
{
|
||||
"rgcID": null,
|
||||
"chartID": "5088a4d0e1ee9d0cc2f625934306e45b1a60699b",
|
||||
"difficulty": "ADV",
|
||||
"songID": 1,
|
||||
"playtype": "Single",
|
||||
"levelNum": 10,
|
||||
"level": "10",
|
||||
"flags": {
|
||||
"IN BASE GAME": true,
|
||||
"OMNIMIX": false,
|
||||
"N-1": false
|
||||
},
|
||||
"data": {
|
||||
"inGameID": 1,
|
||||
"uscEquiv": null,
|
||||
"arcChartID": "EOZ7FixCDpv"
|
||||
},
|
||||
"isPrimary": true,
|
||||
"versions": [
|
||||
"booth",
|
||||
"inf",
|
||||
"gw",
|
||||
"heaven",
|
||||
"vivid"
|
||||
]
|
||||
"rgcID": null,
|
||||
"chartID": "5088a4d0e1ee9d0cc2f625934306e45b1a60699b",
|
||||
"difficulty": "ADV",
|
||||
"songID": 1,
|
||||
"playtype": "Single",
|
||||
"levelNum": 10,
|
||||
"level": "10",
|
||||
"data": {
|
||||
"inGameID": 1,
|
||||
"arcChartID": "EOZ7FixCDpv"
|
||||
},
|
||||
"isPrimary": true,
|
||||
"versions": [
|
||||
"booth",
|
||||
"inf",
|
||||
"gw",
|
||||
"heaven",
|
||||
"vivid",
|
||||
"konaste"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user