Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Update "any" types to more precise #230

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 10 additions & 10 deletions src/config/passport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import _ from "lodash";

// import { User, UserType } from '../models/User';
GrayStrider marked this conversation as resolved.
Show resolved Hide resolved
import { User, UserDocument } from "../models/User";
import { Request, Response, NextFunction } from "express";
import {genericExpressMethod} from "express-request-with-user";
GrayStrider marked this conversation as resolved.
Show resolved Hide resolved

const LocalStrategy = passportLocal.Strategy;
const FacebookStrategy = passportFacebook.Strategy;
Expand All @@ -25,12 +25,12 @@ passport.deserializeUser((id, done) => {
* Sign in using Email and Password.
*/
passport.use(new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
User.findOne({ email: email.toLowerCase() }, (err, user: any) => {
User.findOne({ email: email.toLowerCase() }, (err, user: UserDocument) => {
if (err) { return done(err); }
if (!user) {
return done(undefined, false, { message: `Email ${email} not found.` });
}
user.comparePassword(password, (err: Error, isMatch: boolean) => {
user.comparePassword(password, (err, isMatch) => {
if (err) { return done(err); }
if (isMatch) {
return done(undefined, user);
Expand Down Expand Up @@ -66,15 +66,15 @@ passport.use(new FacebookStrategy({
callbackURL: "/auth/facebook/callback",
profileFields: ["name", "email", "link", "locale", "timezone"],
passReqToCallback: true
}, (req: any, accessToken, refreshToken, profile, done) => {
}, (req, accessToken, refreshToken, profile, done) => {
if (req.user) {
User.findOne({ facebook: profile.id }, (err, existingUser) => {
if (err) { return done(err); }
if (existingUser) {
req.flash("errors", { msg: "There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account." });
done(err);
} else {
User.findById(req.user.id, (err, user: any) => {
User.findById(req.user.id, (err, user) => {
if (err) { return done(err); }
user.facebook = profile.id;
user.tokens.push({ kind: "facebook", accessToken });
Expand All @@ -100,7 +100,7 @@ passport.use(new FacebookStrategy({
req.flash("errors", { msg: "There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings." });
done(err);
} else {
const user: any = new User();
const user: UserDocument = new User();
user.email = profile._json.email;
user.facebook = profile.id;
user.tokens.push({ kind: "facebook", accessToken });
Expand All @@ -120,7 +120,7 @@ passport.use(new FacebookStrategy({
/**
* Login Required middleware.
*/
export const isAuthenticated = (req: Request, res: Response, next: NextFunction) => {
export const isAuthenticated: genericExpressMethod = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
Expand All @@ -130,11 +130,11 @@ export const isAuthenticated = (req: Request, res: Response, next: NextFunction)
/**
* Authorization Required middleware.
*/
export const isAuthorized = (req: Request, res: Response, next: NextFunction) => {
export const isAuthorized: genericExpressMethod = (req, res, next) => {
const provider = req.path.split("/").slice(-1)[0];

const user = req.user as UserDocument;
if (_.find(user.tokens, { kind: provider })) {
// const user = req.user as UserDocument;
if (_.find(req.user.tokens, { kind: provider })) {
next();
} else {
res.redirect(`/auth/${provider}`);
Expand Down
14 changes: 6 additions & 8 deletions src/controllers/api.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"use strict";

import graph from "fbgraph";
import { Response, Request, NextFunction } from "express";
import { UserDocument } from "../models/User";
import { Response, Request } from "express";
import {genericExpressMethod} from "express-request-with-user";
GrayStrider marked this conversation as resolved.
Show resolved Hide resolved


/**
Expand All @@ -19,11 +17,11 @@ export const getApi = (req: Request, res: Response) => {
* GET /api/facebook
* Facebook API example.
*/
export const getFacebook = (req: Request, res: Response, next: NextFunction) => {
const user = req.user as UserDocument;
const token = user.tokens.find((token: any) => token.kind === "facebook");
export const getFacebook: genericExpressMethod = (req, res, next) => {
// const user = req.user /*as UserDocument*/;
const token = req.user.tokens.find(token => token.kind === "facebook");
graph.setAccessToken(token.accessToken);
graph.get(`${user.facebook}?fields=id,name,email,first_name,last_name,gender,link,locale,timezone`, (err: Error, results: graph.FacebookUser) => {
graph.get(`${req.user.facebook}?fields=id,name,email,first_name,last_name,gender,link,locale,timezone`, (err: Error, results: graph.FacebookUser) => {
if (err) { return next(err); }
res.render("api/facebook", {
title: "Facebook API",
Expand Down
54 changes: 28 additions & 26 deletions src/controllers/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import async from "async";
import crypto from "crypto";
import nodemailer from "nodemailer";
import passport from "passport";
import { User, UserDocument, AuthToken } from "../models/User";
import { Request, Response, NextFunction } from "express";
import { IVerifyOptions } from "passport-local";
import { WriteError } from "mongodb";
import { check, sanitize, validationResult } from "express-validator";
import {AuthToken, User, UserDocument} from "../models/User";
import {Request, Response} from "express";
import {IVerifyOptions} from "passport-local";
import {WriteError} from "mongodb";
import {check, sanitize, validationResult} from "express-validator";
import "../config/passport";
import {genericExpressMethod} from "express-request-with-user";
GrayStrider marked this conversation as resolved.
Show resolved Hide resolved

/**
* GET /login
Expand All @@ -26,7 +27,8 @@ export const getLogin = (req: Request, res: Response) => {
* POST /login
* Sign in using email and password.
*/
export const postLogin = (req: Request, res: Response, next: NextFunction) => {

export const postLogin: genericExpressMethod = (req, res, next) => {
check("email", "Email is not valid").isEmail();
check("password", "Password cannot be blank").isLength({min: 1});
// eslint-disable-next-line @typescript-eslint/camelcase
Expand Down Expand Up @@ -79,7 +81,7 @@ export const getSignup = (req: Request, res: Response) => {
* POST /signup
* Create a new local account.
*/
export const postSignup = (req: Request, res: Response, next: NextFunction) => {
export const postSignup: genericExpressMethod = (req, res, next) => {
check("email", "Email is not valid").isEmail();
check("password", "Password must be at least 4 characters long").isLength({ min: 4 });
check("confirmPassword", "Passwords do not match").equals(req.body.password);
Expand Down Expand Up @@ -130,7 +132,7 @@ export const getAccount = (req: Request, res: Response) => {
* POST /account/profile
* Update profile information.
*/
export const postUpdateProfile = (req: Request, res: Response, next: NextFunction) => {
export const postUpdateProfile: genericExpressMethod = (req, res, next) => {
check("email", "Please enter a valid email address.").isEmail();
// eslint-disable-next-line @typescript-eslint/camelcase
sanitize("email").normalizeEmail({ gmail_remove_dots: false });
Expand All @@ -142,8 +144,8 @@ export const postUpdateProfile = (req: Request, res: Response, next: NextFunctio
return res.redirect("/account");
}

const user = req.user as UserDocument;
User.findById(user.id, (err, user: UserDocument) => {
// const user = req.user as UserDocument;
GrayStrider marked this conversation as resolved.
Show resolved Hide resolved
User.findById(req.user.id, (err, user) => {
if (err) { return next(err); }
user.email = req.body.email || "";
user.profile.name = req.body.name || "";
Expand All @@ -168,7 +170,7 @@ export const postUpdateProfile = (req: Request, res: Response, next: NextFunctio
* POST /account/password
* Update current password.
*/
export const postUpdatePassword = (req: Request, res: Response, next: NextFunction) => {
export const postUpdatePassword: genericExpressMethod = (req, res, next) => {
check("password", "Password must be at least 4 characters long").isLength({ min: 4 });
check("confirmPassword", "Passwords do not match").equals(req.body.password);

Expand All @@ -179,8 +181,8 @@ export const postUpdatePassword = (req: Request, res: Response, next: NextFuncti
return res.redirect("/account");
}

const user = req.user as UserDocument;
User.findById(user.id, (err, user: UserDocument) => {
// const user = req.user as UserDocument;
User.findById(req.user.id, (err, user) => {
if (err) { return next(err); }
user.password = req.body.password;
user.save((err: WriteError) => {
Expand All @@ -195,9 +197,9 @@ export const postUpdatePassword = (req: Request, res: Response, next: NextFuncti
* POST /account/delete
* Delete user account.
*/
export const postDeleteAccount = (req: Request, res: Response, next: NextFunction) => {
const user = req.user as UserDocument;
User.remove({ _id: user.id }, (err) => {
export const postDeleteAccount: genericExpressMethod = (req, res, next) => {
// const user = req.user as UserDocument;
User.remove({ _id: req.user.id }, (err) => {
if (err) { return next(err); }
req.logout();
req.flash("info", { msg: "Your account has been deleted." });
Expand All @@ -209,12 +211,12 @@ export const postDeleteAccount = (req: Request, res: Response, next: NextFunctio
* GET /account/unlink/:provider
* Unlink OAuth provider.
*/
export const getOauthUnlink = (req: Request, res: Response, next: NextFunction) => {
export const getOauthUnlink: genericExpressMethod = (req, res, next) => {
const provider = req.params.provider;
const user = req.user as UserDocument;
User.findById(user.id, (err, user: any) => {
// const user = req.user as UserDocument;
User.findById(req.user.id, (err, user) => {
if (err) { return next(err); }
user[provider] = undefined;
// user[provider] = undefined;
user.tokens = user.tokens.filter((token: AuthToken) => token.kind !== provider);
user.save((err: WriteError) => {
if (err) { return next(err); }
Expand All @@ -228,7 +230,7 @@ export const getOauthUnlink = (req: Request, res: Response, next: NextFunction)
* GET /reset/:token
* Reset Password page.
*/
export const getReset = (req: Request, res: Response, next: NextFunction) => {
export const getReset: genericExpressMethod = (req, res, next) => {
if (req.isAuthenticated()) {
return res.redirect("/");
}
Expand All @@ -251,7 +253,7 @@ export const getReset = (req: Request, res: Response, next: NextFunction) => {
* POST /reset/:token
* Process the reset password request.
*/
export const postReset = (req: Request, res: Response, next: NextFunction) => {
export const postReset: genericExpressMethod = (req, res, next) => {
check("password", "Password must be at least 4 characters long.").isLength({ min: 4 });
check("confirm", "Passwords must match.").equals(req.body.password);

Expand All @@ -267,7 +269,7 @@ export const postReset = (req: Request, res: Response, next: NextFunction) => {
User
.findOne({ passwordResetToken: req.params.token })
.where("passwordResetExpires").gt(Date.now())
.exec((err, user: any) => {
.exec((err, user) => {
if (err) { return next(err); }
if (!user) {
req.flash("errors", { msg: "Password reset token is invalid or has expired." });
Expand Down Expand Up @@ -326,7 +328,7 @@ export const getForgot = (req: Request, res: Response) => {
* POST /forgot
* Create a random token, then the send user an email with a reset link.
*/
export const postForgot = (req: Request, res: Response, next: NextFunction) => {
export const postForgot: genericExpressMethod = (req, res, next) => {
check("email", "Please enter a valid email address.").isEmail();
// eslint-disable-next-line @typescript-eslint/camelcase
sanitize("email").normalizeEmail({ gmail_remove_dots: false });
Expand All @@ -346,14 +348,14 @@ export const postForgot = (req: Request, res: Response, next: NextFunction) => {
});
},
function setRandomToken(token: AuthToken, done: Function) {
User.findOne({ email: req.body.email }, (err, user: any) => {
User.findOne({ email: req.body.email }, (err, user) => {
if (err) { return done(err); }
if (!user) {
req.flash("errors", { msg: "Account with that email address does not exist." });
return res.redirect("/forgot");
}
user.passwordResetToken = token;
user.passwordResetExpires = Date.now() + 3600000; // 1 hour
user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 hour
user.save((err: WriteError) => {
done(err, token, user);
});
Expand Down
7 changes: 5 additions & 2 deletions src/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import mongoose from "mongoose";
export type UserDocument = mongoose.Document & {
email: string;
password: string;
passwordResetToken: string;
passwordResetToken: AuthToken;
// passwordResetToken: string;
passwordResetExpires: Date;

facebook: string;
Expand All @@ -21,9 +22,11 @@ export type UserDocument = mongoose.Document & {

comparePassword: comparePasswordFunction;
gravatar: (size: number) => string;

// [provider: string]: any;
};

type comparePasswordFunction = (candidatePassword: string, cb: (err: any, isMatch: any) => {}) => void;
type comparePasswordFunction = (candidatePassword: string, cb: (err: Error, isMatch: boolean) => void) => void;

export interface AuthToken {
accessToken: string;
Expand Down
14 changes: 14 additions & 0 deletions src/types/express-request-with-user.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// <reference types="express" />
GrayStrider marked this conversation as resolved.
Show resolved Hide resolved

import {UserDocument} from "../models/User";
import {NextFunction, Request, Response} from "express";

declare module 'express' {
export interface User extends UserDocument {}
export interface Request {
user?: User;
}
}

/** To avoid duplication */
export type genericExpressMethod = (req: Request, res: Response, next: NextFunction) => void