sendou.ink/old/index.js
Kalle (Sendou) 1576f89925 move to old
2020-10-13 14:27:02 +03:00

255 lines
7.0 KiB
JavaScript

const { ApolloServer } = require("apollo-server-express");
const mongoose = require("mongoose");
const express = require("express");
const compression = require("compression");
const bodyParser = require("body-parser");
const session = require("express-session");
const MongoStore = require("connect-mongo")(session);
const cors = require("cors");
const passport = require("passport");
const { Model, knexSnakeCaseMappers } = require("objection");
const Knex = require("knex");
import knexConfiguration from "./knexfile";
const DiscordStrategy = require("passport-discord").Strategy;
const User = require("./mongoose-models/user");
const ObjectionUser = require("./models/User").default;
const XRankPlacement = require("./models/XRankPlacement").default;
const path = require("path");
const schema = require("./schema");
const mockUser = require("./utils/mocks");
const depthLimit = require("graphql-depth-limit");
const DataLoader = require("dataloader");
const knex = Knex({
...knexConfiguration,
...knexSnakeCaseMappers(),
});
Model.knex(knex);
mongoose.set("useFindAndModify", false);
mongoose.set("useCreateIndex", true);
const callbackURL =
process.env.NODE_ENV === "development"
? "http://localhost:3001/auth/discord/callback"
: "https://sendou.ink/auth/discord/callback";
passport.use(
new DiscordStrategy(
{
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL,
scope: ["identify", "connections"],
},
function (_accessToken, _refreshToken, profile, cb) {
const userToSave = {
username: profile.username,
discriminator: profile.discriminator,
discord_id: profile.id,
avatar: profile.avatar,
};
for (var i = 0; i < profile.connections.length; i++) {
const connection = profile.connections[i];
if (connection.visibility === 1 && connection.verified) {
if (connection.type === "twitch") {
userToSave.twitch_name = connection.name.toLowerCase();
} else if (connection.type === "twitter") {
userToSave.twitter_name = connection.name.toLowerCase();
} else if (connection.type === "youtube") {
userToSave.youtube_name = connection.name;
userToSave.youtube_id = connection.id;
}
}
}
Promise.all([
knex.raw(
`? ON CONFLICT (discord_id)
DO UPDATE SET
username = EXCLUDED.username,
discriminator = EXCLUDED.discriminator,
discord_avatar = EXCLUDED.discord_avatar`,
[
knex("users").insert({
username: profile.username,
discriminator: profile.discriminator,
discordId: profile.id,
discordAvatar: profile.avatar,
}),
]
),
User.updateOne({ discord_id: userToSave.discord_id }, userToSave, {
upsert: true,
}),
])
.then(() => cb(null, userToSave))
.catch((err) => cb(err, userToSave));
}
)
);
passport.serializeUser(function (user, done) {
done(null, user.discord_id);
});
passport.deserializeUser(function (discord_id, done) {
User.findOne({ discord_id }, function (err, user) {
done(err, user);
});
});
console.log("connecting to MongoDB");
let dbName =
process.env.NODE_ENV === "development" ? "development" : "production";
if (process.env.USE_PRODUCTION_DB) dbName = "production";
mongoose
.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
dbName,
useUnifiedTopology: true,
})
.then(() => {
console.log(`connected to MongoDB (${dbName})`);
})
.catch((error) => {
console.log("error connection to MongoDB:", error.message);
});
const server = new ApolloServer({
introspection: true,
playground: true,
schema,
context: ({ req }) => {
return {
user: process.env.LOGGED_IN ? mockUser : req.user,
playerLoader: new DataLoader(async (playerIds) => {
const users = await ObjectionUser.query()
.select()
.whereIn("playerId", playerIds);
const userMap = new Map();
users.forEach((user) => {
userMap.set(user.playerId, user);
});
return playerIds.map((id) => userMap.get(id));
}),
xRankPlacementLoader: new DataLoader(async (playerIds) => {
const placements = await XRankPlacement.query()
.select()
.whereIn("playerId", playerIds)
.withGraphFetched("weapon");
const placementsMap = new Map();
placements.forEach((placement) => {
const arr = placementsMap.get(placement.playerId);
if (arr) {
arr.push(placement);
} else {
placementsMap.set(placement.playerId, [placement]);
}
});
return playerIds.map((id) => placementsMap.get(id));
}),
xRankPlayerNameLoader: new DataLoader(async (playerIds) => {
const placements = await XRankPlacement.query()
.select()
.whereIn("playerId", playerIds);
const nameMap = new Map();
placements.forEach((placement) => {
nameMap.set(placement.playerId, placement.playerName);
});
return playerIds.map((id) => nameMap.get(id));
}),
};
},
validationRules: [depthLimit(4)],
});
const app = express();
app.use(bodyParser.json({ limit: "1mb" }));
app.use(bodyParser.urlencoded({ limit: "50mb", extended: true }));
app.use(cors());
//https://stackoverflow.com/questions/8605720/how-to-force-ssl-https-in-express-js/31144924#31144924
function requireHTTPS(req, res, next) {
// The 'x-forwarded-proto' check is for Heroku
if (
!req.secure &&
req.get("x-forwarded-proto") !== "https" &&
process.env.NODE_ENV !== "development"
) {
return res.redirect("https://" + req.get("host") + req.url);
}
next();
}
app.use(requireHTTPS);
//https://www.npmjs.com/package/express-session
let sess = {
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: { maxAge: 1209600000 }, // 2 weeks
store: new MongoStore({
mongooseConnection: mongoose.connection,
touchAfter: 24 * 3600,
}),
};
if (process.env.NODE_ENV === "production") {
sess.cookie.secure = true;
app.set("trust proxy", 1);
}
app.use(session(sess));
app.use(compression());
app.use(express.static("build"));
app.use(passport.initialize());
app.use(passport.session());
server.applyMiddleware({ app });
app.get("/auth/discord", passport.authenticate("discord"));
app.get(
"/auth/discord/callback",
passport.authenticate("discord", {
failureRedirect: "/404",
}),
function (req, res) {
res.redirect("/u/" + req.user.discord_id); // Successful auth
}
);
app.get("/logout", function (req, res) {
req.logout();
res.redirect("/");
});
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "../build", "index.html"));
});
const PORT = process.env.PORT || 3001;
app.listen({ port: PORT }, () => {
console.log(
`Server running on http://localhost:${PORT}${server.graphqlPath}`
);
});