返回提交历史
Modified
src/controllers/api/loginController.ts
+1
-1
Modified
src/controllers/api/setActiveShipController.ts
+1
-4
Modified
src/controllers/api/signupAndroidController.ts
+1
-1
Deleted
src/controllers/custom/createAccountController.ts
+0
-16
Deleted
src/helpers/customHelpers/customHelpers.ts
+0
-74
Modified
src/helpers/general.ts
+1
-66
Modified
src/routes/custom.ts
+0
-2
Modified
src/services/loginService.ts
+25
-2
Modified
src/services/questService.ts
+2
-2
Modified
src/services/saveLoadoutService.ts
+2
-2
Deleted
src/types/customTypes.ts
+0
-11
Modified
src/types/loginTypes.ts
+7
-2
XFEstudio/SpaceNinjaServer
chore: remove /custom/createAccount endpoint (#4107)
Not that it's an entirely useless endpoint, but way too much code for something no one was using. Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/4107 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
bd0cfb54
代码差异
12 个文件
+40
-183
@@ -7,6 +7,7 @@ import {
7
7
buildVersionToInt,
8
8
createAccount,
9
9
createNonce,
10
getGoogleAccountData,
10
11
getUsernameFromEmail,
11
12
isCorrectPassword
12
13
} from "../../services/loginService.ts";
@@ -25,7 +26,6 @@ import { fromStoreItem } from "../../services/itemDataService.ts";
25
26
import { getTokenForClient, getTunablesForClient } from "../../services/tunablesService.ts";
26
27
import type { AddressInfo } from "node:net";
27
28
import gameToBuildVersion from "../../constants/gameToBuildVersion.ts";
28
import { getGoogleAccountData } from "../../helpers/customHelpers/customHelpers.ts";
29
29
import { args } from "../../helpers/commandLineArguments.ts";
30
30
31
31
export const loginController: RequestHandler = async (request, response) => {
@@ -1,15 +1,12 @@
1
1
import { getPersonalRooms } from "../../services/personalRoomsService.ts";
2
2
import { getAccountIdForRequest } from "../../services/loginService.ts";
3
import { parseString } from "../../helpers/general.ts";
4
3
import type { RequestHandler } from "express";
5
4
import { Types } from "mongoose";
6
5
7
6
export const setActiveShipController: RequestHandler = async (req, res) => {
8
7
const accountId = await getAccountIdForRequest(req);
9
const shipId = parseString(req.query.shipId);
10
11
8
const personalRooms = await getPersonalRooms(accountId);
12
personalRooms.activeShipId = new Types.ObjectId(shipId);
9
personalRooms.activeShipId = new Types.ObjectId(req.query.shipId as string);
13
10
await personalRooms.save();
14
11
res.status(200).end();
15
12
};
@@ -1,6 +1,6 @@
1
1
import type { RequestHandler } from "express";
2
2
import { Account } from "../../models/loginModel.ts";
3
import { getGoogleAccountData } from "../../helpers/customHelpers/customHelpers.ts";
3
import { getGoogleAccountData } from "../../services/loginService.ts";
4
4
5
5
export const signupAndroidController: RequestHandler = async (request, res) => {
6
6
const googleTokenId = request.query.googleTokenId as string | undefined;
@@ -1,16 +0,0 @@
1
import { toCreateAccount, toDatabaseAccount } from "../../helpers/customHelpers/customHelpers.ts";
2
import { createAccount, isNameTaken } from "../../services/loginService.ts";
3
import type { RequestHandler } from "express";
4
5
const createAccountController: RequestHandler = async (req, res) => {
6
const createAccountData = toCreateAccount(req.body);
7
if (await isNameTaken(createAccountData.DisplayName)) {
8
res.status(409).json("Name already in use");
9
} else {
10
const databaseAccount = toDatabaseAccount(createAccountData);
11
const account = await createAccount(databaseAccount);
12
res.json(account);
13
}
14
};
15
16
export { createAccountController };
@@ -1,74 +0,0 @@
1
import type { IAccountCreation, IAndroidAccount } from "../../types/customTypes.ts";
2
import type { IDatabaseAccountRequiredFields } from "../../types/loginTypes.ts";
3
import crypto from "crypto";
4
import { isString, parseEmail, parseString } from "../general.ts";
5
import { OAuth2Client } from "google-auth-library";
6
7
const getWhirlpoolHash = (rawPassword: string): string => {
8
const whirlpool = crypto.createHash("whirlpool");
9
const data = whirlpool.update(rawPassword, "utf8");
10
const hash = data.digest("hex");
11
return hash;
12
};
13
14
const getGoogleAccountData = async (googleTokenId: string | undefined): Promise<IAndroidAccount> => {
15
if (!googleTokenId) {
16
throw new Error("google token is missing");
17
}
18
const client = new OAuth2Client();
19
const ticket = await client.verifyIdToken({
20
idToken: googleTokenId
21
});
22
23
const payload = ticket.getPayload();
24
if (!payload) {
25
throw new Error("payload missing, perhaps invalid google token");
26
}
27
28
return { userId: payload["sub"], email: payload["email"] };
29
};
30
31
const parsePassword = (passwordCandidate: unknown): string => {
32
// a different function could be called that checks whether the password has a certain shape
33
if (!isString(passwordCandidate)) {
34
throw new Error("incorrect password format");
35
}
36
return passwordCandidate;
37
};
38
39
const toAccountCreation = (accountCreation: unknown): IAccountCreation => {
40
if (!accountCreation || typeof accountCreation !== "object") {
41
throw new Error("incorrect or missing account creation data");
42
}
43
44
if (
45
"email" in accountCreation &&
46
"password" in accountCreation &&
47
"DisplayName" in accountCreation &&
48
"CountryCode" in accountCreation
49
) {
50
const rawPassword = parsePassword(accountCreation.password);
51
return {
52
email: parseEmail(accountCreation.email),
53
password: getWhirlpoolHash(rawPassword),
54
CountryCode: parseString(accountCreation.CountryCode),
55
DisplayName: parseString(accountCreation.DisplayName)
56
};
57
}
58
throw new Error("incorrect account creation data: incorrect properties");
59
};
60
61
const toDatabaseAccount = (createAccount: IAccountCreation): IDatabaseAccountRequiredFields => {
62
return {
63
...createAccount,
64
ClientType: "",
65
ConsentNeeded: false,
66
CrossPlatformAllowed: true,
67
ForceLogoutVersion: 0,
68
TrackedSettings: [],
69
Nonce: 0,
70
LastLogin: new Date()
71
} satisfies IDatabaseAccountRequiredFields;
72
};
73
74
export { toDatabaseAccount, toAccountCreation as toCreateAccount, getGoogleAccountData };
@@ -2,74 +2,9 @@ export const isEmptyObject = (obj: unknown): boolean => {
2
2
return Boolean(obj && Object.keys(obj).length === 0 && obj.constructor === Object);
3
3
};
4
4
5
/*
6
alternative to isEmptyObject
7
export const isEmptyObject = (obj: object): boolean => {
5
export const isObjectEmpty = (obj: object): boolean => {
8
6
return Object.keys(obj).length === 0;
9
7
};
10
*/
11
12
export const isString = (text: unknown): text is string => {
13
return typeof text === "string" || text instanceof String;
14
};
15
16
export const parseString = (data: unknown): string => {
17
if (!isString(data)) {
18
throw new Error("data is not a string");
19
}
20
21
return data;
22
};
23
24
export const isNumber = (number: unknown): number is number => {
25
return typeof number === "number" && !isNaN(number);
26
};
27
28
export const parseNumber = (data: unknown): number => {
29
if (!isNumber(data)) {
30
throw new Error("data is not a number");
31
}
32
33
return Number(data);
34
};
35
36
export const isDate = (date: string): boolean => {
37
return Date.parse(date) != 0;
38
};
39
40
export const parseDateNumber = (date: unknown): string => {
41
if (!isString(date) || !isDate(date)) {
42
throw new Error("date could not be parsed");
43
}
44
45
return date;
46
};
47
48
export const parseEmail = (email: unknown): string => {
49
if (!isString(email)) {
50
throw new Error("incorrect email");
51
}
52
return email;
53
};
54
55
export const isBoolean = (booleanCandidate: unknown): booleanCandidate is boolean => {
56
return typeof booleanCandidate === "boolean";
57
};
58
59
export const parseBoolean = (booleanCandidate: unknown): boolean => {
60
if (!isBoolean(booleanCandidate)) {
61
throw new Error("argument was not a boolean");
62
}
63
return booleanCandidate;
64
};
65
66
export const isObject = (objectCandidate: unknown): objectCandidate is Record<string, unknown> => {
67
return (
68
(typeof objectCandidate === "object" || objectCandidate instanceof Object) &&
69
objectCandidate !== null &&
70
!Array.isArray(objectCandidate)
71
);
72
};
73
8
74
9
export const lerp = (v0: number, v1: number, t: number): number => {
75
10
return v0 + t * (v1 - v0);
@@ -33,7 +33,6 @@ import { retroactivelyApplyGuildCheatController } from "../controllers/custom/re
33
33
import { getRegisteredLosersController } from "../controllers/custom/getRegisteredLosersController.ts";
34
34
35
35
import { abilityOverrideController } from "../controllers/custom/abilityOverrideController.ts";
36
import { createAccountController } from "../controllers/custom/createAccountController.ts";
37
36
import { createMessageController } from "../controllers/custom/createMessageController.ts";
38
37
import { addCurrencyController } from "../controllers/custom/addCurrencyController.ts";
39
38
import { addItemsController } from "../controllers/custom/addItemsController.ts";
@@ -92,7 +91,6 @@ customRouter.get("/retroactivelyApplyGuildCheat", retroactivelyApplyGuildCheatCo
92
91
customRouter.get("/getRegisteredLosers", getRegisteredLosersController);
93
92
94
93
customRouter.post("/abilityOverride", abilityOverrideController);
95
customRouter.post("/createAccount", createAccountController);
96
94
customRouter.post("/createMessage", createMessageController);
97
95
customRouter.post("/addCurrency", addCurrencyController);
98
96
customRouter.post("/addItems", addItemsController);
@@ -1,6 +1,11 @@
1
1
import { Account } from "../models/loginModel.ts";
2
2
import { createInventory } from "./inventoryService.ts";
3
import { Platform, type IDatabaseAccountJson, type IDatabaseAccountRequiredFields } from "../types/loginTypes.ts";
3
import {
4
Platform,
5
type IAndroidAccount,
6
type IDatabaseAccountJson,
7
type IAccountCreationData
8
} from "../types/loginTypes.ts";
4
9
import { createShip } from "./shipService.ts";
5
10
import type { Document, Types } from "mongoose";
6
11
import { Loadout, type TLoadoutDatabaseDocument } from "../models/inventoryModels/loadoutModel.ts";
@@ -13,6 +18,7 @@ import crypto from "node:crypto";
13
18
import { logger } from "../utils/logger.ts";
14
19
import { version_compare } from "../helpers/inventoryHelpers.ts";
15
20
import gameToBuildVersion from "../constants/gameToBuildVersion.ts";
21
import { OAuth2Client } from "google-auth-library";
16
22
17
23
export const isCorrectPassword = (requestPassword: string, databasePassword: string): boolean => {
18
24
return requestPassword === databasePassword;
@@ -39,7 +45,7 @@ export const getUsernameFromEmail = async (email: string): Promise<string> => {
39
45
return name;
40
46
};
41
47
42
export const createAccount = async (accountData: IDatabaseAccountRequiredFields): Promise<IDatabaseAccountJson> => {
48
export const createAccount = async (accountData: IAccountCreationData): Promise<IDatabaseAccountJson> => {
43
49
if (accountData.DisplayName == "all") {
44
50
throw new Error(`"${accountData.DisplayName}" is reserved and may not be used as a username`);
45
51
}
@@ -170,6 +176,23 @@ export const hasPermission = (account: Pick<TAccountDocument, "DisplayName">, pe
170
176
return true;
171
177
};
172
178
179
export const getGoogleAccountData = async (googleTokenId: string | undefined): Promise<IAndroidAccount> => {
180
if (!googleTokenId) {
181
throw new Error("google token is missing");
182
}
183
const client = new OAuth2Client();
184
const ticket = await client.verifyIdToken({
185
idToken: googleTokenId
186
});
187
188
const payload = ticket.getPayload();
189
if (!payload) {
190
throw new Error("payload missing, perhaps invalid google token");
191
}
192
193
return { userId: payload["sub"], email: payload["email"] };
194
};
195
173
196
export const getOriginalPlatform = (account: TAccountDocument): number => {
174
197
return account.GoogleTokenId ? Platform.Android : Platform.Windows;
175
198
};
@@ -1,5 +1,5 @@
1
1
import type { IKeyChainRequest } from "../types/requestTypes.ts";
2
import { isEmptyObject } from "../helpers/general.ts";
2
import { isObjectEmpty } from "../helpers/general.ts";
3
3
import type { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel.ts";
4
4
import { createMessage } from "./inboxService.ts";
5
5
import {
@@ -371,7 +371,7 @@ export const giveKeyChainItem = async (
371
371
if (!questKey.Progress?.[keyChainInfo.ChainStage]?.i) {
372
372
inventoryChanges = await addKeyChainItems(inventory, keyChainInfo, buildLabel);
373
373
374
if (isEmptyObject(inventoryChanges)) {
374
if (isObjectEmpty(inventoryChanges)) {
375
375
logger.warn("inventory changes was empty after getting keychain items: should not happen");
376
376
}
377
377
// items were added: update quest stage's i (item was given)
@@ -11,7 +11,7 @@ import { Loadout } from "../models/inventoryModels/loadoutModel.ts";
11
11
import { addMods, getInventory } from "./inventoryService.ts";
12
12
import type { IOidWithLegacySupport } from "../types/commonTypes.ts";
13
13
import { Types } from "mongoose";
14
import { isEmptyObject } from "../helpers/general.ts";
14
import { isEmptyObject, isObjectEmpty } from "../helpers/general.ts";
15
15
import { convertLegacyColorsToIColor, fromOid, toObjectId, version_compare } from "../helpers/inventoryHelpers.ts";
16
16
import { logger } from "../utils/logger.ts";
17
17
import type { ISketch, TEquipmentKey } from "../types/inventoryTypes/inventoryTypes.ts";
@@ -99,7 +99,7 @@ export const handleInventoryItemConfigChange = async (
99
99
const newLoadout = _loadout as ILoadoutEntry;
100
100
101
101
// empty loadout slot like: "NORMAL": {}
102
if (isEmptyObject(newLoadout)) {
102
if (isObjectEmpty(newLoadout)) {
103
103
continue;
104
104
}
105
105
@@ -1,11 +0,0 @@
1
export interface IAccountCreation {
2
email: string;
3
password: string;
4
DisplayName: string;
5
CountryCode: string;
6
}
7
8
export interface IAndroidAccount {
9
email?: string;
10
userId: string;
11
}
@@ -21,7 +21,7 @@ export interface IAccountAndLoginResponseCommons {
21
21
Nonce: number;
22
22
}
23
23
24
export interface IDatabaseAccountRequiredFields extends IAccountAndLoginResponseCommons {
24
export interface IAccountCreationData extends IAccountAndLoginResponseCommons {
25
25
email: string;
26
26
password: string;
27
27
Language?: string;
@@ -29,7 +29,7 @@ export interface IDatabaseAccountRequiredFields extends IAccountAndLoginResponse
29
29
LastLogin: Date;
30
30
}
31
31
32
export interface IDatabaseAccount extends IDatabaseAccountRequiredFields {
32
export interface IDatabaseAccount extends IAccountCreationData {
33
33
LastPlatform?: Platform;
34
34
Dropped?: true;
35
35
LatestEventMessageDate: Date;
@@ -90,3 +90,8 @@ export interface IIgnore {
90
90
ignorer: Types.ObjectId;
91
91
ignoree: Types.ObjectId;
92
92
}
93
94
export interface IAndroidAccount {
95
email?: string;
96
userId: string;
97
}