Skip to content

Commit

Permalink
intial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Bot-Rakshit committed Jun 22, 2024
1 parent 1e15e8b commit 1092f63
Show file tree
Hide file tree
Showing 192 changed files with 4,087 additions and 29,688 deletions.
18,128 changes: 3,551 additions & 14,577 deletions package-lock.json

Large diffs are not rendered by default.

130 changes: 38 additions & 92 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,100 +1,46 @@
{
"name": "express-typescript-starter",
"version": "0.1.0",
"description": "A starting point for Node.js express apps with TypeScript",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/TypeScript-Node-Starter"
},
"author": "Bowden Kelly",
"license": "MIT",
"name": "chess-community-backend",
"version": "1.0.0",
"main": "dist/server.js",
"scripts": {
"build-sass": "sass src/public/css/main.scss dist/public/css/main.css",
"build-ts": "tsc",
"build": "npm run build-sass && npm run build-ts && npm run lint && npm run copy-static-assets",
"copy-static-assets": "ts-node copyStaticAssets.ts",
"debug": "npm run build && npm run watch-debug",
"lint": "tsc --noEmit && eslint \"**/*.{js,ts}\" --quiet --fix",
"serve-debug": "nodemon --inspect dist/server.js",
"serve": "node dist/server.js",
"start": "npm run serve",
"test": "jest --forceExit --coverage --verbose",
"watch-debug": "concurrently -k -p \"[{name}]\" -n \"Sass,TypeScript,Node\" -c \"yellow.bold,cyan.bold,green.bold\" \"npm run watch-sass\" \"npm run watch-ts\" \"npm run serve-debug\"",
"watch-node": "nodemon dist/server.js",
"watch-sass": "sass --watch src/public/css/main.scss dist/public/css/main.css",
"watch-test": "npm run test -- --watchAll",
"watch-ts": "tsc -w",
"watch": "concurrently -k -p \"[{name}]\" -n \"Sass,TypeScript,Node\" -c \"yellow.bold,cyan.bold,green.bold\" \"npm run watch-sass\" \"npm run watch-ts\" \"npm run watch-node\""
"start": "node dist/server.js",
"dev": "ts-node-dev --respawn --transpile-only src/server.ts",
"build": "tsc",
"prisma:generate": "prisma generate",
"prisma:migrate": "prisma migrate deploy"
},
"dependencies": {
"async": "3.2.2",
"bcrypt-nodejs": "0.0.3",
"bluebird": "3.7.2",
"body-parser": "1.19.0",
"compression": "1.7.4",
"connect-mongo": "4.4.0",
"dotenv": "8.2.0",
"errorhandler": "1.5.1",
"express": "4.17.1",
"express-flash": "0.0.2",
"express-session": "1.17.1",
"express-validator": "6.9.2",
"fbgraph": "1.4.4",
"lodash": "^4.17.21",
"lusca": "1.6.1",
"mongoose": "5.11.15",
"nodemailer": "6.6.1",
"passport": "0.4.1",
"passport-facebook": "3.0.0",
"passport-local": "1.0.0",
"pug": "3.0.2",
"winston": "3.3.3"
"@prisma/client": "^3.15.2",
"axios": "^0.27.2",
"compression": "^1.7.4",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.1",
"express-session": "^1.18.0",
"googleapis": "^140.0.0",
"helmet": "^5.1.1",
"joi": "^17.13.3",
"jsonwebtoken": "^8.5.1",
"node-cron": "^3.0.3",
"passport": "^0.6.0",
"passport-google-oauth20": "^2.0.0",
"passport-jwt": "^4.0.1",
"redis": "^4.6.14",
"winston": "^3.8.1"
},
"devDependencies": {
"@types/async": "3.2.5",
"@types/bcrypt-nodejs": "0.0.31",
"@types/bluebird": "3.5.33",
"@types/body-parser": "1.19.0",
"@types/bson": "4.0.5",
"@types/chai": "4.2.14",
"@types/compression": "1.7.0",
"@types/concurrently": "5.2.1",
"@types/errorhandler": "1.5.0",
"@types/eslint": "7.2.6",
"@types/express": "4.17.11",
"@types/express-flash": "0.0.2",
"@types/express-session": "1.17.3",
"@types/jest": "^26.0.23",
"@types/jquery": "3.5.5",
"@types/lodash": "^4.14.170",
"@types/lusca": "1.6.2",
"@types/mongodb": "3.6.5",
"@types/node": "^14.18",
"@types/nodemailer": "6.4.0",
"@types/passport": "1.0.5",
"@types/passport-facebook": "2.1.10",
"@types/passport-local": "1.0.33",
"@types/pug": "2.0.4",
"@types/request": "2.48.5",
"@types/request-promise": "4.1.47",
"@types/shelljs": "0.8.8",
"@types/supertest": "2.0.10",
"@types/winston": "2.4.4",
"@typescript-eslint/eslint-plugin": "4.14.2",
"@typescript-eslint/parser": "4.14.2",
"chai": "4.3.0",
"concurrently": "6.0.2",
"eslint": "7.19.0",
"jest": "^27.0.6",
"nodemon": "^2.0.7",
"sass": "1.32.6",
"shelljs": "0.8.5",
"supertest": "6.1.3",
"ts-jest": "^27.0.3",
"ts-node": "9.1.1",
"typescript": "4.1.3"
},
"engines": {
"node": ">=14.0.0"
"@types/compression": "^1.7.2",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-session": "^1.18.0",
"@types/jsonwebtoken": "^8.5.8",
"@types/node": "^18.0.0",
"@types/node-cron": "^3.0.11",
"@types/passport": "^1.0.9",
"@types/passport-google-oauth20": "^2.0.11",
"@types/passport-jwt": "^4.0.1",
"prisma": "^3.15.2",
"ts-node-dev": "^2.0.0",
"typescript": "^4.7.4"
}
}
22 changes: 22 additions & 0 deletions prisma/migrations/20240621221158_changeschema/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"googleId" TEXT NOT NULL,
"email" TEXT NOT NULL,
"name" TEXT NOT NULL,
"chessUsername" TEXT,
"youtubeChannelId" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "User_googleId_key" ON "User"("googleId");

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");

-- CreateIndex
CREATE UNIQUE INDEX "User_chessUsername_key" ON "User"("chessUsername");
17 changes: 17 additions & 0 deletions prisma/migrations/20240622000112_init/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- CreateTable
CREATE TABLE "ChessInfo" (
"id" TEXT NOT NULL,
"blitz" INTEGER NOT NULL,
"bullet" INTEGER NOT NULL,
"rapid" INTEGER NOT NULL,
"puzzle" INTEGER NOT NULL,
"userId" TEXT NOT NULL,

CONSTRAINT "ChessInfo_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "ChessInfo_userId_key" ON "ChessInfo"("userId");

-- AddForeignKey
ALTER TABLE "ChessInfo" ADD CONSTRAINT "ChessInfo_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
3 changes: 3 additions & 0 deletions prisma/migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"
31 changes: 31 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "darwin-arm64"]
}

model User {
id String @id @default(uuid())
googleId String @unique
email String @unique
name String
chessUsername String? @unique
youtubeChannelId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
chessInfo ChessInfo?
}

model ChessInfo {
id String @id @default(uuid())
blitz Int
bullet Int
rapid Int
puzzle Int
userId String @unique
user User @relation(fields: [userId], references: [id])
}
131 changes: 24 additions & 107 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,118 +1,35 @@
import express from "express";
import compression from "compression"; // compresses requests
import session from "express-session";
import bodyParser from "body-parser";
import lusca from "lusca";
import MongoStore from "connect-mongo";
import flash from "express-flash";
import path from "path";
import mongoose from "mongoose";
import passport from "passport";
import bluebird from "bluebird";
import { MONGODB_URI, SESSION_SECRET } from "./util/secrets";
import express from 'express';
import passport from 'passport';
import cors from 'cors';
import helmet from 'helmet';
import compression from 'compression';
import session from 'express-session';
import { errorHandler } from './middlewares/errorHandler';
import authRoutes from './routes/auth';
import './config/passport';
import './utils/scheduler';

// Controllers (route handlers)
import * as homeController from "./controllers/home";
import * as userController from "./controllers/user";
import * as apiController from "./controllers/api";
import * as contactController from "./controllers/contact";

// API keys and Passport configuration
import * as passportConfig from "./config/passport";

// Create Express server
const app = express();

// Connect to MongoDB
const mongoUrl = MONGODB_URI;
mongoose.Promise = bluebird;

mongoose.connect(mongoUrl, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true } ).then(
() => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ },
).catch(err => {
console.log(`MongoDB connection error. Please make sure MongoDB is running. ${err}`);
// process.exit();
});

// Express configuration
app.set("port", process.env.PORT || 3000);
app.set("views", path.join(__dirname, "../views"));
app.set("view engine", "pug");
app.use(cors());
app.use(helmet());
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Configure express-session
app.use(session({
resave: true,
saveUninitialized: true,
secret: SESSION_SECRET,
store: new MongoStore({
mongoUrl,
mongoOptions: {
autoReconnect: true
}
})
secret: process.env.SESSION_SECRET || 'your_secret_key', // Use a strong secret key
resave: false,
saveUninitialized: false,
cookie: { secure: process.env.NODE_ENV === 'production' } // Use secure cookies in production
}));

app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(lusca.xframe("SAMEORIGIN"));
app.use(lusca.xssProtection(true));
app.use((req, res, next) => {
res.locals.user = req.user;
next();
});
app.use((req, res, next) => {
// After successful login, redirect back to the intended page
if (!req.user &&
req.path !== "/login" &&
req.path !== "/signup" &&
!req.path.match(/^\/auth/) &&
!req.path.match(/\./)) {
req.session.returnTo = req.path;
} else if (req.user &&
req.path == "/account") {
req.session.returnTo = req.path;
}
next();
});

app.use(
express.static(path.join(__dirname, "public"), { maxAge: 31557600000 })
);

/**
* Primary app routes.
*/
app.get("/", homeController.index);
app.get("/login", userController.getLogin);
app.post("/login", userController.postLogin);
app.get("/logout", userController.logout);
app.get("/forgot", userController.getForgot);
app.post("/forgot", userController.postForgot);
app.get("/reset/:token", userController.getReset);
app.post("/reset/:token", userController.postReset);
app.get("/signup", userController.getSignup);
app.post("/signup", userController.postSignup);
app.get("/contact", contactController.getContact);
app.post("/contact", contactController.postContact);
app.get("/account", passportConfig.isAuthenticated, userController.getAccount);
app.post("/account/profile", passportConfig.isAuthenticated, userController.postUpdateProfile);
app.post("/account/password", passportConfig.isAuthenticated, userController.postUpdatePassword);
app.post("/account/delete", passportConfig.isAuthenticated, userController.postDeleteAccount);
app.get("/account/unlink/:provider", passportConfig.isAuthenticated, userController.getOauthUnlink);

/**
* API examples routes.
*/
app.get("/api", apiController.getApi);
app.get("/api/facebook", passportConfig.isAuthenticated, passportConfig.isAuthorized, apiController.getFacebook);
app.use('/api/auth', authRoutes);

/**
* OAuth authentication routes. (Sign in)
*/
app.get("/auth/facebook", passport.authenticate("facebook", { scope: ["email", "public_profile"] }));
app.get("/auth/facebook/callback", passport.authenticate("facebook", { failureRedirect: "/login" }), (req, res) => {
res.redirect(req.session.returnTo || "/");
});
app.use(errorHandler);

export default app;
export default app;
17 changes: 17 additions & 0 deletions src/config/chesscom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import axios from 'axios';

export const chessComConfig = {
baseURL: 'https://api.chess.com/pub/player',
headers: {
'User-Agent': 'chessconnect ([email protected])',
},
};

export const isValidChessComId = async (chesscomId: string): Promise<boolean> => {
try {
const response = await axios.get(`${chessComConfig.baseURL}/${chesscomId}`, { headers: chessComConfig.headers });
return response.status === 200;
} catch (error) {
return false;
}
};
Loading

0 comments on commit 1092f63

Please sign in to comment.