├── .gitignore
├── README.md
├── client
├── package.json
├── public
│ ├── index.html
│ └── manifest.json
├── src
│ ├── App.js
│ ├── App.test.js
│ ├── AppRouter.js
│ ├── components
│ │ ├── Header.jsx
│ │ └── Homepage.jsx
│ ├── images
│ │ ├── AppPage.png
│ │ ├── demo.gif
│ │ ├── keys.png
│ │ ├── session.png
│ │ └── sign-in-with-twitter-gray.png
│ ├── index.css
│ ├── index.js
│ └── serviceWorker.js
└── yarn.lock
├── server
├── config
│ ├── keys.copy.js
│ └── passport-setup.js
├── index.js
├── models
│ └── user-model.js
├── package.json
├── routes
│ └── auth-routes.js
└── yarn.lock
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /.pnp
5 | .pnp.js
6 |
7 | # testing
8 | /coverage
9 |
10 | # production
11 | /build
12 | /public
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | # client
22 | /client/node_modules
23 |
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # server
29 | /server/config/keys.js
30 | /server/node_modules
31 | /client/build/
32 | node_modules
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Authenticate Twitter via passport
2 |
3 | ### About
4 |
5 | This is a simple web authentication web application via Twitter OAuth. Please feel free to fork this and build your own application. If you have any questions, please feel free to send me an issue or a pull request.
6 |
7 | ### Demo
8 |
9 | 
10 |
11 | ---
12 | ### Follow my online tutorial
13 | - https://medium.com/@leannezhang/building-a-web-application-twitter-oauth-using-passport-js-part-1-9ffa6f49ef0
14 |
15 | ---
16 |
17 | ### Server
18 |
19 | Run on express server
20 |
21 | ```
22 | cd server/
23 | nodemon index.js
24 | ```
25 |
26 | Go to localhost:4000
27 |
28 | ### Client
29 |
30 | ```
31 | cd client/
32 | yarn install
33 | yarn run start
34 | ```
35 |
36 | Go to localhost:3000
37 |
38 | ### Instructions
39 |
40 | - Rename `/server/config/keys.copy.js` to `/server/config/keys.js` and add your keys
41 |
42 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "twitter-authentication",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "prop-types": "^15.6.2",
7 | "react": "^16.7.0",
8 | "react-dom": "^16.7.0",
9 | "react-router-dom": "^5.0.0",
10 | "react-scripts": "2.1.2"
11 | },
12 | "scripts": {
13 | "start": "react-scripts start",
14 | "build": "react-scripts build",
15 | "test": "react-scripts test",
16 | "eject": "react-scripts eject"
17 | },
18 | "eslintConfig": {
19 | "extends": "react-app"
20 | },
21 | "browserslist": [
22 | ">0.2%",
23 | "not dead",
24 | "not ie <= 11",
25 | "not op_mini all"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
15 |
16 |
25 | React App
26 |
27 |
28 |
29 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/client/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/client/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { AppRouter } from "./AppRouter";
3 |
4 | class App extends Component {
5 | render() {
6 | return ;
7 | }
8 | }
9 |
10 | export default App;
11 |
--------------------------------------------------------------------------------
/client/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/client/src/AppRouter.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import HomePage from "./components/Homepage";
3 | import { BrowserRouter as Router, Route } from "react-router-dom";
4 |
5 | export const AppRouter = () => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/client/src/components/Header.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 | import PropTypes from "prop-types";
3 | import React, { Component } from "react";
4 |
5 | export default class Header extends Component {
6 | static propTypes = {
7 | authenticated: PropTypes.bool.isRequired
8 | };
9 |
10 | render() {
11 | const { authenticated } = this.props;
12 | return (
13 |
14 | -
15 | Home
16 |
17 | {authenticated ? (
18 | - Logout
19 | ) : (
20 | - Login
21 | )}
22 |
23 | );
24 | }
25 |
26 | _handleSignInClick = () => {
27 | // Authenticate using via passport api in the backend
28 | // Open Twitter login page
29 | // Upon successful login, a cookie session will be stored in the client
30 | window.open("http://localhost:4000/auth/twitter", "_self");
31 | };
32 |
33 | _handleLogoutClick = () => {
34 | // Logout using Twitter passport api
35 | // Set authenticated state to false in the HomePage
36 | window.open("http://localhost:4000/auth/logout", "_self");
37 | this.props.handleNotAuthenticated();
38 | };
39 | }
40 |
--------------------------------------------------------------------------------
/client/src/components/Homepage.jsx:
--------------------------------------------------------------------------------
1 | import Header from "./Header";
2 | import PropTypes from "prop-types";
3 | import React, { Component } from "react";
4 |
5 | export default class HomePage extends Component {
6 | static propTypes = {
7 | user: PropTypes.shape({
8 | name: PropTypes.string,
9 | profileImageUrl: PropTypes.string,
10 | twitterId: PropTypes.string,
11 | screenName: PropTypes.string,
12 | _id: PropTypes.string
13 | })
14 | };
15 |
16 | state = {
17 | user: {},
18 | error: null,
19 | authenticated: false
20 | };
21 |
22 | componentDidMount() {
23 | // Fetch does not send cookies. So you should add credentials: 'include'
24 | fetch("http://localhost:4000/auth", {
25 | method: "GET",
26 | credentials: "include",
27 | headers: {
28 | Accept: "application/json",
29 | "Content-Type": "application/json",
30 | "Access-Control-Allow-Credentials": true
31 | }
32 | })
33 | .then(response => {
34 | if (response.status === 200) return response.json();
35 | throw new Error("failed to authenticate user");
36 | })
37 | .then(responseJson => {
38 | this.setState({
39 | authenticated: true,
40 | user: responseJson.user
41 | });
42 | })
43 | .catch(error => {
44 | this.setState({
45 | authenticated: false,
46 | error: "Failed to authenticate user"
47 | });
48 | });
49 | }
50 |
51 | render() {
52 | const { authenticated } = this.state;
53 | return (
54 |
55 |
59 |
60 | {!authenticated ? (
61 |
Welcome!
62 | ) : (
63 |
64 |
You have login succcessfully!
65 | Welcome {this.state.user.name}!
66 |
67 | )}
68 |
69 |
70 | );
71 | }
72 |
73 | _handleNotAuthenticated = () => {
74 | this.setState({ authenticated: false });
75 | };
76 | }
77 |
--------------------------------------------------------------------------------
/client/src/images/AppPage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leannezhang/twitter-authentication/50355fe039ae149b944b8851493308738bbda0de/client/src/images/AppPage.png
--------------------------------------------------------------------------------
/client/src/images/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leannezhang/twitter-authentication/50355fe039ae149b944b8851493308738bbda0de/client/src/images/demo.gif
--------------------------------------------------------------------------------
/client/src/images/keys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leannezhang/twitter-authentication/50355fe039ae149b944b8851493308738bbda0de/client/src/images/keys.png
--------------------------------------------------------------------------------
/client/src/images/session.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leannezhang/twitter-authentication/50355fe039ae149b944b8851493308738bbda0de/client/src/images/session.png
--------------------------------------------------------------------------------
/client/src/images/sign-in-with-twitter-gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leannezhang/twitter-authentication/50355fe039ae149b944b8851493308738bbda0de/client/src/images/sign-in-with-twitter-gray.png
--------------------------------------------------------------------------------
/client/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
6 | sans-serif;
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | }
10 |
11 | code {
12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
13 | monospace;
14 | }
15 |
16 | .menu {
17 | display: flex;
18 | list-style-type: none;
19 | justify-content: flex-end;
20 | }
21 |
22 | .menu li {
23 | margin: 0 10px;
24 | cursor: pointer;
25 | text-decoration: underline;
26 | }
27 |
--------------------------------------------------------------------------------
/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import * as serviceWorker from './serviceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 |
9 | // If you want your app to work offline and load faster, you can change
10 | // unregister() to register() below. Note this comes with some pitfalls.
11 | // Learn more about service workers: http://bit.ly/CRA-PWA
12 | serviceWorker.unregister();
13 |
--------------------------------------------------------------------------------
/client/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read http://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/server/config/keys.copy.js:
--------------------------------------------------------------------------------
1 | // ADD YOUR OWN KEYS AND RENAME THIS FILE TO keys.js
2 | const TWITTER_TOKENS = {
3 | TWITTER_CONSUMER_KEY: "SOME KEY",
4 | TWITTER_CONSUMER_SECRET: "SOME SECRET",
5 | TWITTER_ACCESS_TOKEN: "SOME ACCESS TOKEN",
6 | TWITTER_TOKEN_SECRET: "SOME TOKEN SECRET"
7 | };
8 |
9 | const DB_USER = "SOME USER";
10 | const DB_PASSWORD = "SOME PASSWPORD";
11 | const MONGODB = {
12 | MONGODB_URI: `mongodb://${DB_USER}:${DB_PASSWORD}@ds.mlab.com:/`
13 | };
14 |
15 | const SESSION = {
16 | COOKIE_KEY: "thisappisawesome"
17 | };
18 |
19 | const KEYS = {
20 | ...TWITTER_TOKENS,
21 | ...MONGODB,
22 | ...SESSION
23 | };
24 |
25 | module.exports = KEYS;
26 |
--------------------------------------------------------------------------------
/server/config/passport-setup.js:
--------------------------------------------------------------------------------
1 | const passport = require("passport");
2 | const TwitterStrategy = require("passport-twitter");
3 | const keys = require("./keys");
4 | const User = require("../models/user-model");
5 |
6 | // serialize the user.id to save in the cookie session
7 | // so the browser will remember the user when login
8 | passport.serializeUser((user, done) => {
9 | done(null, user.id);
10 | });
11 |
12 | // deserialize the cookieUserId to user in the database
13 | passport.deserializeUser((id, done) => {
14 | User.findById(id)
15 | .then(user => {
16 | done(null, user);
17 | })
18 | .catch(e => {
19 | done(new Error("Failed to deserialize an user"));
20 | });
21 | });
22 |
23 | passport.use(
24 | new TwitterStrategy(
25 | {
26 | consumerKey: keys.TWITTER_CONSUMER_KEY,
27 | consumerSecret: keys.TWITTER_CONSUMER_SECRET,
28 | callbackURL: "/auth/twitter/redirect"
29 | },
30 | async (token, tokenSecret, profile, done) => {
31 | // find current user in UserModel
32 | const currentUser = await User.findOne({
33 | twitterId: profile._json.id_str
34 | });
35 | // create new user if the database doesn't have this user
36 | if (!currentUser) {
37 | const newUser = await new User({
38 | name: profile._json.name,
39 | screenName: profile._json.screen_name,
40 | twitterId: profile._json.id_str,
41 | profileImageUrl: profile._json.profile_image_url
42 | }).save();
43 | if (newUser) {
44 | done(null, newUser);
45 | }
46 | }
47 | done(null, currentUser);
48 | }
49 | )
50 | );
51 |
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | const cookieSession = require("cookie-session");
2 | const express = require("express");
3 | const app = express();
4 | const port = 4000;
5 | const passport = require("passport");
6 | const passportSetup = require("./config/passport-setup");
7 | const session = require("express-session");
8 | const authRoutes = require("./routes/auth-routes");
9 | const mongoose = require("mongoose");
10 | const keys = require("./config/keys");
11 | const cors = require("cors");
12 | const cookieParser = require("cookie-parser"); // parse cookie header
13 |
14 | // connect to mongodb
15 | mongoose.connect(keys.MONGODB_URI, () => {
16 | console.log("connected to mongo db");
17 | });
18 |
19 | app.use(
20 | cookieSession({
21 | name: "session",
22 | keys: [keys.COOKIE_KEY],
23 | maxAge: 24 * 60 * 60 * 100
24 | })
25 | );
26 |
27 | // parse cookies
28 | app.use(cookieParser());
29 |
30 | // initalize passport
31 | app.use(passport.initialize());
32 | // deserialize cookie from the browser
33 | app.use(passport.session());
34 |
35 | // set up cors to allow us to accept requests from our client
36 | app.use(
37 | cors({
38 | origin: "http://localhost:3000", // allow to server to accept request from different origin
39 | methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
40 | credentials: true // allow session cookie from browser to pass through
41 | })
42 | );
43 |
44 | // set up routes
45 | app.use("/auth", authRoutes);
46 |
47 | const authCheck = (req, res, next) => {
48 | if (!req.user) {
49 | res.status(401).json({
50 | authenticated: false,
51 | message: "user has not been authenticated"
52 | });
53 | } else {
54 | next();
55 | }
56 | };
57 |
58 | // if it's already login, send the profile response,
59 | // otherwise, send a 401 response that the user is not authenticated
60 | // authCheck before navigating to home page
61 | app.get("/", authCheck, (req, res) => {
62 | res.status(200).json({
63 | authenticated: true,
64 | message: "user successfully authenticated",
65 | user: req.user,
66 | cookies: req.cookies
67 | });
68 | });
69 |
70 | // connect react to nodejs express server
71 | app.listen(port, () => console.log(`Server is running on port ${port}!`));
72 |
--------------------------------------------------------------------------------
/server/models/user-model.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const Schema = mongoose.Schema;
3 |
4 | const userSchema = new Schema({
5 | name: String,
6 | screenName: String,
7 | twitterId: String,
8 | profileImageUrl: String
9 | });
10 |
11 | const User = mongoose.model("user", userSchema);
12 |
13 | module.exports = User;
14 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "twitter-oauth",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "body-parser": "^1.18.3",
13 | "cookie-parser": "^1.4.3",
14 | "cookie-session": "^2.0.0-beta.3",
15 | "cors": "^2.8.5",
16 | "express": "^4.16.4",
17 | "express-session": "^1.15.6",
18 | "mongoose": "^5.4.1",
19 | "passport": "^0.4.0",
20 | "passport-twitter": "^1.0.4"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/server/routes/auth-routes.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const passport = require("passport");
3 | const CLIENT_HOME_PAGE_URL = "http://localhost:3000";
4 |
5 | // when login is successful, retrieve user info
6 | router.get("/login/success", (req, res) => {
7 | if (req.user) {
8 | res.json({
9 | success: true,
10 | message: "user has successfully authenticated",
11 | user: req.user,
12 | cookies: req.cookies
13 | });
14 | }
15 | });
16 |
17 | // when login failed, send failed msg
18 | router.get("/login/failed", (req, res) => {
19 | res.status(401).json({
20 | success: false,
21 | message: "user failed to authenticate."
22 | });
23 | });
24 |
25 | // When logout, redirect to client
26 | router.get("/logout", (req, res) => {
27 | req.logout();
28 | res.redirect(CLIENT_HOME_PAGE_URL);
29 | });
30 |
31 | // auth with twitter
32 | router.get("/twitter", passport.authenticate("twitter"));
33 |
34 | // redirect to home page after successfully login via twitter
35 | router.get(
36 | "/twitter/redirect",
37 | passport.authenticate("twitter", {
38 | successRedirect: CLIENT_HOME_PAGE_URL,
39 | failureRedirect: "/auth/login/failed"
40 | })
41 | );
42 |
43 | module.exports = router;
44 |
--------------------------------------------------------------------------------
/server/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | accepts@~1.3.5:
6 | version "1.3.5"
7 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
8 | integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I=
9 | dependencies:
10 | mime-types "~2.1.18"
11 | negotiator "0.6.1"
12 |
13 | array-flatten@1.1.1:
14 | version "1.1.1"
15 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
16 | integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
17 |
18 | bluebird@3.5.1:
19 | version "3.5.1"
20 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
21 | integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==
22 |
23 | body-parser@1.18.3, body-parser@^1.18.3:
24 | version "1.18.3"
25 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
26 | integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=
27 | dependencies:
28 | bytes "3.0.0"
29 | content-type "~1.0.4"
30 | debug "2.6.9"
31 | depd "~1.1.2"
32 | http-errors "~1.6.3"
33 | iconv-lite "0.4.23"
34 | on-finished "~2.3.0"
35 | qs "6.5.2"
36 | raw-body "2.3.3"
37 | type-is "~1.6.16"
38 |
39 | bson@^1.1.1, bson@~1.1.1:
40 | version "1.1.1"
41 | resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.1.tgz#4330f5e99104c4e751e7351859e2d408279f2f13"
42 | integrity sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==
43 |
44 | bytes@3.0.0:
45 | version "3.0.0"
46 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
47 | integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
48 |
49 | content-disposition@0.5.2:
50 | version "0.5.2"
51 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
52 | integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
53 |
54 | content-type@~1.0.4:
55 | version "1.0.4"
56 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
57 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
58 |
59 | cookie-parser@^1.4.3:
60 | version "1.4.3"
61 | resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.3.tgz#0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5"
62 | integrity sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=
63 | dependencies:
64 | cookie "0.3.1"
65 | cookie-signature "1.0.6"
66 |
67 | cookie-session@^2.0.0-beta.3:
68 | version "2.0.0-beta.3"
69 | resolved "https://registry.yarnpkg.com/cookie-session/-/cookie-session-2.0.0-beta.3.tgz#4e446bd9f85bd7e27d3e226f4e99af12011a4386"
70 | integrity sha512-zyqm5tA0z9yMEB/xyP7lnRnqp8eLR2e0dap+9+rBwVigla9yPKn8XTL1jJymog8xjfrowqW2o5LUjixQChkqrw==
71 | dependencies:
72 | cookies "0.7.1"
73 | debug "3.1.0"
74 | on-headers "~1.0.1"
75 | safe-buffer "5.1.1"
76 |
77 | cookie-signature@1.0.6:
78 | version "1.0.6"
79 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
80 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
81 |
82 | cookie@0.3.1:
83 | version "0.3.1"
84 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
85 | integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
86 |
87 | cookies@0.7.1:
88 | version "0.7.1"
89 | resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b"
90 | integrity sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=
91 | dependencies:
92 | depd "~1.1.1"
93 | keygrip "~1.0.2"
94 |
95 | cors@^2.8.5:
96 | version "2.8.5"
97 | resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
98 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
99 | dependencies:
100 | object-assign "^4"
101 | vary "^1"
102 |
103 | crc@3.4.4:
104 | version "3.4.4"
105 | resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b"
106 | integrity sha1-naHpgOO9RPxck79as9ozeNheRms=
107 |
108 | debug@2.6.9:
109 | version "2.6.9"
110 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
111 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
112 | dependencies:
113 | ms "2.0.0"
114 |
115 | debug@3.1.0:
116 | version "3.1.0"
117 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
118 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
119 | dependencies:
120 | ms "2.0.0"
121 |
122 | depd@~1.1.1, depd@~1.1.2:
123 | version "1.1.2"
124 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
125 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
126 |
127 | destroy@~1.0.4:
128 | version "1.0.4"
129 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
130 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
131 |
132 | ee-first@1.1.1:
133 | version "1.1.1"
134 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
135 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
136 |
137 | encodeurl@~1.0.2:
138 | version "1.0.2"
139 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
140 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
141 |
142 | escape-html@~1.0.3:
143 | version "1.0.3"
144 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
145 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
146 |
147 | etag@~1.8.1:
148 | version "1.8.1"
149 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
150 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
151 |
152 | express-session@^1.15.6:
153 | version "1.15.6"
154 | resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.6.tgz#47b4160c88f42ab70fe8a508e31cbff76757ab0a"
155 | integrity sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==
156 | dependencies:
157 | cookie "0.3.1"
158 | cookie-signature "1.0.6"
159 | crc "3.4.4"
160 | debug "2.6.9"
161 | depd "~1.1.1"
162 | on-headers "~1.0.1"
163 | parseurl "~1.3.2"
164 | uid-safe "~2.1.5"
165 | utils-merge "1.0.1"
166 |
167 | express@^4.16.4:
168 | version "4.16.4"
169 | resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e"
170 | integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==
171 | dependencies:
172 | accepts "~1.3.5"
173 | array-flatten "1.1.1"
174 | body-parser "1.18.3"
175 | content-disposition "0.5.2"
176 | content-type "~1.0.4"
177 | cookie "0.3.1"
178 | cookie-signature "1.0.6"
179 | debug "2.6.9"
180 | depd "~1.1.2"
181 | encodeurl "~1.0.2"
182 | escape-html "~1.0.3"
183 | etag "~1.8.1"
184 | finalhandler "1.1.1"
185 | fresh "0.5.2"
186 | merge-descriptors "1.0.1"
187 | methods "~1.1.2"
188 | on-finished "~2.3.0"
189 | parseurl "~1.3.2"
190 | path-to-regexp "0.1.7"
191 | proxy-addr "~2.0.4"
192 | qs "6.5.2"
193 | range-parser "~1.2.0"
194 | safe-buffer "5.1.2"
195 | send "0.16.2"
196 | serve-static "1.13.2"
197 | setprototypeof "1.1.0"
198 | statuses "~1.4.0"
199 | type-is "~1.6.16"
200 | utils-merge "1.0.1"
201 | vary "~1.1.2"
202 |
203 | finalhandler@1.1.1:
204 | version "1.1.1"
205 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
206 | integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==
207 | dependencies:
208 | debug "2.6.9"
209 | encodeurl "~1.0.2"
210 | escape-html "~1.0.3"
211 | on-finished "~2.3.0"
212 | parseurl "~1.3.2"
213 | statuses "~1.4.0"
214 | unpipe "~1.0.0"
215 |
216 | forwarded@~0.1.2:
217 | version "0.1.2"
218 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
219 | integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
220 |
221 | fresh@0.5.2:
222 | version "0.5.2"
223 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
224 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
225 |
226 | http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
227 | version "1.6.3"
228 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
229 | integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=
230 | dependencies:
231 | depd "~1.1.2"
232 | inherits "2.0.3"
233 | setprototypeof "1.1.0"
234 | statuses ">= 1.4.0 < 2"
235 |
236 | iconv-lite@0.4.23:
237 | version "0.4.23"
238 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
239 | integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==
240 | dependencies:
241 | safer-buffer ">= 2.1.2 < 3"
242 |
243 | inherits@2.0.3:
244 | version "2.0.3"
245 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
246 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
247 |
248 | ipaddr.js@1.8.0:
249 | version "1.8.0"
250 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
251 | integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4=
252 |
253 | kareem@2.3.1:
254 | version "2.3.1"
255 | resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.1.tgz#def12d9c941017fabfb00f873af95e9c99e1be87"
256 | integrity sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==
257 |
258 | keygrip@~1.0.2:
259 | version "1.0.3"
260 | resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.3.tgz#399d709f0aed2bab0a059e0cdd3a5023a053e1dc"
261 | integrity sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==
262 |
263 | media-typer@0.3.0:
264 | version "0.3.0"
265 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
266 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
267 |
268 | merge-descriptors@1.0.1:
269 | version "1.0.1"
270 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
271 | integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
272 |
273 | methods@~1.1.2:
274 | version "1.1.2"
275 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
276 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
277 |
278 | mime-db@~1.37.0:
279 | version "1.37.0"
280 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8"
281 | integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==
282 |
283 | mime-types@~2.1.18:
284 | version "2.1.21"
285 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96"
286 | integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==
287 | dependencies:
288 | mime-db "~1.37.0"
289 |
290 | mime@1.4.1:
291 | version "1.4.1"
292 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
293 | integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
294 |
295 | mongodb@3.3.2:
296 | version "3.3.2"
297 | resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.3.2.tgz#ff086b5f552cf07e24ce098694210f3d42d668b2"
298 | integrity sha512-fqJt3iywelk4yKu/lfwQg163Bjpo5zDKhXiohycvon4iQHbrfflSAz9AIlRE6496Pm/dQKQK5bMigdVo2s6gBg==
299 | dependencies:
300 | bson "^1.1.1"
301 | require_optional "^1.0.1"
302 | safe-buffer "^5.1.2"
303 |
304 | mongoose-legacy-pluralize@1.0.2:
305 | version "1.0.2"
306 | resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4"
307 | integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==
308 |
309 | mongoose@^5.4.1:
310 | version "5.7.5"
311 | resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.7.5.tgz#b787b47216edf62036aa358c3ef0f1869c46cdc2"
312 | integrity sha512-BZ4FxtnbTurc/wcm/hLltLdI4IDxo4nsE0D9q58YymTdZwreNzwO62CcjVtaHhmr8HmJtOInp2W/T12FZaMf8g==
313 | dependencies:
314 | bson "~1.1.1"
315 | kareem "2.3.1"
316 | mongodb "3.3.2"
317 | mongoose-legacy-pluralize "1.0.2"
318 | mpath "0.6.0"
319 | mquery "3.2.2"
320 | ms "2.1.2"
321 | regexp-clone "1.0.0"
322 | safe-buffer "5.1.2"
323 | sift "7.0.1"
324 | sliced "1.0.1"
325 |
326 | mpath@0.6.0:
327 | version "0.6.0"
328 | resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.6.0.tgz#aa922029fca4f0f641f360e74c5c1b6a4c47078e"
329 | integrity sha512-i75qh79MJ5Xo/sbhxrDrPSEG0H/mr1kcZXJ8dH6URU5jD/knFxCVqVC/gVSW7GIXL/9hHWlT9haLbCXWOll3qw==
330 |
331 | mquery@3.2.2:
332 | version "3.2.2"
333 | resolved "https://registry.yarnpkg.com/mquery/-/mquery-3.2.2.tgz#e1383a3951852ce23e37f619a9b350f1fb3664e7"
334 | integrity sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==
335 | dependencies:
336 | bluebird "3.5.1"
337 | debug "3.1.0"
338 | regexp-clone "^1.0.0"
339 | safe-buffer "5.1.2"
340 | sliced "1.0.1"
341 |
342 | ms@2.0.0:
343 | version "2.0.0"
344 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
345 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
346 |
347 | ms@2.1.2:
348 | version "2.1.2"
349 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
350 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
351 |
352 | negotiator@0.6.1:
353 | version "0.6.1"
354 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
355 | integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
356 |
357 | oauth@0.9.x:
358 | version "0.9.15"
359 | resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
360 | integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
361 |
362 | object-assign@^4:
363 | version "4.1.1"
364 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
365 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
366 |
367 | on-finished@~2.3.0:
368 | version "2.3.0"
369 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
370 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
371 | dependencies:
372 | ee-first "1.1.1"
373 |
374 | on-headers@~1.0.1:
375 | version "1.0.1"
376 | resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
377 | integrity sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=
378 |
379 | parseurl@~1.3.2:
380 | version "1.3.2"
381 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
382 | integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=
383 |
384 | passport-oauth1@1.x.x:
385 | version "1.1.0"
386 | resolved "https://registry.yarnpkg.com/passport-oauth1/-/passport-oauth1-1.1.0.tgz#a7de988a211f9cf4687377130ea74df32730c918"
387 | integrity sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=
388 | dependencies:
389 | oauth "0.9.x"
390 | passport-strategy "1.x.x"
391 | utils-merge "1.x.x"
392 |
393 | passport-strategy@1.x.x:
394 | version "1.0.0"
395 | resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
396 | integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=
397 |
398 | passport-twitter@^1.0.4:
399 | version "1.0.4"
400 | resolved "https://registry.yarnpkg.com/passport-twitter/-/passport-twitter-1.0.4.tgz#01a799e1f760bf2de49f2ba5fba32282f18932d7"
401 | integrity sha1-AaeZ4fdgvy3knyul+6MigvGJMtc=
402 | dependencies:
403 | passport-oauth1 "1.x.x"
404 | xtraverse "0.1.x"
405 |
406 | passport@^0.4.0:
407 | version "0.4.0"
408 | resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.0.tgz#c5095691347bd5ad3b5e180238c3914d16f05811"
409 | integrity sha1-xQlWkTR71a07XhgCOMORTRbwWBE=
410 | dependencies:
411 | passport-strategy "1.x.x"
412 | pause "0.0.1"
413 |
414 | path-to-regexp@0.1.7:
415 | version "0.1.7"
416 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
417 | integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
418 |
419 | pause@0.0.1:
420 | version "0.0.1"
421 | resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
422 | integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=
423 |
424 | proxy-addr@~2.0.4:
425 | version "2.0.4"
426 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
427 | integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==
428 | dependencies:
429 | forwarded "~0.1.2"
430 | ipaddr.js "1.8.0"
431 |
432 | qs@6.5.2:
433 | version "6.5.2"
434 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
435 | integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
436 |
437 | random-bytes@~1.0.0:
438 | version "1.0.0"
439 | resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
440 | integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=
441 |
442 | range-parser@~1.2.0:
443 | version "1.2.0"
444 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
445 | integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
446 |
447 | raw-body@2.3.3:
448 | version "2.3.3"
449 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
450 | integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==
451 | dependencies:
452 | bytes "3.0.0"
453 | http-errors "1.6.3"
454 | iconv-lite "0.4.23"
455 | unpipe "1.0.0"
456 |
457 | regexp-clone@1.0.0, regexp-clone@^1.0.0:
458 | version "1.0.0"
459 | resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-1.0.0.tgz#222db967623277056260b992626354a04ce9bf63"
460 | integrity sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==
461 |
462 | require_optional@^1.0.1:
463 | version "1.0.1"
464 | resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
465 | integrity sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==
466 | dependencies:
467 | resolve-from "^2.0.0"
468 | semver "^5.1.0"
469 |
470 | resolve-from@^2.0.0:
471 | version "2.0.0"
472 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
473 | integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=
474 |
475 | safe-buffer@5.1.1:
476 | version "5.1.1"
477 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
478 | integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==
479 |
480 | safe-buffer@5.1.2, safe-buffer@^5.1.2:
481 | version "5.1.2"
482 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
483 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
484 |
485 | "safer-buffer@>= 2.1.2 < 3":
486 | version "2.1.2"
487 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
488 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
489 |
490 | semver@^5.1.0:
491 | version "5.6.0"
492 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
493 | integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
494 |
495 | send@0.16.2:
496 | version "0.16.2"
497 | resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
498 | integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
499 | dependencies:
500 | debug "2.6.9"
501 | depd "~1.1.2"
502 | destroy "~1.0.4"
503 | encodeurl "~1.0.2"
504 | escape-html "~1.0.3"
505 | etag "~1.8.1"
506 | fresh "0.5.2"
507 | http-errors "~1.6.2"
508 | mime "1.4.1"
509 | ms "2.0.0"
510 | on-finished "~2.3.0"
511 | range-parser "~1.2.0"
512 | statuses "~1.4.0"
513 |
514 | serve-static@1.13.2:
515 | version "1.13.2"
516 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
517 | integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==
518 | dependencies:
519 | encodeurl "~1.0.2"
520 | escape-html "~1.0.3"
521 | parseurl "~1.3.2"
522 | send "0.16.2"
523 |
524 | setprototypeof@1.1.0:
525 | version "1.1.0"
526 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
527 | integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
528 |
529 | sift@7.0.1:
530 | version "7.0.1"
531 | resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08"
532 | integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==
533 |
534 | sliced@1.0.1:
535 | version "1.0.1"
536 | resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41"
537 | integrity sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=
538 |
539 | "statuses@>= 1.4.0 < 2":
540 | version "1.5.0"
541 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
542 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
543 |
544 | statuses@~1.4.0:
545 | version "1.4.0"
546 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
547 | integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
548 |
549 | type-is@~1.6.16:
550 | version "1.6.16"
551 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
552 | integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==
553 | dependencies:
554 | media-typer "0.3.0"
555 | mime-types "~2.1.18"
556 |
557 | uid-safe@~2.1.5:
558 | version "2.1.5"
559 | resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
560 | integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==
561 | dependencies:
562 | random-bytes "~1.0.0"
563 |
564 | unpipe@1.0.0, unpipe@~1.0.0:
565 | version "1.0.0"
566 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
567 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
568 |
569 | utils-merge@1.0.1, utils-merge@1.x.x:
570 | version "1.0.1"
571 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
572 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
573 |
574 | vary@^1, vary@~1.1.2:
575 | version "1.1.2"
576 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
577 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
578 |
579 | xmldom@0.1.x:
580 | version "0.1.27"
581 | resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
582 | integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk=
583 |
584 | xtraverse@0.1.x:
585 | version "0.1.0"
586 | resolved "https://registry.yarnpkg.com/xtraverse/-/xtraverse-0.1.0.tgz#b741bad018ef78d8a9d2e83ade007b3f7959c732"
587 | integrity sha1-t0G60BjveNip0ug63gB7P3lZxzI=
588 | dependencies:
589 | xmldom "0.1.x"
590 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 |
--------------------------------------------------------------------------------