Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8,157 changes: 4,404 additions & 3,753 deletions package-lock.json

Large diffs are not rendered by default.

67 changes: 35 additions & 32 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,54 +27,54 @@
},
"homepage": "https://github.com/hack-the-6ix/hackthe6ix-backend#readme",
"dependencies": {
"@google-cloud/opentelemetry-cloud-trace-exporter": "^2.0.0",
"@opentelemetry/api": "^1.4.1",
"@opentelemetry/instrumentation": "^0.36.0",
"@opentelemetry/instrumentation-express": "^0.32.1",
"@opentelemetry/instrumentation-http": "^0.36.0",
"@opentelemetry/instrumentation-mongodb": "^0.34.1",
"@opentelemetry/resources": "^1.1.1",
"@opentelemetry/sdk-trace-base": "^1.1.1",
"@opentelemetry/sdk-trace-node": "^1.10.0",
"@opentelemetry/semantic-conventions": "^1.1.1",
"archiver": "^5.3.1",
"axios": "^0.21.4",
"@google-cloud/opentelemetry-cloud-trace-exporter": "^2.3.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/instrumentation": "^0.52.1",
"@opentelemetry/instrumentation-express": "^0.41.0",
"@opentelemetry/instrumentation-http": "^0.52.1",
"@opentelemetry/instrumentation-mongodb": "^0.46.0",
"@opentelemetry/resources": "^1.25.1",
"@opentelemetry/sdk-trace-base": "^1.25.1",
"@opentelemetry/sdk-trace-node": "^1.25.1",
"@opentelemetry/semantic-conventions": "^1.25.1",
"archiver": "^7.0.1",
"axios": "^1.7.2",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"deepcopy": "^2.1.0",
"dotenv": "^8.6.0",
"express": "^4.18.2",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-async-errors": "^3.1.1",
"express-fileupload": "^1.4.0",
"express-fileupload": "^1.5.1",
"express-mongo-sanitize": "^2.2.0",
"file-type": "^16.5.4",
"jsonwebtoken": "^9.0.0",
"jsonwebtoken": "^9.0.2",
"jsqr": "^1.4.0",
"lodash.clonedeep": "^4.5.0",
"mongoose": "^6.10.3",
"mongoose-autopopulate": "^1.0.0",
"node-cache": "^5.1.2",
"node-jose": "^2.2.0",
"qrcode": "^1.5.1",
"short-uuid": "^4.2.2",
"simple-oauth2": "^5.0.0",
"qrcode": "^1.5.3",
"short-uuid": "^5.2.0",
"simple-oauth2": "^5.1.0",
"typescript": "^4.9.5",
"winston": "^3.8.2"
"winston": "^3.13.1"
},
"devDependencies": {
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.21.0",
"@types/archiver": "^5.3.2",
"@types/cors": "^2.8.13",
"@types/express": "^4.17.17",
"@types/express-fileupload": "^1.4.1",
"@types/jsonwebtoken": "^9.0.1",
"@types/lodash.clonedeep": "^4.5.7",
"@types/archiver": "^6.0.2",
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/express-fileupload": "^1.5.0",
"@types/jsonwebtoken": "^9.0.6",
"@types/lodash.clonedeep": "^4.5.9",
"@types/node": "^16.18.16",
"@types/node-jose": "^1.1.10",
"@types/qrcode": "^1.5.0",
"@types/simple-oauth2": "^4.1.2",
"@types/unzipper": "^0.10.6",
"@types/node-jose": "^1.1.13",
"@types/qrcode": "^1.5.5",
"@types/simple-oauth2": "^5.0.7",
"@types/unzipper": "^0.10.9",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"eslint": "^7.32.0",
Expand All @@ -83,9 +83,12 @@
"jest-mock-random": "^1.1.1",
"mockdate": "^3.0.5",
"mongodb-memory-server": "^8.12.1",
"nodemon": "^2.0.22",
"nodemon": "^3.1.4",
"prettier": "^2.8.4",
"ts-node": "^10.9.2",
"unzipper": "^0.10.14"
"unzipper": "^0.12.2"
},
"volta": {
"node": "16.20.2"
}
}
4 changes: 2 additions & 2 deletions src/controller/AuthController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export const handleCallback = async (providerName: string, code: string, stateTe
redirect_uri: state.callbackURL,
});

const userData = await _getUserData(provider.userinfo_url, accesstoken.token.access_token);
const userData = await _getUserData(provider.userinfo_url, accesstoken.token.access_token as string);

const localToken = await _issueLocalToken(userData);

Expand All @@ -125,7 +125,7 @@ export const handleCallback = async (providerName: string, code: string, stateTe

return {
token: localToken,
refreshToken: accesstoken.token.refresh_token,
refreshToken: accesstoken.token.refresh_token as string,
redirectTo: redirectTo,
};
} catch (err: any) {
Expand Down
2 changes: 1 addition & 1 deletion src/controller/GridFSController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import mongoose, {Mongoose} from 'mongoose';
import type GridFSFile from "mongoose/node_modules/mongodb";
import type GridFSFile from "mongodb";
import { pipeline } from 'node:stream/promises';
import stream, { Writable, PassThrough } from 'stream';
import { BadRequestError, NotFoundError } from '../types/errors';
Expand Down
101 changes: 101 additions & 0 deletions src/controller/OTPController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { IUser } from '../models/user/fields';
import OTP from '../models/otp/OTP';
import ExternalUser from '../models/externaluser/ExternalUser';
import { BadRequestError, NotFoundError } from '../types/errors';

export async function generateOTP(requestUser: IUser, email: string) {
const externalUser = await ExternalUser.findOne({ email });
if (!externalUser) {
throw new BadRequestError('Email not found in external users');
}

const code = Math.floor(100000 + Math.random() * 900000).toString();
const expiration = Date.now() + 10 * 60 * 1000;

const otp = new OTP({
code,
email,
expiration,
used: false,
issuedBy: requestUser.email,
});

await otp.save();

return {
success: true,
message: 'OTP generated successfully',
code,
expiration: new Date(expiration),
};
}

export async function verifyOTP(
requestUser: IUser,
code: string,
email: string,
) {
const externalUser = await ExternalUser.findOne({ email });
if (!externalUser) {
throw new BadRequestError('Email not found in external users');
}

const otp = await OTP.findOne({ code, email });
if (!otp) {
throw new NotFoundError('Invalid OTP code');
}

if (otp.used) {
throw new BadRequestError('OTP code already used');
}

if (Date.now() > otp.expiration) {
throw new BadRequestError('OTP code expired');
}

otp.used = true;
otp.usedBy = externalUser._id.toString();
otp.usedAt = new Date();
otp.usedName = externalUser.firstName + ' ' + externalUser.lastName;
await otp.save();

return {
success: true,
message: 'OTP verified successfully',
user: externalUser,
};
}

export async function getAllOTPs(requestUser: IUser) {
const otps = await OTP.find({}).sort({ createdAt: -1 });

return {
success: true,
otps: otps.map((otp) => ({
id: otp._id,
code: otp.code,
email: otp.email,
used: otp.used,
expiration: new Date(otp.expiration),
createdAt: otp.createdAt,
usedBy: otp.usedBy,
usedAt: otp.usedAt,
issuedBy: otp.issuedBy,
usedName: otp.usedName,
})),
};
}

export async function removeOTP(requestUser: IUser, otpId: string) {
const otp = await OTP.findById(otpId);
if (!otp) {
throw new NotFoundError('OTP not found');
}

await OTP.findByIdAndDelete(otpId);

return {
success: true,
message: 'OTP removed successfully',
};
}
3 changes: 2 additions & 1 deletion src/controller/applicationStatus/assignApplicationStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ export default async (legit?: boolean, waitlistOver?: boolean, rawAcceptedFromWa
}
}


await syncMailingLists(undefined, true);

return { dead, accepted, rejected, waitlisted };
};
50 changes: 32 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dotenv/config';
import * as OpenTelemetry from './tracing';

OpenTelemetry.init('ht6-backend')
OpenTelemetry.init('ht6-backend');

import bodyParser from 'body-parser';
import cors from 'cors';
Expand All @@ -24,37 +24,51 @@ const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

const corsFilter = process.env.NODE_ENV === 'production'
const corsFilter =
process.env.NODE_ENV === 'production'
? [/hackthe6ix\.com$/, /localhost:/]
: '*';
app.use(cors({
origin: corsFilter,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
}));
app.use(
cors({
origin: corsFilter,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
}),
);

app.use(fileUpload({
// We add one byte here so that all the excess data get truncated, but we can still trigger the filesize error in our code
limits: { fileSize: 5000001 },
}));
app.use(
fileUpload({
// We add one byte here so that all the excess data get truncated, but we can still trigger the filesize error in our code
limits: { fileSize: 5000001 },
}),
);

app.use('/api', apiRouter);
app.use('/api/action', actionRouter);
app.use('/auth', authRouter);
app.use('/health', healthRouter);

app.use(function(err: any, req: express.Request, res: express.Response, next: express.NextFunction) {
logResponse(req, res, (
async () => {
throw new InternalServerError('An error occurred', err.stack);
}
)());
app.use(function (
err: any,
req: express.Request,
res: express.Response,
next: express.NextFunction,
) {
logResponse(
req,
res,
(async () => {
throw new InternalServerError('An error occurred', err.stack);
})(),
);
} as ErrorRequestHandler);

log.info(`Node Environment: ${process.env.NODE_ENV}`);
log.info("Waiting for MongoDB...")
log.info('Waiting for MongoDB...');

app.listen(port, () => {
log.info(`Server running on port ${port}`);
});

console.log(`Node Environment: ${process.env.NODE_ENV}`);
console.log(`Node Environment: ${process.env.NODE_ENV}`);

export default app;
14 changes: 14 additions & 0 deletions src/models/otp/OTP.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import mongoose from 'mongoose';
import { extractFields } from '../util';
import { fields, IOTP } from './fields';

const schema = new mongoose.Schema(extractFields(fields), {
toObject: {
virtuals: true,
},
toJSON: {
virtuals: true,
},
});

export default mongoose.model<IOTP>('OTP', schema);
Loading
Loading