1
0
mirror of https://github.com/microsoft/TypeScript-Node-Starter.git synced 2025-11-09 16:27:25 +00:00

Merge branch 'master' into master

This commit is contained in:
Orta
2019-06-19 14:55:39 -07:00
committed by GitHub
17 changed files with 4680 additions and 4629 deletions

View File

@@ -2,7 +2,6 @@ import express from "express";
import compression from "compression"; // compresses requests
import session from "express-session";
import bodyParser from "body-parser";
import logger from "./util/logger";
import lusca from "lusca";
import dotenv from "dotenv";
import mongo from "connect-mongo";
@@ -35,7 +34,8 @@ const app = express();
// Connect to MongoDB
const mongoUrl = MONGODB_URI;
(<any>mongoose).Promise = bluebird;
mongoose.connect(mongoUrl, {useMongoClient: true}).then(
mongoose.connect(mongoUrl, { useMongoClient: 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);
@@ -122,4 +122,4 @@ app.get("/auth/facebook/callback", passport.authenticate("facebook", { failureRe
res.redirect(req.session.returnTo || "/");
});
export default app;
export default app;

View File

@@ -1,11 +1,10 @@
import passport from "passport";
import request from "request";
import passportLocal from "passport-local";
import passportFacebook from "passport-facebook";
import _ from "lodash";
// import { User, UserType } from '../models/User';
import { default as User } from "../models/User";
import { User } from "../models/User";
import { Request, Response, NextFunction } from "express";
const LocalStrategy = passportLocal.Strategy;
@@ -121,7 +120,7 @@ passport.use(new FacebookStrategy({
/**
* Login Required middleware.
*/
export let isAuthenticated = (req: Request, res: Response, next: NextFunction) => {
export const isAuthenticated = (req: Request, res: Response, next: NextFunction) => {
if (req.isAuthenticated()) {
return next();
}
@@ -131,7 +130,7 @@ export let isAuthenticated = (req: Request, res: Response, next: NextFunction) =
/**
* Authorization Required middleware.
*/
export let isAuthorized = (req: Request, res: Response, next: NextFunction) => {
export const isAuthorized = (req: Request, res: Response, next: NextFunction) => {
const provider = req.path.split("/").slice(-1)[0];
if (_.find(req.user.tokens, { kind: provider })) {

View File

@@ -1,7 +1,5 @@
"use strict";
import async from "async";
import request from "request";
import graph from "fbgraph";
import { Response, Request, NextFunction } from "express";
@@ -10,7 +8,7 @@ import { Response, Request, NextFunction } from "express";
* GET /api
* List of API examples.
*/
export let getApi = (req: Request, res: Response) => {
export const getApi = (req: Request, res: Response) => {
res.render("api/index", {
title: "API Examples"
});
@@ -20,7 +18,7 @@ export let getApi = (req: Request, res: Response) => {
* GET /api/facebook
* Facebook API example.
*/
export let getFacebook = (req: Request, res: Response, next: NextFunction) => {
export const getFacebook = (req: Request, res: Response, next: NextFunction) => {
const token = req.user.tokens.find((token: any) => token.kind === "facebook");
graph.setAccessToken(token.accessToken);
graph.get(`${req.user.facebook}?fields=id,name,email,first_name,last_name,gender,link,locale,timezone`, (err: Error, results: graph.FacebookUser) => {

View File

@@ -13,7 +13,7 @@ const transporter = nodemailer.createTransport({
* GET /contact
* Contact form page.
*/
export let getContact = (req: Request, res: Response) => {
export const getContact = (req: Request, res: Response) => {
res.render("contact", {
title: "Contact"
});
@@ -23,7 +23,7 @@ export let getContact = (req: Request, res: Response) => {
* POST /contact
* Send a contact form via Nodemailer.
*/
export let postContact = (req: Request, res: Response) => {
export const postContact = (req: Request, res: Response) => {
req.assert("name", "Name cannot be blank").notEmpty();
req.assert("email", "Email is not valid").isEmail();
req.assert("message", "Message cannot be blank").notEmpty();

View File

@@ -4,7 +4,7 @@ import { Request, Response } from "express";
* GET /
* Home page.
*/
export let index = (req: Request, res: Response) => {
export const index = (req: Request, res: Response) => {
res.render("home", {
title: "Home"
});

View File

@@ -2,19 +2,18 @@ import async from "async";
import crypto from "crypto";
import nodemailer from "nodemailer";
import passport from "passport";
import { default as User, UserModel, AuthToken } from "../models/User";
import { User, UserDocument, AuthToken } from "../models/User";
import { Request, Response, NextFunction } from "express";
import { IVerifyOptions } from "passport-local";
import { WriteError } from "mongodb";
import request from "express-validator";
import "../config/passport";
/**
* GET /login
* Login page.
*/
export let getLogin = (req: Request, res: Response) => {
export const getLogin = (req: Request, res: Response) => {
if (req.user) {
return res.redirect("/");
}
@@ -27,7 +26,7 @@ export let getLogin = (req: Request, res: Response) => {
* POST /login
* Sign in using email and password.
*/
export let postLogin = (req: Request, res: Response, next: NextFunction) => {
export const postLogin = (req: Request, res: Response, next: NextFunction) => {
req.assert("email", "Email is not valid").isEmail();
req.assert("password", "Password cannot be blank").notEmpty();
req.sanitize("email").normalizeEmail({ gmail_remove_dots: false });
@@ -39,7 +38,7 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
return res.redirect("/login");
}
passport.authenticate("local", (err: Error, user: UserModel, info: IVerifyOptions) => {
passport.authenticate("local", (err: Error, user: UserDocument, info: IVerifyOptions) => {
if (err) { return next(err); }
if (!user) {
req.flash("errors", info.message);
@@ -57,7 +56,7 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
* GET /logout
* Log out.
*/
export let logout = (req: Request, res: Response) => {
export const logout = (req: Request, res: Response) => {
req.logout();
res.redirect("/");
};
@@ -66,7 +65,7 @@ export let logout = (req: Request, res: Response) => {
* GET /signup
* Signup page.
*/
export let getSignup = (req: Request, res: Response) => {
export const getSignup = (req: Request, res: Response) => {
if (req.user) {
return res.redirect("/");
}
@@ -79,7 +78,7 @@ export let getSignup = (req: Request, res: Response) => {
* POST /signup
* Create a new local account.
*/
export let postSignup = (req: Request, res: Response, next: NextFunction) => {
export const postSignup = (req: Request, res: Response, next: NextFunction) => {
req.assert("email", "Email is not valid").isEmail();
req.assert("password", "Password must be at least 4 characters long").len({ min: 4 });
req.assert("confirmPassword", "Passwords do not match").equals(req.body.password);
@@ -119,7 +118,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => {
* GET /account
* Profile page.
*/
export let getAccount = (req: Request, res: Response) => {
export const getAccount = (req: Request, res: Response) => {
res.render("account/profile", {
title: "Account Management"
});
@@ -129,7 +128,7 @@ export let getAccount = (req: Request, res: Response) => {
* POST /account/profile
* Update profile information.
*/
export let postUpdateProfile = (req: Request, res: Response, next: NextFunction) => {
export const postUpdateProfile = (req: Request, res: Response, next: NextFunction) => {
req.assert("email", "Please enter a valid email address.").isEmail();
req.sanitize("email").normalizeEmail({ gmail_remove_dots: false });
@@ -140,7 +139,7 @@ export let postUpdateProfile = (req: Request, res: Response, next: NextFunction)
return res.redirect("/account");
}
User.findById(req.user.id, (err, user: UserModel) => {
User.findById(req.user.id, (err, user: UserDocument) => {
if (err) { return next(err); }
user.email = req.body.email || "";
user.profile.name = req.body.name || "";
@@ -165,7 +164,7 @@ export let postUpdateProfile = (req: Request, res: Response, next: NextFunction)
* POST /account/password
* Update current password.
*/
export let postUpdatePassword = (req: Request, res: Response, next: NextFunction) => {
export const postUpdatePassword = (req: Request, res: Response, next: NextFunction) => {
req.assert("password", "Password must be at least 4 characters long").len({ min: 4 });
req.assert("confirmPassword", "Passwords do not match").equals(req.body.password);
@@ -176,7 +175,7 @@ export let postUpdatePassword = (req: Request, res: Response, next: NextFunction
return res.redirect("/account");
}
User.findById(req.user.id, (err, user: UserModel) => {
User.findById(req.user.id, (err, user: UserDocument) => {
if (err) { return next(err); }
user.password = req.body.password;
user.save((err: WriteError) => {
@@ -191,7 +190,7 @@ export let postUpdatePassword = (req: Request, res: Response, next: NextFunction
* POST /account/delete
* Delete user account.
*/
export let postDeleteAccount = (req: Request, res: Response, next: NextFunction) => {
export const postDeleteAccount = (req: Request, res: Response, next: NextFunction) => {
User.remove({ _id: req.user.id }, (err) => {
if (err) { return next(err); }
req.logout();
@@ -204,7 +203,7 @@ export let postDeleteAccount = (req: Request, res: Response, next: NextFunction)
* GET /account/unlink/:provider
* Unlink OAuth provider.
*/
export let getOauthUnlink = (req: Request, res: Response, next: NextFunction) => {
export const getOauthUnlink = (req: Request, res: Response, next: NextFunction) => {
const provider = req.params.provider;
User.findById(req.user.id, (err, user: any) => {
if (err) { return next(err); }
@@ -222,7 +221,7 @@ export let getOauthUnlink = (req: Request, res: Response, next: NextFunction) =>
* GET /reset/:token
* Reset Password page.
*/
export let getReset = (req: Request, res: Response, next: NextFunction) => {
export const getReset = (req: Request, res: Response, next: NextFunction) => {
if (req.isAuthenticated()) {
return res.redirect("/");
}
@@ -245,7 +244,7 @@ export let getReset = (req: Request, res: Response, next: NextFunction) => {
* POST /reset/:token
* Process the reset password request.
*/
export let postReset = (req: Request, res: Response, next: NextFunction) => {
export const postReset = (req: Request, res: Response, next: NextFunction) => {
req.assert("password", "Password must be at least 4 characters long.").len({ min: 4 });
req.assert("confirm", "Passwords must match.").equals(req.body.password);
@@ -278,7 +277,7 @@ export let postReset = (req: Request, res: Response, next: NextFunction) => {
});
});
},
function sendResetPasswordEmail(user: UserModel, done: Function) {
function sendResetPasswordEmail(user: UserDocument, done: Function) {
const transporter = nodemailer.createTransport({
service: "SendGrid",
auth: {
@@ -307,7 +306,7 @@ export let postReset = (req: Request, res: Response, next: NextFunction) => {
* GET /forgot
* Forgot Password page.
*/
export let getForgot = (req: Request, res: Response) => {
export const getForgot = (req: Request, res: Response) => {
if (req.isAuthenticated()) {
return res.redirect("/");
}
@@ -320,7 +319,7 @@ export let getForgot = (req: Request, res: Response) => {
* POST /forgot
* Create a random token, then the send user an email with a reset link.
*/
export let postForgot = (req: Request, res: Response, next: NextFunction) => {
export const postForgot = (req: Request, res: Response, next: NextFunction) => {
req.assert("email", "Please enter a valid email address.").isEmail();
req.sanitize("email").normalizeEmail({ gmail_remove_dots: false });
@@ -352,7 +351,7 @@ export let postForgot = (req: Request, res: Response, next: NextFunction) => {
});
});
},
function sendForgotPasswordEmail(token: AuthToken, user: UserModel, done: Function) {
function sendForgotPasswordEmail(token: AuthToken, user: UserDocument, done: Function) {
const transporter = nodemailer.createTransport({
service: "SendGrid",
auth: {

View File

@@ -2,7 +2,7 @@ import bcrypt from "bcrypt-nodejs";
import crypto from "crypto";
import mongoose from "mongoose";
export type UserModel = mongoose.Document & {
export type UserDocument = mongoose.Document & {
email: string,
password: string,
passwordResetToken: string,
@@ -77,10 +77,7 @@ userSchema.methods.comparePassword = comparePassword;
/**
* Helper method for getting user's gravatar.
*/
userSchema.methods.gravatar = function (size: number) {
if (!size) {
size = 200;
}
userSchema.methods.gravatar = function (size: number = 200) {
if (!this.email) {
return `https://gravatar.com/avatar/?s=${size}&d=retro`;
}
@@ -88,6 +85,4 @@ userSchema.methods.gravatar = function (size: number) {
return `https://gravatar.com/avatar/${md5}?s=${size}&d=retro`;
};
// export const User: UserType = mongoose.model<UserType>('User', userSchema);
const User = mongoose.model("User", userSchema);
export default User;
export const User = mongoose.model<UserDocument>("User", userSchema);

View File

@@ -1,6 +1,5 @@
import winston from "winston";
import { Logger } from "winston";
import { ENVIRONMENT } from "./secrets";
const logger = new (Logger)({
transports: [

View File

@@ -21,6 +21,10 @@ if (!SESSION_SECRET) {
}
if (!MONGODB_URI) {
logger.error("No mongo connection string. Set MONGODB_URI environment variable.");
if (prod) {
logger.error("No mongo connection string. Set MONGODB_URI environment variable.");
} else {
logger.error("No mongo connection string. Set MONGODB_URI_LOCAL environment variable.");
}
process.exit(1);
}