summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulie Lala <jules@okfoc.us>2014-06-09 07:48:34 -0400
committerJulie Lala <jules@okfoc.us>2014-06-09 07:48:34 -0400
commite8ba718205d41e75923264ef945178030b662c93 (patch)
tree97bff0c0ec0a2bd2b6efb7d5ddbb1ff60c102529
parentd385f80d0942494410432f11d3f3ca0f05d9e4a9 (diff)
populate edit profile form
-rw-r--r--public/assets/javascripts/ui/EditProfileModal.js51
-rw-r--r--public/assets/javascripts/ui/MasterView.js3
-rw-r--r--public/assets/javascripts/ui/ModalFormView.js70
-rw-r--r--public/assets/javascripts/ui/ModalView.js1
-rw-r--r--public/assets/javascripts/ui/NewProjectModal.js39
-rw-r--r--public/assets/javascripts/ui/SignInModal.js49
-rw-r--r--public/assets/javascripts/ui/SignUpModal.js60
-rw-r--r--server/index.js2
-rw-r--r--server/lib/api.js24
-rw-r--r--server/lib/auth.js6
-rw-r--r--server/lib/schemas/User.js8
-rw-r--r--server/lib/upload.js72
-rw-r--r--server/lib/util.js11
-rw-r--r--views/partials/edit-profile.ejs47
-rw-r--r--views/partials/scripts.ejs1
15 files changed, 248 insertions, 196 deletions
diff --git a/public/assets/javascripts/ui/EditProfileModal.js b/public/assets/javascripts/ui/EditProfileModal.js
index de8a8be..5b79a31 100644
--- a/public/assets/javascripts/ui/EditProfileModal.js
+++ b/public/assets/javascripts/ui/EditProfileModal.js
@@ -1,48 +1,23 @@
-var EditProfileModal = ModalView.extend({
+var EditProfileModal = ModalFormView.extend({
el: ".mediaDrawer.editProfile",
- action: "/project/edit",
+ action: "/api/profile",
- events: {
- "submit form": "submit"
- },
-
- initialize: function(){
- this.$form = this.$("form")
- this.$errors = this.$(".errors")
- this.$errorList = this.$(".errorList")
- },
-
- reset: function(){
- this.$("input").not("[type='submit']").not("[type='hidden']").val("")
- },
-
load: function(){
this.reset()
- this.show()
+ $.get("/api/profile", $.proxy(function(data){
+ console.log(data)
+
+ for (var i in data) {
+ this.$("[name='" + i + "']").val(data[i])
+ }
+
+ this.show()
+ }, this))
},
- submit: function(e){
- e.preventDefault()
-
- this.$errors.hide();
- this.$errorList.empty()
-
- var fields = this.$form.serializeArray()
-
- var request = $.post(this.action, $.param(fields));
- request.done($.proxy(function (response) {
- if (response.error) {
- this.$errors.show();
- for (var key in response.error.errors) {
- this.$errorList.append('<div>' + response.error.errors[key].message + '</div>');
- }
- return
- }
- else {
- window.location.href = "/profile"
- }
- }, this));
+ success: function(){
+ window.location.href = "/profile"
}
})
diff --git a/public/assets/javascripts/ui/MasterView.js b/public/assets/javascripts/ui/MasterView.js
index a39c6f0..5aca4e0 100644
--- a/public/assets/javascripts/ui/MasterView.js
+++ b/public/assets/javascripts/ui/MasterView.js
@@ -25,6 +25,8 @@ var MasterView = View.extend({
this.editProjectModal = new EditProjectModal()
this.editProfileModal = new EditProfileModal()
+ this.originalPath = window.location.pathname
+
for (var route in this.routes) {
if (window.location.pathname.indexOf(route) === 0) {
this[this.routes[route]]()
@@ -61,7 +63,6 @@ var MasterView = View.extend({
editProject: function(e){
e && e.preventDefault()
window.history.pushState(null, document.title, "/project/edit")
-
this.editProjectModal.load()
},
diff --git a/public/assets/javascripts/ui/ModalFormView.js b/public/assets/javascripts/ui/ModalFormView.js
new file mode 100644
index 0000000..608b8c1
--- /dev/null
+++ b/public/assets/javascripts/ui/ModalFormView.js
@@ -0,0 +1,70 @@
+
+var ModalFormView = ModalView.extend({
+
+ events: {
+ "submit form": "submit"
+ },
+
+ initialize: function(){
+ this.$form = this.$("form")
+ this.$errors = this.$(".errors")
+ this.$errorList = this.$(".errorList")
+ },
+
+ reset: function(){
+ this.$("input").not("[type='submit']").not("[type='hidden']").val("")
+ },
+
+ load: function(){
+ this.reset()
+ this.show()
+ },
+
+ showErrors: function(errors){
+ if (errors && errors.length) {
+ this.$errors.show();
+ for (var i in errors) {
+ this.$errorList.append('<div>' + errors[i] + '</div>');
+ }
+ }
+ },
+
+ submit: function(e){
+ e.preventDefault()
+
+ this.$errors.hide();
+ this.$errorList.empty();
+
+ if (this.validate) {
+ var errors = this.validate()
+ if (errors && errors.length) {
+ this.showErrors(errors)
+ return
+ }
+ }
+
+ var fields = this.$form.serializeArray()
+ fields.forEach(function(pair){
+ if (pair.name == "password" && pair.value.length > 0) {
+ pair.value = SHA1.hex('lol$' + pair.value + '$vvalls')
+ }
+ })
+
+ var request = $.post(this.action, $.param(fields));
+ request.done($.proxy(function (response) {
+ if (response.error) {
+ this.$errors.show();
+ var errors = []
+ for (var key in response.error.errors) {
+ errors.push(response.error.errors[key].message);
+ }
+ this.showErrors(errors)
+ return
+ }
+ else {
+ this.success && this.success(response)
+ }
+ }, this));
+ }
+
+})
diff --git a/public/assets/javascripts/ui/ModalView.js b/public/assets/javascripts/ui/ModalView.js
index a34520f..80ce8d0 100644
--- a/public/assets/javascripts/ui/ModalView.js
+++ b/public/assets/javascripts/ui/ModalView.js
@@ -21,6 +21,7 @@ var ModalView = View.extend({
window.location.pathname = "/"
}
else {
+ history.pushState(null, document.title, app.master.originalPath)
this.hide()
}
}
diff --git a/public/assets/javascripts/ui/NewProjectModal.js b/public/assets/javascripts/ui/NewProjectModal.js
index 58dcb73..cf2044f 100644
--- a/public/assets/javascripts/ui/NewProjectModal.js
+++ b/public/assets/javascripts/ui/NewProjectModal.js
@@ -1,49 +1,16 @@
-var NewProjectModal = ModalView.extend({
+var NewProjectModal = ModalFormView.extend({
el: ".mediaDrawer.newProject",
action: "/project/new",
- events: {
- "submit form": "submit"
- },
-
- initialize: function(){
- this.$form = this.$("form")
- this.$errors = this.$(".errors")
- this.$errorList = this.$(".errorList")
- },
-
- reset: function(){
- this.$("input").not("[type='submit']").not("[type='hidden']").val("")
- },
-
load: function(){
this.reset()
this.show()
},
- submit: function(e){
- e.preventDefault()
-
- this.$errors.hide();
- this.$errorList.empty()
-
- var fields = this.$form.serializeArray()
-
- var request = $.post(this.action, $.param(fields));
- request.done($.proxy(function (response) {
- if (response.error) {
- this.$errors.show();
- for (var key in response.error.errors) {
- this.$errorList.append('<div>' + response.error.errors[key].message + '</div>');
- }
- return
- }
- else {
- window.location.href = "/profile"
- }
- }, this));
+ success: function(){
+ //
}
})
diff --git a/public/assets/javascripts/ui/SignInModal.js b/public/assets/javascripts/ui/SignInModal.js
index 0112513..4c91b54 100644
--- a/public/assets/javascripts/ui/SignInModal.js
+++ b/public/assets/javascripts/ui/SignInModal.js
@@ -1,54 +1,11 @@
-var SignInModal = ModalView.extend({
+var SignInModal = ModalFormView.extend({
el: ".mediaDrawer.signin",
action: "/auth/signin",
- events: {
- "submit form": "submit"
- },
-
- initialize: function(){
- this.$form = this.$("form")
- this.$errors = this.$(".errors")
- this.$errorList = this.$(".errorList")
- },
-
- reset: function(){
- this.$("input").not("[type='submit']").not("[type='hidden']").val("")
- },
-
- load: function(){
- this.reset()
- this.show()
- },
-
- submit: function(e){
- e.preventDefault()
-
- this.$errors.hide();
- this.$errorList.empty()
-
- var fields = this.$form.serializeArray()
- fields.forEach(function(pair){
- if (pair.name == "password" && pair.value.length > 0) {
- pair.value = SHA1.hex('lol$' + pair.value + '$vvalls')
- }
- })
-
- var request = $.post(this.action, $.param(fields));
- request.done($.proxy(function (response) {
- if (response.error) {
- this.$errors.show();
- for (var key in response.error.errors) {
- this.$errorList.append('<div>' + response.error.errors[key].message + '</div>');
- }
- return
- }
- else {
- window.location.href = "/profile"
- }
- }, this));
+ success: function(res){
+ window.location.href = "/profile"
}
})
diff --git a/public/assets/javascripts/ui/SignUpModal.js b/public/assets/javascripts/ui/SignUpModal.js
index 160323b..95b5837 100644
--- a/public/assets/javascripts/ui/SignUpModal.js
+++ b/public/assets/javascripts/ui/SignUpModal.js
@@ -1,28 +1,9 @@
-var SignUpModal = ModalView.extend({
+var SignUpModal = ModalFormView.extend({
el: ".mediaDrawer.signup",
action: "/auth/signup",
-
- events: {
- "submit form": "submit",
- },
-
- initialize: function(){
- this.$form = this.$("form")
- this.$errors = this.$(".errors")
- this.$errorList = this.$(".errorList")
- },
- reset: function(){
- this.$("input").not("[type='submit']").not("[type='hidden']").val("")
- },
-
- load: function(){
- this.reset()
- this.show()
- },
-
validate: function(){
var errors = []
@@ -47,43 +28,12 @@ var SignUpModal = ModalView.extend({
errors.push("Passwords don't match");
}
- if (errors.length) {
- this.$errors.show();
- for (var i in errors) {
- this.$errorList.append('<div>' + errors[i] + '</div>');
- }
- }
-
- return ! errors.length
+ return errors
},
- submit: function(e){
- e.preventDefault()
-
- this.$errors.hide();
- this.$errorList.empty()
-
- if (! this.validate()) return
-
- var fields = this.$form.serializeArray()
- fields.forEach(function(pair){
- if (pair.name == "password" && pair.value.length > 0) {
- pair.value = SHA1.hex('lol$' + pair.value + '$vvalls')
- }
- })
- var request = $.post(this.action, $.param(fields));
- request.done($.proxy(function (response) {
- if (response.error) {
- this.$errors.show();
- for (var key in response.error.errors) {
- this.$errorList.append('<div>' + response.error.errors[key].message + '</div>');
- }
- return;
- }
- else {
- window.location.href = "/profile"
- }
- }, this));
+ success: function(res){
+ window.location.href = "/profile"
}
})
+
diff --git a/server/index.js b/server/index.js
index fc77660..34d5989 100644
--- a/server/index.js
+++ b/server/index.js
@@ -71,6 +71,8 @@ app.get('/auth/facebook', auth.login('facebook'));
app.get('/auth/facebook/callback', auth.loggedIn('facebook'));
app.get('/profile', views.profile)
app.get('/profile/edit', views.profile)
+app.get('/api/profile', middleware.ensureAuthenticated, api.profile.show)
+app.put('/api/profile', middleware.ensureAuthenticated, api.profile.update)
app.get('/project/new', views.modal);
diff --git a/server/lib/api.js b/server/lib/api.js
index d9934ab..9ff9f38 100644
--- a/server/lib/api.js
+++ b/server/lib/api.js
@@ -3,10 +3,32 @@
var passport = require('passport'),
_ = require('lodash'),
Entities = require('html-entities').XmlEntities,
- entities = new Entities();
+ entities = new Entities(),
+ crypto = require('crypto'),
+ _ = require('lodash'),
+ util = require('./util'),
+ config = require('../../config.json'),
+ User = require('./schemas/User');
var api = {
+
+ profile: {
+ show: function(req, res){
+ User.findOne({ _id: req.user._id }, function(err, user){
+ res.json(err || user)
+ })
+ },
+ update: function(req, res){
+ var data = req.cleanQuery(req.body)
+ if (data.new_password.length && req.user.checkPassword(data.old_password)) {
+ data.password = data.new_password
+ }
+ delete data.old_password
+ delete data.new_password
+ }
+ }
+
}
diff --git a/server/lib/auth.js b/server/lib/auth.js
index ede52b6..e7b7a75 100644
--- a/server/lib/auth.js
+++ b/server/lib/auth.js
@@ -5,6 +5,7 @@ var passport = require('passport'),
TwitterStrategy = require('passport-twitter').Strategy,
LocalStrategy = require('passport-local').Strategy,
passportSocketIo = require("passport.socketio"),
+ crypto = require('crypto'),
_ = require('lodash'),
util = require('./util'),
config = require('../../config.json'),
@@ -91,6 +92,10 @@ var auth = {
var username = util.trim(req.body.username)
var password = req.body.password
var email = util.trim(req.body.email)
+
+ var shasum = crypto.createHash('sha1')
+ shasum.update(password)
+ password = shasum.digest('hex');
User.findOne({ username: username }, function (err, user) {
if (user) {
@@ -156,6 +161,7 @@ var auth = {
username: profile.username || profile.displayName.toLowerCase().replace(/ /g,'-'),
displayName: profile.displayName,
photo: "http://graph.facebook.com/" + profile.id + "/picture?type=large",
+ facebookUrl: profile.username ? "https://facebook.com/" + profile.username : ""
};
User.findOne({facebook_id: profile.id}, function(err, data){
diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js
index d78bfd2..24b0adf 100644
--- a/server/lib/schemas/User.js
+++ b/server/lib/schemas/User.js
@@ -4,6 +4,7 @@ var NONALPHANUMERICS_REGEX = new RegExp('[^-_a-zA-Z0-9]', 'g')
var mongoose = require('mongoose'),
_ = require('lodash'),
+ crypto = require('crypto'),
config = require('../../../config.json');
var UserSchema = new mongoose.Schema({
@@ -28,6 +29,8 @@ var UserSchema = new mongoose.Schema({
case 'assets':
case 'admin':
case 'terms':
+ case 'api':
+ case 'vvalls':
case 'assets':
case '':
return false
@@ -53,11 +56,14 @@ var UserSchema = new mongoose.Schema({
bio: { type: String, default: "" },
website: { type: String, default: "" },
twitterName: { type: String, default: "" },
+ facebookUrl: { type: String, default: "" },
isAdmin: { type: Boolean, default: false }
});
UserSchema.methods.validPassword = function (pw) {
- return this.password === pw
+ var shasum = crypto.createHash('sha1')
+ shasum.update(pw)
+ return this.password === shasum.digest('hex');
}
module.exports = exports = mongoose.model('user', UserSchema);
diff --git a/server/lib/upload.js b/server/lib/upload.js
new file mode 100644
index 0000000..5c130a2
--- /dev/null
+++ b/server/lib/upload.js
@@ -0,0 +1,72 @@
+
+var config = require('../../config.json'),
+ util = require('./util'),
+ knox = require('knox'),
+ moment = require('moment');
+
+var s3 = module.exports.s3 = knox.createClient({
+ key: process.env.OKFOCUS_S3_KEY,
+ secret: process.env.OKFOCUS_S3_SECRET,
+ bucket: 'vvalls'
+});
+
+var acceptableuploadTypes = {
+ 'image/gif': 'gif',
+ 'image/jpeg': 'jpg',
+ 'image/png': 'png'
+}
+
+module.exports.put = function (key, image, opt) {
+ var imageSize, imageType, filename
+ var err
+ var now = new Date()
+
+ var ts = moment().format('YYYYMMDD')
+
+ var extension = acceptableuploadTypes[image.type]
+ filename = (+now) + "-"
+ + image.name.replace(/\..*$/,"")
+ .replace(/[^0-9a-zA-Z]+/g,"-")
+ .substr(-64)
+ + "." + extension;
+
+ var remote_path = "/images/" + key + "/" + ts + "/" + filename
+
+ if (! extension) {
+ err = "unacceptable filetype"
+ }
+ else if (image.size < 10) {
+ err = "file too small"
+ }
+ else if (image.size > 2097152) { // 2mb limit
+ err = "file too large"
+ }
+
+ if (err) {
+ console.error(">>>", err)
+ opt.unacceptable && opt.unacceptable(err)
+ return
+ }
+
+ opt.acceptable && opt.acceptable(err)
+
+ console.log("upload > ", remote_path)
+ s3.putFile(image.path, remote_path, {
+ 'Content-Length': image.size,
+ 'Content-Type': image.type,
+ 'x-amz-acl': 'public-read'
+ }, function(err, s3res) {
+ if (err || s3res.statusCode !== 200) {
+ console.error(err);
+ s3res.resume()
+ return;
+ }
+
+ var image_url = s3res.url || s3res.req.url
+
+ opt.success && opt.success(image_url)
+ }).on('error', function(err, s3res){
+ console.error(err)
+ s3res && s3res.resume && s3res.resume()
+ })
+}
diff --git a/server/lib/util.js b/server/lib/util.js
index 45902f3..7a63507 100644
--- a/server/lib/util.js
+++ b/server/lib/util.js
@@ -5,4 +5,15 @@ var whitespaceTail = /\s+$/
var util = {}
util.trim = function (s){ return s.replace(whitespaceHead,"").replace(whitespaceTail,"") }
+util.cleanQuery = function (query) {
+ var update = _.extend({}, query);
+ delete update._id;
+ delete update.created_at;
+ delete update.modified_at;
+ delete update.modified_by;
+ delete update.created_by;
+ return update;
+}
+
+
module.exports = util
diff --git a/views/partials/edit-profile.ejs b/views/partials/edit-profile.ejs
index d7c9a34..a9a5a9a 100644
--- a/views/partials/edit-profile.ejs
+++ b/views/partials/edit-profile.ejs
@@ -9,60 +9,71 @@
<h3>Edit Profile</h3>
</li>
<li>
- <label class="description" for="element_3">Name:</label>
+ <label class="description" for="profile_displayName">Name:</label>
<div>
- <input id="element_3_1" name= "element_3_1" class="element text" type="text" maxlength="255" value="Ivan Sidorov"/>
+ <input id="profile_displayName" name="displayName" class="element text" type="text" maxlength="255">
</div>
</li>
<li>
- <label class="description" for="element_2">Website:</label>
+ <label class="description" for="profile_email">Email:</label>
<div>
- <input id="element_2" name="element_2" class="element text medium" type="text" maxlength="255" value="http://"/>
+ <input id="profile_email" name="email" class="element text medium" type="text" maxlength="255">
</div>
- </li>
+ </li>
<li>
- <label class="description" for="element_5">Twitter:</label>
+ <label class="description" for="profile_website">Website:</label>
<div>
- <input id="element_5" name="element_5" class="element text medium" type="text" maxlength="255" value="@"/>
+ <input id="profile_website" name="website" class="element text medium" type="text" maxlength="255">
+ </div>
+ </li>
+ <li>
+ <label class="description" for="profile_twitter">Twitter:</label>
+ <div>
+ <input id="profile_twitter" name="twitter" class="element text medium" type="text" maxlength="255">
</div>
</li>
<li>
- <label class="description" for="element_4">Facebook:</label>
+ <label class="description" for="profile_facebook">Facebook:</label>
<div>
- <input id="element_4" name="element_4" class="element text medium" type="text" maxlength="255" value="http://"/>
+ <input id="profile_facebook" name="facebook" class="element text medium" type="text" maxlength="255">
</div>
</li>
<li>
- <label class="description" for="element_1">Upload Avatar:</label>
+ <label class="description" for="profile_avatar">Upload Avatar:</label>
<div>
- <input id="element_1" name="element_1" class="element file" type="file"/>
- </div> <p class="guidelines" id="guide_1"><small>please choose a picture at least 500px wide</small></p>
+ <input id="profile_avatar" name="avatar" class="element file" type="file"/>
+ </div>
+ <p class="guidelines" id="guide_1"><small>please choose a picture at least 500px wide</small></p>
</li>
<li class="section_break">
<h3>Edit Password</h3>
</li>
<li>
- <label class="description" for="element_7">Old Password:</label>
+ <label class="description" for="profile_old_password">Old Password:</label>
<div>
- <input id="element_7" name="element_7" class="element text medium" type="password" maxlength="255" value=""/>
+ <input id="profile_old_password" name="old_password" class="element text medium" type="password" maxlength="255">
</div>
</li>
<li>
- <label class="description" for="element_8">New Password:</label>
+ <label class="description" for="profile_password">New Password:</label>
<div>
- <input id="element_8" name="element_8" class="element text medium" type="password" maxlength="255" value=""/>
+ <input id="profile_password" name="new_password" class="element text medium" type="password" maxlength="255">
</div>
</li>
<li>
- <label class="description" for="element_9">Again!</label>
+ <label class="description" for="profile_new_password2">Again!</label>
<div>
- <input id="element_9" name="element_9" class="element text medium" type="password" maxlength="255" value=""/>
+ <input id="profile_new_password2" class="element text medium" type="password" maxlength="255">
</div>
</li>
<li class="buttons">
<input id="saveForm" class="button_text" type="submit" name="submit" value="Submit" />
</li>
+ <div class="errors">
+ <div>There was a problem with your submission:</div>
+ <div class="errorList"></div>
+ </div>
</ul>
</form>
</div>
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs
index e466f8b..fdb2229 100644
--- a/views/partials/scripts.ejs
+++ b/views/partials/scripts.ejs
@@ -44,6 +44,7 @@
<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.image.js"></script>
<script type="text/javascript" src="/assets/javascripts/ui/ModalView.js"></script>
+<script type="text/javascript" src="/assets/javascripts/ui/ModalFormView.js"></script>
<script type="text/javascript" src="/assets/javascripts/ui/MasterView.js"></script>
<script type="text/javascript" src="/assets/javascripts/ui/SignInModal.js"></script>
<script type="text/javascript" src="/assets/javascripts/ui/SignUpModal.js"></script>