Skip to content

Instantly share code, notes, and snippets.

@sailsinaction
Last active May 12, 2016 18:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sailsinaction/c44232a4d7dfe2c22cde to your computer and use it in GitHub Desktop.
Save sailsinaction/c44232a4d7dfe2c22cde to your computer and use it in GitHub Desktop.
Chapter 10 - Gists
.d8888b. 888 888 d888 .d8888b. .d8888b. d8b 888
d88P Y88b 888 888 d8888 d88P Y88b d88P Y88b Y8P 888
888 888 888 888 888 888 888 888 888 888
888 88888b. 8888b. 88888b. 888888 .d88b. 888d888 888 888 888 888 888 .d8888b 888888 .d8888b
888 888 "88b "88b 888 "88b 888 d8P Y8b 888P" 888 888 888 888 88888 888 88K 888 88K
888 888 888 888 .d888888 888 888 888 88888888 888 888 888 888 888888 888 888 888 "Y8888b. 888 "Y8888b.
Y88b d88P 888 888 888 888 888 d88P Y88b. Y8b. 888 888 Y88b d88P Y88b d88P 888 X88 Y88b. X88
"Y8888P" 888 888 "Y888888 88888P" "Y888 "Y8888 888 8888888 "Y8888P" "Y8888P88 888 88888P' "Y888 88888P'
888
888
888
module.exports.routes = {
/*************************************************************
* JSON API *
*************************************************************/
'PUT /login': 'UserController.login',
'GET /logout': 'UserController.logout',
'GET /video': 'VideoController.find',
'POST /video': 'VideoController.create',
/*************************************************************
* Server-rendered HTML Pages *
*************************************************************/
'GET /': 'PageController.showHomePage',
'GET /videos': 'PageController.showVideosPage',
'GET /administration': 'PageController.showAdminPage',
'GET /profile': 'PageController.showProfilePage',
'GET /edit-profile': 'PageController.showEditProfilePage',
'GET /restore-profile': 'PageController.showRestorePage',
'GET /signup': 'PageController.showSignupPage',
};
module.exports.routes = {
/*************************************************************
* JSON API *
*************************************************************/
'PUT /login': 'UserController.login',
'GET /logout': 'UserController.logout',
'GET /video': 'VideoController.find',
'POST /video': 'VideoController.create',
'POST /user/signup': 'UserController.signup',
'PUT /user/removeProfile/:id': 'UserController.removeProfile',
'PUT /user/restoreProfile': 'UserController.restoreProfile',
'PUT /user/restoreGravatarURL': 'UserController.restoreGravatarURL',
'PUT /user/updateProfile/:id': 'UserController.updateProfile',
'PUT /user/changePassword': 'UserController.changePassword',
'GET /user/adminUsers': 'UserController.adminUsers',
'PUT /user/updateAdmin/:id': 'UserController.updateAdmin',
'PUT /user/updateBanned/:id': 'UserController.updateBanned',
'PUT /user/updateDeleted/:id': 'UserController.updateDeleted',
/*************************************************************
* Server-rendered HTML Pages *
*************************************************************/
'GET /': 'PageController.showHomePage',
'GET /videos': 'PageController.showVideosPage',
'GET /administration': 'PageController.showAdminPage',
'GET /profile': 'PageController.showProfilePage',
'GET /edit-profile': 'PageController.showEditProfilePage',
'GET /restore-profile': 'PageController.showRestorePage',
'GET /signup': 'PageController.showSignupPage',
};
/**
* Blueprint API Configuration
* (sails.config.blueprints)
*
* These settings are for the global configuration of blueprint routes and
* request options (which impact the behavior of blueprint actions).
*
* You may also override any of these settings on a per-controller basis
* by defining a '_config' key in your controller defintion, and assigning it
* a configuration object with overrides for the settings in this file.
* A lot of the configuration options below affect so-called "CRUD methods",
* or your controllers' `find`, `create`, `update`, and `destroy` actions.
*
* It's important to realize that, even if you haven't defined these yourself, as long as
* a model exists with the same name as the controller, Sails will respond with built-in CRUD
* logic in the form of a JSON API, including support for sort, pagination, and filtering.
*
* For more information on the blueprint API, check out:
* http://sailsjs.org/#!/documentation/reference/blueprint-api
*
* For more information on the settings in this file, see:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.blueprints.html
*
*/
module.exports.blueprints = {
/***************************************************************************
* *
* Action routes speed up the backend development workflow by *
* eliminating the need to manually bind routes. When enabled, GET, POST, *
* PUT, and DELETE routes will be generated for every one of a controller's *
* actions. *
* *
* If an `index` action exists, additional naked routes will be created for *
* it. Finally, all `actions` blueprints support an optional path *
* parameter, `id`, for convenience. *
* *
* `actions` are enabled by default, and can be OK for production-- *
* however, if you'd like to continue to use controller/action autorouting *
* in a production deployment, you must take great care not to *
* inadvertently expose unsafe/unintentional controller logic to GET *
* requests. *
* *
***************************************************************************/
actions: false,
/***************************************************************************
* *
* RESTful routes (`sails.config.blueprints.rest`) *
* *
* REST blueprints are the automatically generated routes Sails uses to *
* expose a conventional REST API on top of a controller's `find`, *
* `create`, `update`, and `destroy` actions. *
* *
* For example, a BoatController with `rest` enabled generates the *
* following routes: *
* ::::::::::::::::::::::::::::::::::::::::::::::::::::::: *
* GET /boat -> BoatController.find *
* GET /boat/:id -> BoatController.findOne *
* POST /boat -> BoatController.create *
* PUT /boat/:id -> BoatController.update *
* DELETE /boat/:id -> BoatController.destroy *
* *
* `rest` blueprint routes are enabled by default, and are suitable for use *
* in a production scenario, as long you take standard security precautions *
* (combine w/ policies, etc.) *
* *
***************************************************************************/
rest: false,
/***************************************************************************
* *
* Shortcut routes are simple helpers to provide access to a *
* controller's CRUD methods from your browser's URL bar. When enabled, *
* GET, POST, PUT, and DELETE routes will be generated for the *
* controller's`find`, `create`, `update`, and `destroy` actions. *
* *
* `shortcuts` are enabled by default, but should be disabled in *
* production. *
* *
***************************************************************************/
shortcuts: false,
/***************************************************************************
* *
* An optional mount path for all blueprint routes on a controller, *
* including `rest`, `actions`, and `shortcuts`. This allows you to take *
* advantage of blueprint routing, even if you need to namespace your API *
* methods. *
* *
* (NOTE: This only applies to blueprint autoroutes, not manual routes from *
* `sails.config.routes`) *
* *
***************************************************************************/
// prefix: '',
/***************************************************************************
* *
* An optional mount path for all REST blueprint routes on a controller. *
* And it do not include `actions` and `shortcuts` routes. *
* This allows you to take advantage of REST blueprint routing, *
* even if you need to namespace your RESTful API methods *
* *
***************************************************************************/
// restPrefix: '',
/***************************************************************************
* *
* Whether to pluralize controller names in blueprint routes. *
* *
* (NOTE: This only applies to blueprint autoroutes, not manual routes from *
* `sails.config.routes`) *
* *
* For example, REST blueprints for `FooController` with `pluralize` *
* enabled: *
* GET /foos/:id? *
* POST /foos *
* PUT /foos/:id? *
* DELETE /foos/:id? *
* *
***************************************************************************/
// pluralize: false,
/***************************************************************************
* *
* Whether the blueprint controllers should populate model fetches with *
* data from other models which are linked by associations *
* *
* If you have a lot of data in one-to-many associations, leaving this on *
* may result in very heavy api calls *
* *
***************************************************************************/
// populate: true,
/****************************************************************************
* *
* Whether to run Model.watch() in the find and findOne blueprint actions. *
* Can be overridden on a per-model basis. *
* *
****************************************************************************/
// autoWatch: true,
/****************************************************************************
* *
* The default number of records to show in the response from a "find" *
* action. Doubles as the default size of populated arrays if populate is *
* true. *
* *
****************************************************************************/
// defaultLimit: 30
};
module.exports = function isLoggedIn(req, res, next) {
if (req.session.userId) {
return next();
}
if (req.wantsJSON) {
return res.forbidden('You are not permitted to perform this action.');
}
return res.redirect('/');
};
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
module.exports = function isLoggedOut(req, res, next) {
if (!req.session.userId) {
return next();
}
if (req.wantsJSON) {
return res.forbidden('You are not permitted to perform this action.');
}
return res.redirect('/');
};
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut']
},
PageController: {
showSignupPage: ['isLoggedOut']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut'],
logout: ['isLoggedIn']
},
PageController: {
showSignupPage: ['isLoggedOut'],
showAdminPage: ['isLoggedIn'],
showProfilePage: ['isLoggedIn']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
module.exports = function isAdmin(req, res, next) {
// If the user agent DOES NOT have a user id stored in their session...
if (!req.session.userId) {
if (req.wantsJSON) {
return res.forbidden('You are not permitted to perform this action.');
}
return res.redirect('/');
}
// Search for a user based upon the user record id in the session
User.findOne(req.session.userId).exec(function(err, foundUser){
// Handle any errors from the findOne query.
if (err) return res.negotiate(err);
// If the user id associated with this session does not correspond
// with a User record in the database...
if (!foundUser) {
if (req.wantsJSON) {
return res.forbidden('You are not permitted to perform this action.');
}
return res.redirect('/');
}
// If the found user record's admin property is true go to the action
if (foundUser.admin) {
return next();
// Respond with forbidden or redirect based upon the user-agent requirements
} else {
if (req.wantsJSON) {
return res.forbidden('You are not permitted to perform this action.');
}
return res.redirect('/');
}
});
};
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut'],
logout: ['isLoggedIn']
},
PageController: {
showSignupPage: ['isLoggedOut'],
showAdminPage: ['isLoggedIn', 'isAdmin'],
showProfilePage: ['isLoggedIn']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut'],
logout: ['isLoggedIn'],
removeProfile: ['isLoggedIn']
},
PageController: {
showSignupPage: ['isLoggedOut'],
showAdminPage: ['isLoggedIn', 'isAdmin'],
showProfilePage: ['isLoggedIn'],
showEditProfilePage: ['isLoggedIn']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
/**
* UserController
*
* @description :: Server-side logic for managing users
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
var Emailaddresses = require('machinepack-emailaddresses');
var Passwords = require('machinepack-passwords');
var Gravatar = require('machinepack-gravatar');
module.exports = {
login: function (req, res) {
User.findOne({
or : [
{ email: req.param('email') },
{ username: req.param('username') }
]
}, function foundUser(err, user) {
if (err) return res.negotiate(err);
if (!user) return res.notFound();
Passwords.checkPassword({
passwordAttempt: req.param('password'),
encryptedPassword: user.encryptedPassword
}).exec({
error: function (err){
return res.negotiate(err);
},
incorrect: function (){
return res.notFound();
},
success: function (){
if (user.deleted) {
return res.forbidden("'Your our account has been deleted. Please visit http://brushfire.io/restore to restore your account.'");
}
if (user.banned) {
return res.forbidden("'Your our account has been banned, most likely for adding dog videos in violation of the Terms of Service. Please contact Chad or his mother.'");
}
// Login user
req.session.userId = user.id;
// console.log('req.session.userId: ', req.session.userId);
// Respond with a 200 status
return res.ok();
}
});
});
},
logout: function (req, res) {
if (!req.session.userId) return res.redirect('/');
User.findOne(req.session.userId, function foundUser(err, user) {
if (err) return res.negotiate(err);
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists.');
return res.redirect('/');
}
// Logout user
req.session.userId = null;
return res.redirect('/');
});
},
signup: function(req, res) {
if (_.isUndefined(req.param('email'))) {
return res.badRequest('An email address is required!');
}
if (_.isUndefined(req.param('password'))) {
return res.badRequest('A password is required!');
}
if (req.param('password').length < 6) {
return res.badRequest('Password must be at least 6 characters!');
}
if (_.isUndefined(req.param('username'))) {
return res.badRequest('A username is required!');
}
// username must be at least 6 characters
if (req.param('username').length < 6) {
return res.badRequest('Username must be at least 6 characters!');
}
// Username must contain only numbers and letters.
if (!_.isString(req.param('username')) || req.param('username').match(/[^a-z0-9]/i)) {
return res.badRequest('Invalid username: must consist of numbers and letters only.');
}
Emailaddresses.validate({
string: req.param('email'),
}).exec({
// An unexpected error occurred.
error: function(err) {
return res.serverError(err);
},
// The provided string is not an email address.
invalid: function() {
return res.badRequest('Doesn\'t look like an email address to me!');
},
// OK.
success: function() {
Passwords.encryptPassword({
password: req.param('password'),
}).exec({
error: function(err) {
return res.serverError(err);
},
success: function(result) {
var options = {};
try {
options.gravatarURL = Gravatar.getImageUrl({
emailAddress: req.param('email')
}).execSync();
} catch (err) {
return res.serverError(err);
}
options.email = req.param('email');
options.username = req.param('username');
options.encryptedPassword = result;
options.deleted = false;
options.admin = false;
options.banned = false;
User.create(options).exec(function(err, createdUser) {
if (err) {
console.log('the error is: ', err.invalidAttributes);
if (err.invalidAttributes && err.invalidAttributes.email && err.invalidAttributes.email[0] && err.invalidAttributes.email[0].rule === 'unique') {
// return res.send(409, 'Email address is already taken by another user, please try again.');
return res.alreadyInUse(err);
}
if (err.invalidAttributes && err.invalidAttributes.username && err.invalidAttributes.username[0] && err.invalidAttributes.username[0].rule === 'unique') {
// return res.send(409, 'Username is already taken by another user, please try again.');
return res.alreadyInUse(err);
}
return res.negotiate(err);
}
// Log the user in
req.session.userId = createdUser.id;
return res.json(createdUser);
});
}
});
}
});
},
profile: function(req, res) {
// Try to look up user using the provided email address
User.findOne(req.param('id')).exec(function foundUser(err, user) {
// Handle error
if (err) return res.negotiate(err);
// Handle no user being found
if (!user) return res.notFound();
// Return the user
return res.json(user);
});
},
delete: function(req, res) {
if (!req.param('id')) {
return res.badRequest('id is a required parameter.');
}
User.destroy({
id: req.param('id')
}).exec(function(err, usersDestroyed) {
if (err) return res.negotiate(err);
if (usersDestroyed.length === 0) {
return res.notFound();
}
return res.ok();
});
},
removeProfile: function(req, res) {
User.update({
id: req.session.userId
}, {
deleted: true
}, function(err, removedUser) {
if (err) return res.negotiate(err);
if (removedUser.length === 0) {
return res.notFound();
}
// Log user out
req.session.userId = null;
return res.ok();
});
},
restoreProfile: function(req, res) {
User.findOne({
email: req.param('email')
}, function foundUser(err, user) {
if (err) return res.negotiate(err);
if (!user) return res.notFound();
Passwords.checkPassword({
passwordAttempt: req.param('password'),
encryptedPassword: user.encryptedPassword
}).exec({
error: function(err) {
return res.negotiate(err);
},
incorrect: function() {
return res.notFound();
},
success: function() {
User.update({
id: user.id
}, {
deleted: false
}).exec(function(err, updatedUser) {
// Log the user in
req.session.userId = user.id;
return res.json(updatedUser);
});
}
});
});
},
restoreGravatarURL: function(req, res) {
try {
var restoredGravatarURL = gravatarURL = Gravatar.getImageUrl({
emailAddress: req.param('email')
}).execSync();
return res.json(restoredGravatarURL);
} catch (err) {
return res.serverError(err);
}
},
updateProfile: function(req, res) {
User.update({
id: req.param('id')
}, {
gravatarURL: req.param('gravatarURL')
}, function(err, updatedUser) {
if (err) return res.negotiate(err);
return res.json(updatedUser);
});
},
changePassword: function(req, res) {
if (_.isUndefined(req.param('password'))) {
return res.badRequest('A password is required!');
}
if (req.param('password').length < 6) {
return res.badRequest('Password must be at least 6 characters!');
}
Passwords.encryptPassword({
password: req.param('password'),
}).exec({
error: function(err) {
return res.serverError(err);
},
success: function(result) {
User.update({
id: req.param('id')
}, {
encryptedPassword: result
}).exec(function(err, updatedUser) {
if (err) {
return res.negotiate(err);
}
return res.json(updatedUser);
});
}
});
},
adminUsers: function(req, res) {
User.find().exec(function(err, users){
if (err) return res.negotiate(err);
return res.json(users);
});
},
updateAdmin: function(req, res) {
User.update(req.param('id'), {
admin: req.param('admin')
}).exec(function(err, update){
if (err) return res.negotiate(err);
return res.ok();
});
},
updateBanned: function(req, res) {
User.update(req.param('id'), {
banned: req.param('banned')
}).exec(function(err, update){
if (err) return res.negotiate(err);
return res.ok();
});
},
updateDeleted: function(req, res) {
User.update(req.param('id'), {
deleted: req.param('deleted')
}).exec(function(err, update){
if (err) return res.negotiate(err);
return res.ok();
});
}
};
angular.module('brushfire').controller('profilePageController', ['$location', '$routeParams', '$scope', '$http', function($location, $routeParams, $scope, $http){
// Just a hack so we can type `SCOPE` in the Chrome inspector.
SCOPE=$scope;
$scope.me = window.SAILS_LOCALS.me;
/////////////////////////////////////////////////////////////////////////////////
// When HTML is rendered... (i.e. when the page loads)
/////////////////////////////////////////////////////////////////////////////////
// Set up initial objects
// (kind of like our schema for the page)
$scope.userProfile = {
properties: {},
errorMsg: '',
saving: false,
loading: false,
noProfile: false
};
$scope.userProfile.loading = true;
$scope.removeProfile = function() {
// console.log('the change userprofile is: ', $scope.userProfile);
// var theRoute = '/user/removeProfile/' + $scope.userProfile.properties.id;
// var theRoute = '/user/removeProfile/' + $scope.me.id;
$$http.put('/user/removeProfile', {
deleted: true
})
.then(function onSuccess(sailsResponse) {
// console.log('sailsResponse: ', sailsResponse);
// $scope.userProfile.properties.gravatarURL = sailsResponse.data.gravatarURL;
window.location = '/signup';
//
// toastr.success('Password Updated!');
$scope.userProfile.loading = false;
})
.catch(function onError(sailsResponse) {
// console.log('sailsresponse: ', sailsResponse)
// Otherwise, display generic error if the error is unrecognized.
$scope.userProfile.errorMsg = 'An unexpected error occurred: ' + (sailsResponse.data || sailsResponse.status);
})
.finally(function eitherWay() {
$scope.loading = false;
});
};
$scope.deleteProfile = function() {
var theRoute = 'user/delete/' + $routeParams.id;
$http.delete(theRoute)
.then(function onSuccess(deletedProfile){
window.location = '#/signup';
})
.catch(function onError(err){
$scope.userProfile.errorMsg = 'An unexpected error occurred: ' + err;
});
};
}]);
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut'],
logout: ['isLoggedIn'],
removeProfile: ['isLoggedIn'],
updateProfile: ['isLoggedIn'],
restoreGravatarURL: ['isLoggedIn'],
changePassword: ['isLoggedIn']
},
PageController: {
showSignupPage: ['isLoggedOut'],
showAdminPage: ['isLoggedIn', 'isAdmin'],
showProfilePage: ['isLoggedIn'],
showEditProfilePage: ['isLoggedIn']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
/**
* UserController
*
* @description :: Server-side logic for managing users
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
var Emailaddresses = require('machinepack-emailaddresses');
var Passwords = require('machinepack-passwords');
var Gravatar = require('machinepack-gravatar');
module.exports = {
login: function (req, res) {
User.findOne({
or : [
{ email: req.param('email') },
{ username: req.param('username') }
]
}, function foundUser(err, user) {
if (err) return res.negotiate(err);
if (!user) return res.notFound();
Passwords.checkPassword({
passwordAttempt: req.param('password'),
encryptedPassword: user.encryptedPassword
}).exec({
error: function (err){
return res.negotiate(err);
},
incorrect: function (){
return res.notFound();
},
success: function (){
if (user.deleted) {
return res.forbidden("'Your our account has been deleted. Please visit http://brushfire.io/restore to restore your account.'");
}
if (user.banned) {
return res.forbidden("'Your our account has been banned, most likely for adding dog videos in violation of the Terms of Service. Please contact Chad or his mother.'");
}
// Login user
req.session.userId = user.id;
// console.log('req.session.userId: ', req.session.userId);
// Respond with a 200 status
return res.ok();
}
});
});
},
logout: function (req, res) {
if (!req.session.userId) return res.redirect('/');
User.findOne(req.session.userId, function foundUser(err, user) {
if (err) return res.negotiate(err);
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists.');
return res.redirect('/');
}
// Logout user
req.session.userId = null;
return res.redirect('/');
});
},
signup: function(req, res) {
if (_.isUndefined(req.param('email'))) {
return res.badRequest('An email address is required!');
}
if (_.isUndefined(req.param('password'))) {
return res.badRequest('A password is required!');
}
if (req.param('password').length < 6) {
return res.badRequest('Password must be at least 6 characters!');
}
if (_.isUndefined(req.param('username'))) {
return res.badRequest('A username is required!');
}
// username must be at least 6 characters
if (req.param('username').length < 6) {
return res.badRequest('Username must be at least 6 characters!');
}
// Username must contain only numbers and letters.
if (!_.isString(req.param('username')) || req.param('username').match(/[^a-z0-9]/i)) {
return res.badRequest('Invalid username: must consist of numbers and letters only.');
}
Emailaddresses.validate({
string: req.param('email'),
}).exec({
// An unexpected error occurred.
error: function(err) {
return res.serverError(err);
},
// The provided string is not an email address.
invalid: function() {
return res.badRequest('Doesn\'t look like an email address to me!');
},
// OK.
success: function() {
Passwords.encryptPassword({
password: req.param('password'),
}).exec({
error: function(err) {
return res.serverError(err);
},
success: function(result) {
var options = {};
try {
options.gravatarURL = Gravatar.getImageUrl({
emailAddress: req.param('email')
}).execSync();
} catch (err) {
return res.serverError(err);
}
options.email = req.param('email');
options.username = req.param('username');
options.encryptedPassword = result;
options.deleted = false;
options.admin = false;
options.banned = false;
User.create(options).exec(function(err, createdUser) {
if (err) {
console.log('the error is: ', err.invalidAttributes);
if (err.invalidAttributes && err.invalidAttributes.email && err.invalidAttributes.email[0] && err.invalidAttributes.email[0].rule === 'unique') {
// return res.send(409, 'Email address is already taken by another user, please try again.');
return res.alreadyInUse(err);
}
if (err.invalidAttributes && err.invalidAttributes.username && err.invalidAttributes.username[0] && err.invalidAttributes.username[0].rule === 'unique') {
// return res.send(409, 'Username is already taken by another user, please try again.');
return res.alreadyInUse(err);
}
return res.negotiate(err);
}
// Log the user in
req.session.userId = createdUser.id;
return res.json(createdUser);
});
}
});
}
});
},
profile: function(req, res) {
// Try to look up user using the provided email address
User.findOne(req.param('id')).exec(function foundUser(err, user) {
// Handle error
if (err) return res.negotiate(err);
// Handle no user being found
if (!user) return res.notFound();
// Return the user
return res.json(user);
});
},
delete: function(req, res) {
if (!req.param('id')) {
return res.badRequest('id is a required parameter.');
}
User.destroy({
id: req.param('id')
}).exec(function(err, usersDestroyed) {
if (err) return res.negotiate(err);
if (usersDestroyed.length === 0) {
return res.notFound();
}
return res.ok();
});
},
removeProfile: function(req, res) {
User.update({
id: req.session.userId
}, {
deleted: true
}, function(err, removedUser) {
if (err) return res.negotiate(err);
if (removedUser.length === 0) {
return res.notFound();
}
// Log user out
req.session.userId = null;
return res.ok();
});
},
restoreProfile: function(req, res) {
User.findOne({
email: req.param('email')
}, function foundUser(err, user) {
if (err) return res.negotiate(err);
if (!user) return res.notFound();
Passwords.checkPassword({
passwordAttempt: req.param('password'),
encryptedPassword: user.encryptedPassword
}).exec({
error: function(err) {
return res.negotiate(err);
},
incorrect: function() {
return res.notFound();
},
success: function() {
User.update({
id: user.id
}, {
deleted: false
}).exec(function(err, updatedUser) {
// Log the user in
req.session.userId = user.id;
return res.json(updatedUser);
});
}
});
});
},
restoreGravatarURL: function(req, res) {
try {
var restoredGravatarURL = gravatarURL = Gravatar.getImageUrl({
emailAddress: req.param('email')
}).execSync();
return res.json(restoredGravatarURL);
} catch (err) {
return res.serverError(err);
}
},
updateProfile: function(req, res) {
User.update({
id: req.session.userId
}, {
gravatarURL: req.param('gravatarURL')
}, function(err, updatedUser) {
if (err) return res.negotiate(err);
return res.json(updatedUser);
});
},
changePassword: function(req, res) {
if (_.isUndefined(req.param('password'))) {
return res.badRequest('A password is required!');
}
if (req.param('password').length < 6) {
return res.badRequest('Password must be at least 6 characters!');
}
Passwords.encryptPassword({
password: req.param('password'),
}).exec({
error: function(err) {
return res.serverError(err);
},
success: function(result) {
User.update({
id: req.session.userId
}, {
encryptedPassword: result
}).exec(function(err, updatedUser) {
if (err) {
return res.negotiate(err);
}
return res.json(updatedUser);
});
}
});
},
adminUsers: function(req, res) {
User.find().exec(function(err, users){
if (err) return res.negotiate(err);
return res.json(users);
});
},
updateAdmin: function(req, res) {
User.update(req.param('id'), {
admin: req.param('admin')
}).exec(function(err, update){
if (err) return res.negotiate(err);
return res.ok();
});
},
updateBanned: function(req, res) {
User.update(req.param('id'), {
banned: req.param('banned')
}).exec(function(err, update){
if (err) return res.negotiate(err);
return res.ok();
});
},
updateDeleted: function(req, res) {
User.update(req.param('id'), {
deleted: req.param('deleted')
}).exec(function(err, update){
if (err) return res.negotiate(err);
return res.ok();
});
}
};
angular.module('brushfire').controller('editProfilePageController', ['$location', '$routeParams', '$scope', '$http', 'toastr', function($location, $routeParams, $scope, $http, toastr) {
// Just a hack so we can type `SCOPE` in the Chrome inspector.
SCOPE = $scope;
$scope.me = window.SAILS_LOCALS.me;
/////////////////////////////////////////////////////////////////////////////////
// When HTML is rendered... (i.e. when the page loads)
/////////////////////////////////////////////////////////////////////////////////
// Set up initial objects
// (kind of like our schema for the page)
$scope.editProfile = {
properties: {},
errorMsg: '',
error: false,
saving: false,
loading: false,
changePassword: {}
};
$scope.updateProfile = function() {
// var theRoute = 'user/updateProfile/' + $scope.me.id;
// Submit PUT request to Sails.
$http.put('/user/updateProfile', {
gravatarURL: $scope.me.gravatarURL
// gravatarURL: $scope.editProfile.properties.gravatarURL
})
.then(function onSuccess(sailsResponse) {
// Notice that the sailsResponse is an array and not a single object
// The .update() model method returns an array and not a single record.
window.location = '/profile';
$scope.editProfile.loading = false;
})
.catch(function onError(sailsResponse) {
// console.log(sailsResponse);
// Otherwise, display generic error if the error is unrecognized.
$scope.editProfile.errorMsg = 'An unexpected error occurred: ' + (sailsResponse.data || sailsResponse.status);
})
.finally(function eitherWay() {
$scope.editProfile.loading = false;
});
};
$scope.restore = function() {
// Submit PUT request to Restore GravatarURL.
$http.put('/user/restoreGravatarURL', {
email: $scope.me.email
})
.then(function onSuccess(sailsResponse) {
// Restore the current gravatarURL
$scope.me.gravatarURL = sailsResponse.data;
$scope.editProfile.loading = false;
})
.catch(function onError(sailsResponse) {
// console.log(sailsResponse);
// Otherwise, display generic error if the error is unrecognized.
$scope.editProfile.errorMsg = 'An unexpected error occurred: ' + (sailsResponse.data || sailsResponse.status);
})
.finally(function eitherWay() {
$scope.editProfile.loading = false;
});
};
$scope.changeMyPassword = function() {
// console.log('the change userprofile is: ', $scope.userProfile);
$http.put('user/changePassword', {
id: $scope.me.id,
password: $scope.editProfile.properties.password
})
.then(function onSuccess(sailsResponse) {
// console.log('sailsResponse: ', sailsResponse);
// $scope.userProfile.properties.gravatarURL = sailsResponse.data.gravatarURL;
// window.location = '#/profile/' + $scope.editProfile.properties.id;
window.location='/profile';
// toastr.success('Password Updated!');
$scope.editProfile.loading = false;
})
.catch(function onError(sailsResponse) {
// console.log('sailsresponse: ', sailsResponse)
// Otherwise, display generic error if the error is unrecognized.
$scope.editProfile.changePassword.errorMsg = 'An unexpected error occurred: ' + (sailsResponse.data || sailsResponse.status);
})
.finally(function eitherWay() {
$scope.editProfile.loading = false;
});
};
}]);
angular.module('brushfire').controller('editProfilePageController', ['$location', '$routeParams', '$scope', '$http', 'toastr', function($location, $routeParams, $scope, $http, toastr) {
// Just a hack so we can type `SCOPE` in the Chrome inspector.
SCOPE = $scope;
$scope.me = window.SAILS_LOCALS.me;
/////////////////////////////////////////////////////////////////////////////////
// When HTML is rendered... (i.e. when the page loads)
/////////////////////////////////////////////////////////////////////////////////
// Set up initial objects
// (kind of like our schema for the page)
$scope.editProfile = {
properties: {},
errorMsg: '',
error: false,
saving: false,
loading: false,
changePassword: {}
};
$scope.updateProfile = function() {
// var theRoute = 'user/updateProfile/' + $scope.me.id;
// Submit PUT request to Sails.
$http.put('/user/updateProfile', {
gravatarURL: $scope.me.gravatarURL
// gravatarURL: $scope.editProfile.properties.gravatarURL
})
.then(function onSuccess(sailsResponse) {
// Notice that the sailsResponse is an array and not a single object
// The .update() model method returns an array and not a single record.
window.location = '/profile';
$scope.editProfile.loading = false;
})
.catch(function onError(sailsResponse) {
// console.log(sailsResponse);
// Otherwise, display generic error if the error is unrecognized.
$scope.editProfile.errorMsg = 'An unexpected error occurred: ' + (sailsResponse.data || sailsResponse.status);
})
.finally(function eitherWay() {
$scope.editProfile.loading = false;
});
};
$scope.restore = function() {
// Submit PUT request to Restore GravatarURL.
$http.put('/user/restoreGravatarURL', {
email: $scope.me.email
})
.then(function onSuccess(sailsResponse) {
// Restore the current gravatarURL
$scope.me.gravatarURL = sailsResponse.data;
$scope.editProfile.loading = false;
})
.catch(function onError(sailsResponse) {
// console.log(sailsResponse);
// Otherwise, display generic error if the error is unrecognized.
$scope.editProfile.errorMsg = 'An unexpected error occurred: ' + (sailsResponse.data || sailsResponse.status);
})
.finally(function eitherWay() {
$scope.editProfile.loading = false;
});
};
$scope.changeMyPassword = function() {
// console.log('the change userprofile is: ', $scope.userProfile);
$http.put('user/changePassword', {
// id: $scope.me.id,
password: $scope.editProfile.properties.password
})
.then(function onSuccess(sailsResponse) {
// console.log('sailsResponse: ', sailsResponse);
// $scope.userProfile.properties.gravatarURL = sailsResponse.data.gravatarURL;
// window.location = '#/profile/' + $scope.editProfile.properties.id;
window.location='/profile';
// toastr.success('Password Updated!');
$scope.editProfile.loading = false;
})
.catch(function onError(sailsResponse) {
// console.log('sailsresponse: ', sailsResponse)
// Otherwise, display generic error if the error is unrecognized.
$scope.editProfile.changePassword.errorMsg = 'An unexpected error occurred: ' + (sailsResponse.data || sailsResponse.status);
})
.finally(function eitherWay() {
$scope.editProfile.loading = false;
});
};
}]);
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut'],
logout: ['isLoggedIn'],
removeProfile: ['isLoggedIn'],
updateProfile: ['isLoggedIn'],
restoreGravatarURL: ['isLoggedIn'],
changePassword: ['isLoggedIn'],
signup: ['isLoggedOut']
},
PageController: {
showSignupPage: ['isLoggedOut'],
showAdminPage: ['isLoggedIn', 'isAdmin'],
showProfilePage: ['isLoggedIn'],
showEditProfilePage: ['isLoggedIn'],
showRestorePage: ['isLoggedOut']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut'],
logout: ['isLoggedIn'],
removeProfile: ['isLoggedIn'],
updateProfile: ['isLoggedIn'],
restoreGravatarURL: ['isLoggedIn'],
changePassword: ['isLoggedIn'],
signup: ['isLoggedOut'],
restoreProfile: ['isLoggedOut']
},
PageController: {
showSignupPage: ['isLoggedOut'],
showAdminPage: ['isLoggedIn', 'isAdmin'],
showProfilePage: ['isLoggedIn'],
showEditProfilePage: ['isLoggedIn'],
showRestorePage: ['isLoggedOut']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
/**
* Policy Mappings
* (sails.config.policies)
*
* Policies are simple functions which run **before** your controllers.
* You can apply one or more policies to a given controller, or protect
* its actions individually.
*
* Any policy file (e.g. `api/policies/authenticated.js`) can be accessed
* below by its filename, minus the extension, (e.g. "authenticated")
*
* For more information on how policies work, see:
* http://sailsjs.org/#!/documentation/concepts/Policies
*
* For more information on configuring policies, check out:
* http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.policies.html
*/
module.exports.policies = {
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
// '*': true,
VideoController: {
create: ['isLoggedIn']
},
UserController: {
login: ['isLoggedOut'],
logout: ['isLoggedIn'],
removeProfile: ['isLoggedIn'],
updateProfile: ['isLoggedIn'],
restoreGravatarURL: ['isLoggedIn'],
changePassword: ['isLoggedIn'],
signup: ['isLoggedOut'],
restoreProfile: ['isLoggedOut'],
adminUsers: ['isLoggedIn', 'isAdmin'],
updateAdmin: ['isLoggedIn', 'isAdmin'],
updateBanned: ['isLoggedIn', 'isAdmin'],
updateDeleted: ['isLoggedIn', 'isAdmin']
},
PageController: {
showSignupPage: ['isLoggedOut'],
showAdminPage: ['isLoggedIn', 'isAdmin'],
showProfilePage: ['isLoggedIn'],
showEditProfilePage: ['isLoggedIn'],
showRestorePage: ['isLoggedOut']
}
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment