mirror of
https://github.com/PretendoNetwork/account.git
synced 2026-05-15 00:09:54 -05:00
Merge f44c276834 into e2e458bcdb
This commit is contained in:
commit
74e1cc5726
|
|
@ -106,7 +106,8 @@ export const config: Config = {
|
|||
forum_url: process.env.PN_ACT_CONFIG_DISCOURSE_FORUM_URL || '',
|
||||
api_key: process.env.PN_ACT_CONFIG_DISCOURSE_API_KEY || '',
|
||||
api_username: process.env.PN_ACT_CONFIG_DISCOURSE_API_USERNAME || ''
|
||||
}
|
||||
},
|
||||
uidhmac_key: process.env.PN_ACT_CONFIG_UIDHMAC_KEY || ''
|
||||
};
|
||||
|
||||
if (process.env.PN_ACT_CONFIG_STRIPE_SECRET_KEY) {
|
||||
|
|
@ -272,6 +273,11 @@ if (!config.grpc.port) {
|
|||
configValid = false;
|
||||
}
|
||||
|
||||
if (!config.uidhmac_key) {
|
||||
LOG_ERROR('Failed to find NASC uidhmac key. Set the PN_ACT_CONFIG_UIDHMAC_KEY environment variable');
|
||||
configValid = false;
|
||||
}
|
||||
|
||||
if (!config.stripe?.secret_key) {
|
||||
LOG_WARN('Failed to find Stripe api key! If a PNID is deleted with an active subscription, the subscription will *NOT* be canceled! Set the PN_ACT_CONFIG_STRIPE_SECRET_KEY environment variable to enable');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon
|
|||
const fcdcertHash = crypto.createHash('sha256').update(fcdcert).digest('base64');
|
||||
|
||||
let pid = 0; // * Real PIDs are always positive and non-zero
|
||||
let pidHmac = '';
|
||||
let uidhmac = '';
|
||||
let password = '';
|
||||
|
||||
if (requestParams.userid) {
|
||||
|
|
@ -42,7 +42,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon
|
|||
}
|
||||
|
||||
if (requestParams.uidhmac) {
|
||||
pidHmac = nintendoBase64Decode(requestParams.uidhmac).toString();
|
||||
uidhmac = nintendoBase64Decode(requestParams.uidhmac).toString();
|
||||
}
|
||||
|
||||
if (requestParams.passwd) {
|
||||
|
|
@ -102,6 +102,11 @@ async function NASCMiddleware(request: express.Request, response: express.Respon
|
|||
response.status(200).send(nascError('102').toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uidhmac || nexAccount.uidhmac !== uidhmac) {
|
||||
response.status(200).send(nascError('122').toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let device = await Device.findOne({
|
||||
|
|
@ -160,7 +165,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon
|
|||
}
|
||||
|
||||
if (titleID === '0004013000003202') {
|
||||
if (password && !pid && !pidHmac) {
|
||||
if (password && !pid && !uidhmac) {
|
||||
// * Register new user
|
||||
|
||||
const session = await databaseConnection().startSession();
|
||||
|
|
@ -174,6 +179,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon
|
|||
});
|
||||
|
||||
await nexAccount.generatePID();
|
||||
nexAccount.generateUIDHMAC();
|
||||
|
||||
await nexAccount.save({ session });
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import crypto from 'node:crypto';
|
||||
import { Schema, model } from 'mongoose';
|
||||
import uniqueValidator from 'mongoose-unique-validator';
|
||||
import { config } from '@/config-manager';
|
||||
import type { INEXAccount, INEXAccountMethods, NEXAccountModel } from '@/types/mongoose/nex-account';
|
||||
|
||||
const NEXAccountSchema = new Schema<INEXAccount, NEXAccountModel, INEXAccountMethods>({
|
||||
|
|
@ -25,7 +27,8 @@ const NEXAccountSchema = new Schema<INEXAccount, NEXAccountModel, INEXAccountMet
|
|||
type: String,
|
||||
default: 'prod' // * everyone is in production by default
|
||||
},
|
||||
friend_code: String
|
||||
friend_code: String,
|
||||
uidhmac: String
|
||||
});
|
||||
|
||||
NEXAccountSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' });
|
||||
|
|
@ -74,4 +77,12 @@ NEXAccountSchema.method('generatePassword', function generatePassword(): void {
|
|||
this.password = output.join('');
|
||||
});
|
||||
|
||||
NEXAccountSchema.method('generateUIDHMAC', function generateUIDHMAC(): void {
|
||||
const CHAR_SET = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}';
|
||||
const hmac = crypto.createHmac('sha256', config.uidhmac_key).update(this.pid.toString());
|
||||
const hash = hmac.digest();
|
||||
|
||||
this.uidhmac = Array.from(hash.subarray(0, 8), byte => CHAR_SET[byte % CHAR_SET.length]).join('');
|
||||
});
|
||||
|
||||
export const NEXAccount = model<INEXAccount, NEXAccountModel>('NEXAccount', NEXAccountSchema);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ api.use('/v1/login', V1.LOGIN);
|
|||
api.use('/v1/register', V1.REGISTER);
|
||||
api.use('/v1/reset-password', V1.RESET_PASSWORD);
|
||||
api.use('/v1/user', V1.USER);
|
||||
api.use('/v1/repair-uidhmac', V1.REPAIR_UIDHMAC);
|
||||
|
||||
// * Main router for endpoints
|
||||
const router = express.Router();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import login_v1 from '@/services/api/routes/v1/login';
|
|||
import register_v1 from '@/services/api/routes/v1/register';
|
||||
import resetPassword_v1 from '@/services/api/routes/v1/resetPassword';
|
||||
import user_v1 from '@/services/api/routes/v1/user';
|
||||
import repair_uidhmac_v1 from '@/services/api/routes/v1/repair-uidhmac';
|
||||
|
||||
export const V1 = {
|
||||
CONNECTIONS: connections_v1,
|
||||
|
|
@ -13,5 +14,6 @@ export const V1 = {
|
|||
LOGIN: login_v1,
|
||||
REGISTER: register_v1,
|
||||
RESET_PASSWORD: resetPassword_v1,
|
||||
USER: user_v1
|
||||
USER: user_v1,
|
||||
REPAIR_UIDHMAC: repair_uidhmac_v1
|
||||
};
|
||||
|
|
|
|||
77
src/services/api/routes/v1/repair-uidhmac.ts
Normal file
77
src/services/api/routes/v1/repair-uidhmac.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import express from 'express';
|
||||
import { LOG_ERROR } from '@/logger';
|
||||
import { NEXAccount } from '@/models/nex-account';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
/**
|
||||
* [POST]
|
||||
* Implementation of: https://api.pretendo.cc/v1/repair-uidhmac
|
||||
* Description: Creates a new user PNID
|
||||
*/
|
||||
router.post('/', async (request: express.Request, response: express.Response): Promise<void> => {
|
||||
const pid = request.body.pid?.trim(); // * This has to be forwarded since this request comes from the websites server
|
||||
const nexPassword = request.body.password?.trim();
|
||||
|
||||
if (!pid || pid === '' || !/^\d+$/.test(pid)) {
|
||||
response.status(400).json({
|
||||
app: 'api',
|
||||
status: 400,
|
||||
error: 'Invalid PID format'
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nexPassword || !/^[\x21-\x5B\x5D-\x7D]{16}$/.test(nexPassword)) {
|
||||
response.status(400).json({
|
||||
app: 'api',
|
||||
status: 400,
|
||||
error: 'Invalid NEX password format'
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const nexAccount = await NEXAccount.findOne({
|
||||
pid: parseInt(pid),
|
||||
password: nexPassword
|
||||
});
|
||||
|
||||
if (!nexAccount) {
|
||||
response.json({
|
||||
app: 'api',
|
||||
status: 400,
|
||||
error: 'Invalid NEX account'
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nexAccount.generateUIDHMAC();
|
||||
|
||||
response.json({
|
||||
app: 'api',
|
||||
status: 200,
|
||||
data: {
|
||||
uidhmac: nexAccount.uidhmac
|
||||
}
|
||||
});
|
||||
} catch (error: any) {
|
||||
LOG_ERROR('[POST] /v1/repair-uidhmac: ' + error);
|
||||
if (error.stack) {
|
||||
console.error(error.stack);
|
||||
}
|
||||
|
||||
response.status(500).json({
|
||||
app: 'api',
|
||||
status: 500,
|
||||
error: 'Internal server error'
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -75,4 +75,5 @@ export interface Config {
|
|||
api_key: string;
|
||||
api_username: string;
|
||||
};
|
||||
uidhmac_key: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@ export interface INEXAccount {
|
|||
access_level: ACCESS_LEVEL;
|
||||
server_access_level: string;
|
||||
friend_code: string;
|
||||
uidhmac: string;
|
||||
}
|
||||
|
||||
export interface INEXAccountMethods {
|
||||
generatePID(): Promise<void>;
|
||||
generatePassword(): void;
|
||||
generateUIDHMAC(): void;
|
||||
}
|
||||
|
||||
interface INEXAccountQueryHelpers {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user