| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 | 
							- const CoreClass = require("../core.js");
 
- const express = require("express");
 
- const bodyParser = require("body-parser");
 
- const cookieParser = require("cookie-parser");
 
- const cors = require("cors");
 
- const config = require("config");
 
- const async = require("async");
 
- const request = require("request");
 
- const OAuth2 = require("oauth").OAuth2;
 
- class AppModule extends CoreClass {
 
-     constructor() {
 
-         super("app");
 
-     }
 
-     initialize() {
 
-         return new Promise(async (resolve, reject) => {
 
-             const mail = this.moduleManager.modules["mail"],
 
-                 cache = this.moduleManager.modules["cache"],
 
-                 db = this.moduleManager.modules["db"],
 
-                 activities = this.moduleManager.modules["activities"];
 
-             this.utils = this.moduleManager.modules["utils"];
 
-             let app = (this.app = express());
 
-             const SIDname = config.get("cookie.SIDname");
 
-             this.server = app.listen(config.get("serverPort"));
 
-             app.use(cookieParser());
 
-             app.use(bodyParser.json());
 
-             app.use(bodyParser.urlencoded({ extended: true }));
 
-             const userModel = await db.runJob("GET_MODEL", {
 
-                 modelName: "user",
 
-             });
 
-             let corsOptions = Object.assign({}, config.get("cors"));
 
-             app.use(cors(corsOptions));
 
-             app.options("*", cors(corsOptions));
 
-             let oauth2 = new OAuth2(
 
-                 config.get("apis.github.client"),
 
-                 config.get("apis.github.secret"),
 
-                 "https://github.com/",
 
-                 "login/oauth/authorize",
 
-                 "login/oauth/access_token",
 
-                 null
 
-             );
 
-             let redirect_uri =
 
-                 config.get("serverDomain") + "/auth/github/authorize/callback";
 
-             app.get("/auth/github/authorize", async (req, res) => {
 
-                 if (this.getStatus() !== "READY") {
 
-                     this.log(
 
-                         "INFO",
 
-                         "APP_REJECTED_GITHUB_AUTHORIZE",
 
-                         `A user tried to use github authorize, but the APP module is currently not ready.`
 
-                     );
 
-                     return redirectOnErr(
 
-                         res,
 
-                         "Something went wrong on our end. Please try again later."
 
-                     );
 
-                 }
 
-                 let params = [
 
-                     `client_id=${config.get("apis.github.client")}`,
 
-                     `redirect_uri=${config.get(
 
-                         "serverDomain"
 
-                     )}/auth/github/authorize/callback`,
 
-                     `scope=user:email`,
 
-                 ].join("&");
 
-                 res.redirect(
 
-                     `https://github.com/login/oauth/authorize?${params}`
 
-                 );
 
-             });
 
-             app.get("/auth/github/link", async (req, res) => {
 
-                 if (this.getStatus() !== "READY") {
 
-                     this.log(
 
-                         "INFO",
 
-                         "APP_REJECTED_GITHUB_AUTHORIZE",
 
-                         `A user tried to use github authorize, but the APP module is currently not ready.`
 
-                     );
 
-                     return redirectOnErr(
 
-                         res,
 
-                         "Something went wrong on our end. Please try again later."
 
-                     );
 
-                 }
 
-                 let params = [
 
-                     `client_id=${config.get("apis.github.client")}`,
 
-                     `redirect_uri=${config.get(
 
-                         "serverDomain"
 
-                     )}/auth/github/authorize/callback`,
 
-                     `scope=user:email`,
 
-                     `state=${req.cookies[SIDname]}`,
 
-                 ].join("&");
 
-                 res.redirect(
 
-                     `https://github.com/login/oauth/authorize?${params}`
 
-                 );
 
-             });
 
-             function redirectOnErr(res, err) {
 
-                 return res.redirect(
 
-                     `${config.get("domain")}/?err=${encodeURIComponent(err)}`
 
-                 );
 
-             }
 
-             app.get("/auth/github/authorize/callback", async (req, res) => {
 
-                 if (this.getStatus() !== "READY") {
 
-                     this.log(
 
-                         "INFO",
 
-                         "APP_REJECTED_GITHUB_AUTHORIZE",
 
-                         `A user tried to use github authorize, but the APP module is currently not ready.`
 
-                     );
 
-                     return redirectOnErr(
 
-                         res,
 
-                         "Something went wrong on our end. Please try again later."
 
-                     );
 
-                 }
 
-                 let code = req.query.code;
 
-                 let access_token;
 
-                 let body;
 
-                 let address;
 
-                 const state = req.query.state;
 
-                 const verificationToken = await this.utils.runJob(
 
-                     "GENERATE_RANDOM_STRING",
 
-                     { length: 64 }
 
-                 );
 
-                 async.waterfall(
 
-                     [
 
-                         (next) => {
 
-                             if (req.query.error)
 
-                                 return next(req.query.error_description);
 
-                             next();
 
-                         },
 
-                         (next) => {
 
-                             oauth2.getOAuthAccessToken(
 
-                                 code,
 
-                                 { redirect_uri },
 
-                                 next
 
-                             );
 
-                         },
 
-                         (_access_token, refresh_token, results, next) => {
 
-                             if (results.error)
 
-                                 return next(results.error_description);
 
-                             access_token = _access_token;
 
-                             request.get(
 
-                                 {
 
-                                     url: `https://api.github.com/user`,
 
-                                     headers: {
 
-                                         "User-Agent": "request",
 
-                                         Authorization: `token ${access_token}`,
 
-                                     },
 
-                                 },
 
-                                 next
 
-                             );
 
-                         },
 
-                         (httpResponse, _body, next) => {
 
-                             body = _body = JSON.parse(_body);
 
-                             if (httpResponse.statusCode !== 200)
 
-                                 return next(body.message);
 
-                             if (state) {
 
-                                 return async.waterfall(
 
-                                     [
 
-                                         (next) => {
 
-                                             cache
 
-                                                 .runJob("HGET", {
 
-                                                     table: "sessions",
 
-                                                     key: state,
 
-                                                 })
 
-                                                 .then((session) =>
 
-                                                     next(null, session)
 
-                                                 )
 
-                                                 .catch(next);
 
-                                         },
 
-                                         (session, next) => {
 
-                                             if (!session)
 
-                                                 return next("Invalid session.");
 
-                                             userModel.findOne(
 
-                                                 { _id: session.userId },
 
-                                                 next
 
-                                             );
 
-                                         },
 
-                                         (user, next) => {
 
-                                             if (!user)
 
-                                                 return next("User not found.");
 
-                                             if (
 
-                                                 user.services.github &&
 
-                                                 user.services.github.id
 
-                                             )
 
-                                                 return next(
 
-                                                     "Account already has GitHub linked."
 
-                                                 );
 
-                                             userModel.updateOne(
 
-                                                 { _id: user._id },
 
-                                                 {
 
-                                                     $set: {
 
-                                                         "services.github": {
 
-                                                             id: body.id,
 
-                                                             access_token,
 
-                                                         },
 
-                                                     },
 
-                                                 },
 
-                                                 { runValidators: true },
 
-                                                 (err) => {
 
-                                                     if (err) return next(err);
 
-                                                     next(null, user, body);
 
-                                                 }
 
-                                             );
 
-                                         },
 
-                                         (user) => {
 
-                                             cache.runJob("PUB", {
 
-                                                 channel: "user.linkGithub",
 
-                                                 value: user._id,
 
-                                             });
 
-                                             res.redirect(
 
-                                                 `${config.get(
 
-                                                     "domain"
 
-                                                 )}/settings`
 
-                                             );
 
-                                         },
 
-                                     ],
 
-                                     next
 
-                                 );
 
-                             }
 
-                             if (!body.id)
 
-                                 return next("Something went wrong, no id.");
 
-                             userModel.findOne(
 
-                                 { "services.github.id": body.id },
 
-                                 (err, user) => {
 
-                                     next(err, user, body);
 
-                                 }
 
-                             );
 
-                         },
 
-                         (user, body, next) => {
 
-                             if (user) {
 
-                                 user.services.github.access_token = access_token;
 
-                                 return user.save(() => {
 
-                                     next(true, user._id);
 
-                                 });
 
-                             }
 
-                             userModel.findOne(
 
-                                 {
 
-                                     username: new RegExp(
 
-                                         `^${body.login}$`,
 
-                                         "i"
 
-                                     ),
 
-                                 },
 
-                                 (err, user) => {
 
-                                     next(err, user);
 
-                                 }
 
-                             );
 
-                         },
 
-                         (user, next) => {
 
-                             if (user)
 
-                                 return next(
 
-                                     `An account with that username already exists.`
 
-                                 );
 
-                             request.get(
 
-                                 {
 
-                                     url: `https://api.github.com/user/emails`,
 
-                                     headers: {
 
-                                         "User-Agent": "request",
 
-                                         Authorization: `token ${access_token}`,
 
-                                     },
 
-                                 },
 
-                                 next
 
-                             );
 
-                         },
 
-                         (httpResponse, body2, next) => {
 
-                             body2 = JSON.parse(body2);
 
-                             if (!Array.isArray(body2))
 
-                                 return next(body2.message);
 
-                             body2.forEach((email) => {
 
-                                 if (email.primary)
 
-                                     address = email.email.toLowerCase();
 
-                             });
 
-                             userModel.findOne(
 
-                                 { "email.address": address },
 
-                                 next
 
-                             );
 
-                         },
 
-                         (user, next) => {
 
-                             this.utils
 
-                                 .runJob("GENERATE_RANDOM_STRING", {
 
-                                     length: 12,
 
-                                 })
 
-                                 .then((_id) => {
 
-                                     next(null, user, _id);
 
-                                 });
 
-                         },
 
-                         (user, _id, next) => {
 
-                             if (user) {
 
-                                 if (Object.keys(JSON.parse(user.services.github)).length === 0)
 
-                                     return next(`An account with that email address exists, but is not linked to GitHub.`)    
 
-                                 else
 
-                                     return next(`An account with that email address already exists.`);
 
-                             }
 
-                             next(null, {
 
-                                 _id, //TODO Check if exists
 
-                                 username: body.login,
 
-                                 name: body.name,
 
-                                 location: body.location,
 
-                                 bio: body.bio,
 
-                                 email: {
 
-                                     address,
 
-                                     verificationToken,
 
-                                 },
 
-                                 services: {
 
-                                     github: { id: body.id, access_token },
 
-                                 },
 
-                             });
 
-                         },
 
-                         // generate the url for gravatar avatar
 
-                         (user, next) => {
 
-                             this.utils
 
-                                 .runJob("CREATE_GRAVATAR", {
 
-                                     email: user.email.address,
 
-                                 })
 
-                                 .then((url) => {
 
-                                     user.avatar = { type: "gravatar", url };
 
-                                     next(null, user);
 
-                                 });
 
-                         },
 
-                         // save the new user to the database
 
-                         (user, next) => {
 
-                             userModel.create(user, next);
 
-                         },
 
-                         // add the activity of account creation
 
-                         (user, next) => {
 
-                             activities.runJob("ADD_ACTIVITY", {
 
-                                 userId: user._id,
 
-                                 activityType: "created_account",
 
-                             });
 
-                             next(null, user);
 
-                         },
 
-                         (user, next) => {
 
-                             mail.runJob("GET_SCHEMA", {
 
-                                 schemaName: "verifyEmail",
 
-                             }).then((verifyEmailSchema) => {
 
-                                 verifyEmailSchema(
 
-                                     address,
 
-                                     body.login,
 
-                                     user.email.verificationToken
 
-                                 );
 
-                                 next(null, user._id);
 
-                             });
 
-                         },
 
-                     ],
 
-                     async (err, userId) => {
 
-                         if (err && err !== true) {
 
-                             err = await this.utils.runJob("GET_ERROR", {
 
-                                 error: err,
 
-                             });
 
-                             this.log(
 
-                                 "ERROR",
 
-                                 "AUTH_GITHUB_AUTHORIZE_CALLBACK",
 
-                                 `Failed to authorize with GitHub. "${err}"`
 
-                             );
 
-                             return redirectOnErr(res, err);
 
-                         }
 
-                         const sessionId = await this.utils.runJob("GUID", {});
 
-                         const sessionSchema = await cache.runJob("GET_SCHEMA", {
 
-                             schemaName: "session",
 
-                         });
 
-                         cache
 
-                             .runJob("HSET", {
 
-                                 table: "sessions",
 
-                                 key: sessionId,
 
-                                 value: sessionSchema(sessionId, userId),
 
-                             })
 
-                             .then(() => {
 
-                                 let date = new Date();
 
-                                 date.setTime(
 
-                                     new Date().getTime() +
 
-                                         2 * 365 * 24 * 60 * 60 * 1000
 
-                                 );
 
-                                 res.cookie(SIDname, sessionId, {
 
-                                     expires: date,
 
-                                     secure: config.get("cookie.secure"),
 
-                                     path: "/",
 
-                                     domain: config.get("cookie.domain"),
 
-                                 });
 
-                                 this.log(
 
-                                     "INFO",
 
-                                     "AUTH_GITHUB_AUTHORIZE_CALLBACK",
 
-                                     `User "${userId}" successfully authorized with GitHub.`
 
-                                 );
 
-                                 res.redirect(`${config.get("domain")}/`);
 
-                             })
 
-                             .catch((err) => {
 
-                                 return redirectOnErr(res, err.message);
 
-                             });
 
-                     }
 
-                 );
 
-             });
 
-             app.get("/auth/verify_email", async (req, res) => {
 
-                 if (this.getStatus() !== "READY") {
 
-                     this.log(
 
-                         "INFO",
 
-                         "APP_REJECTED_GITHUB_AUTHORIZE",
 
-                         `A user tried to use github authorize, but the APP module is currently not ready.`
 
-                     );
 
-                     return redirectOnErr(
 
-                         res,
 
-                         "Something went wrong on our end. Please try again later."
 
-                     );
 
-                 }
 
-                 let code = req.query.code;
 
-                 async.waterfall(
 
-                     [
 
-                         (next) => {
 
-                             if (!code) return next("Invalid code.");
 
-                             next();
 
-                         },
 
-                         (next) => {
 
-                             userModel.findOne(
 
-                                 { "email.verificationToken": code },
 
-                                 next
 
-                             );
 
-                         },
 
-                         (user, next) => {
 
-                             if (!user) return next("User not found.");
 
-                             if (user.email.verified)
 
-                                 return next("This email is already verified.");
 
-                             userModel.updateOne(
 
-                                 { "email.verificationToken": code },
 
-                                 {
 
-                                     $set: { "email.verified": true },
 
-                                     $unset: { "email.verificationToken": "" },
 
-                                 },
 
-                                 { runValidators: true },
 
-                                 next
 
-                             );
 
-                         },
 
-                     ],
 
-                     (err) => {
 
-                         if (err) {
 
-                             let error = "An error occurred.";
 
-                             if (typeof err === "string") error = err;
 
-                             else if (err.message) error = err.message;
 
-                             this.log(
 
-                                 "ERROR",
 
-                                 "VERIFY_EMAIL",
 
-                                 `Verifying email failed. "${error}"`
 
-                             );
 
-                             return res.json({
 
-                                 status: "failure",
 
-                                 message: error,
 
-                             });
 
-                         }
 
-                         this.log(
 
-                             "INFO",
 
-                             "VERIFY_EMAIL",
 
-                             `Successfully verified email.`
 
-                         );
 
-                         res.redirect(
 
-                             `${config.get(
 
-                                 "domain"
 
-                             )}?msg=Thank you for verifying your email`
 
-                         );
 
-                     }
 
-                 );
 
-             });
 
-             resolve();
 
-         });
 
-     }
 
-     SERVER(payload) {
 
-         return new Promise((resolve, reject) => {
 
-             resolve(this.server);
 
-         });
 
-     }
 
-     GET_APP(payload) {
 
-         return new Promise((resolve, reject) => {
 
-             resolve({ app: this.app });
 
-         });
 
-     }
 
-     EXAMPLE_JOB(payload) {
 
-         return new Promise((resolve, reject) => {
 
-             if (true) {
 
-                 resolve({});
 
-             } else {
 
-                 reject(new Error("Nothing changed."));
 
-             }
 
-         });
 
-     }
 
- }
 
- module.exports = new AppModule();
 
 
  |