Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"presets":[
"es2015", "react"
]
}
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GITHUB_KEY=your-client-id-here
GITHUB_SECRET=your-client-secret-here
SLACK_CLIENT_ID=your-client-id-here
SLACK_CLIENT_SECRET=your-client-secret-here
callbackURL=web-site-base-url
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/data/

client/public/app.js
client/public/app.css

# Node build artifacts
node_modules
npm-debug.log
Expand Down
27 changes: 5 additions & 22 deletions client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,14 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<link rel="stylesheet" href="/app.css">
<title>React App</title>
</head>
<body>
<body>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start`.
To create a production bundle, use `npm run build`.
-->
<script src="/app.js"></script>
</body>
</html>
51 changes: 34 additions & 17 deletions client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class App extends Component {
fetching: true,
viewingJobs: false,
resources: null,
loggedIn: true,
loggedIn: false,
username: null,
jobs: [{"jobPosition": "position1", "companyName": "name1", "dateApplied":"01/dd/yy"},
{"jobPosition": "position2", "companyName": "name2", "dateApplied":"02/dd/yy"},
Expand All @@ -22,9 +22,30 @@ class App extends Component {
this.viewJobs = this.viewJobs.bind(this);
this.viewResources = this.viewResources.bind(this);
this.logOut = this.logOut.bind(this);
this.isAuth = this.isAuth.bind(this);
}

isAuth() {
fetch('/isauth', { method: 'GET', credentials: 'include'})
.then(response => {
if (!response.ok) {
throw new Error('not logged in');
}
return response.json();
})
.then(json => {
this.setState({
loggedIn: true
});
}).catch(e => {
this.setState({
loggedIn: false
});
});
}

componentDidMount() {
this.isAuth();
fetch('/api')
.then(response => {
if (!response.ok) {
Expand All @@ -33,7 +54,6 @@ class App extends Component {
return response.json();
})
.then(json => {
console.log(json.message);
this.setState({
resources: json.message,
fetching: false
Expand All @@ -59,9 +79,12 @@ class App extends Component {
}

logOut() {
this.setState({
loggedIn: false
});
fetch('/logout', { method: 'GET', credentials: 'include'})
.then(json => {
this.setState({
loggedIn: false
});
})
}

render() {
Expand Down Expand Up @@ -90,20 +113,14 @@ class App extends Component {
</div>
)
}
<div>
<a href="/github">Use Github </a>
<button onClick={this.logOut}>logout</button>
<span>logged in state: {this.state.loggedIn ? " In " : " Out "}</span>
</div>
</div>
);
}
}

/*class ResourceModal extends React.Component {
render() {
return (
<div>

</div>
);
}
}*/


module.exports = App;
module.exports = App;
27 changes: 21 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
{
"name": "codepdix",
"name": "codeploy",
"version": "1.0.0",
"description": "Codeploy of resources for individuals job seeking and learning web development.",
"engines": {
"node": "6.9.x"
},
"scripts": {
"start": "concurrently \"npm run server\" \"npm run client\"",
"server": "babel-node server/index.js",
"client": "babel-node client/start.js",
"start": "nodemon --use-strict server/index.js",
"bundle": "webpack",
"heroku-postbuild": "cd client/ && npm install --only=dev && npm install && npm run build"
},
"cacheDirectories": [
Expand All @@ -18,8 +17,14 @@
"dependencies": {
"babel-cli": "6.14.0",
"babel-core": "6.14.0",
"dotenv": "^4.0.0",
"express": "^4.14.1",
"mongoose": "^4.10.2"
"express-session": "^1.15.3",
"mongoose": "^4.10.2",
"passport": "^0.3.2",
"passport-github2": "^0.1.10",
"passport-session": "^1.0.2",
"passport-slack": "0.0.7"
},
"repository": {
"type": "git",
Expand All @@ -33,6 +38,16 @@
],
"license": "MIT",
"devDependencies": {
"concurrently": "^3.4.0"
"babel-core": "^6.14.0",
"babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"concurrently": "^3.4.0",
"css-loader": "^0.28.3",
"extract-text-webpack-plugin": "^2.1.0",
"nodemon": "^1.11.0",
"style-loader": "^0.18.1",
"webpack": "^2.6.1",
"webpack-combine-loaders": "^2.0.3"
}
}
51 changes: 51 additions & 0 deletions server/auth/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
let passport = require('passport');
let GitHubStrategy = require('passport-github2').Strategy;
let User = require('../models/user');
require('dotenv').config()

module.exports = function () {
passport.serializeUser(function (user, done) {
done(null, user._id);
});

passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});

passport.use(new GitHubStrategy({
clientID: process.env.GITHUB_KEY,
clientSecret: process.env.GITHUB_SECRET,
callbackURL: process.env.callbackURL + '/github/callback'
},
function (token, refreshToken, profile, done) {
process.nextTick(function () {
User.findOne({ 'id': profile.id }, function (err, user) {
if (err) {
return done(err);
}

if (user) {
return done(null, user);
} else {
let newUser = new User();
newUser.token = token;
newUser.provider = 'github';

newUser.id = profile.id;
newUser.username = profile.username;
newUser.displayName = profile.displayName;

newUser.save(function (err) {
if (err) {
throw err;
}

return done(null, newUser);
});
}
});
});
}));
};
1 change: 0 additions & 1 deletion server/controllers/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ module.exports.remove = (req, res) => {
});
};


module.exports.index = (req, res) => {
res.set('Content-Type', 'application/json');
let text = `Hello from the backend server @ ${new Date()}`;
Expand Down
24 changes: 19 additions & 5 deletions server/index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
const express = require('express');
const path = require('path');
const app = express();
let passport = require('passport');
let github = require('./auth/github');
var session = require('express-session')

let mongoose = require('mongoose');

let userCtrl = require('./controllers/user'),
resourceCtrl = require('./controllers/resource'),
jobCtrl = require('./controllers/job');

const PORT = process.env.PORT || 3001;
let authRoutes = require('./routes/auth');

const PORT = process.env.PORT || 3000;

// Connect mongoose to our local database
let dbUri = process.env.MONGOLAB_URI || 'mongodb://localhost/codeploy';
mongoose.connect(dbUri);

// Priority serve any static files.
app.use(express.static(path.resolve(__dirname, '../client/build')));
app.use(express.static('./client/public'));

app.use(session({ secret: 'modern art', resave: true, saveUninitialized: true }));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
github(passport);

app.get('/api', resourceCtrl.index);

Expand All @@ -28,11 +40,13 @@ app.get('/api/jobs/:id', jobCtrl.one);
app.post('/api/jobs', jobCtrl.new);
app.post('/api/jobs/:id', jobCtrl.update);

app.use('/', authRoutes);

// All remaining requests return the React app, so it can handle routing.
app.get('*', function(request, response) {
response.sendFile(path.resolve(__dirname, '../client/build', 'index.html'));
response.sendFile(path.resolve(__dirname, '../client/public', 'index.html'));
});

app.listen(PORT, function () {
console.log(`Listening on port ${PORT}`);
});
});
6 changes: 4 additions & 2 deletions server/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ let mongoose = require('mongoose');
let Schema = mongoose.Schema;

let userSchema = new Schema({
id: String,
token: String,
provider: String,
username: String,
slack_id: String,
github_id: String,
displayName: String,
created_at: Date,
updated_at: Date
});
Expand Down
61 changes: 61 additions & 0 deletions server/routes/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
var express = require('express');
let passport = require('passport');
var router = express.Router();
var path = require('path');

// Use passport.authenticate() as route middleware to authenticate the
// request. The first step in GitHub authentication will involve redirecting
// the user to github.com. After authorization, GitHub will redirect the user
// back to this application at /auth/github/callback
router.get('/github',
passport.authenticate('github', { scope: [ 'user:email' ] }),
function(req, res){
}
);

router.get('/github/callback',
passport.authenticate('github', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
}
);

router.get('/logout', function(req, res) {
let user = req.user;
req.logout();
res.status(200).json({
status: 'logout successful!'
});
});

var isAuthenticated = function(req,res,next){
if(req.user)
return next();
else
return res.status(401).json({
error: 'User not authenticated'
})
}

function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
// req.user is available for use here
return next(); }

// denied. redirect to login
res.redirect('/')
}

router.get('/isauth', function(req, res){
if (req.isAuthenticated()) {
res.status(200).json({
status: 'Login successful!'
});
} else {
res.status(401).json({
status: 'User not authenticated'
});
}
});

module.exports = router;
Loading