diff --git a/lib/database/accounts.js b/lib/database/accounts.js index 21b6c3c3..5799cfb9 100644 --- a/lib/database/accounts.js +++ b/lib/database/accounts.js @@ -81,20 +81,20 @@ module.exports = { } if (typeof name !== "string" || typeof pw !== "string") { - callback(new Error("You must provide a nonempty username and password"), null); + callback("You must provide a nonempty username and password", null); return; } var lname = name.toLowerCase(); if (registrationLock[lname]) { - callback(new Error("There is already a registration in progress for "+name), + callback("There is already a registration in progress for "+name, null); return; } if (!$util.isValidUserName(name)) { - callback(new Error("Invalid username. Usernames may consist of 1-20 " + - "characters a-z, A-Z, 0-9, -, _, and accented letters."), + callback("Invalid username. Usernames may consist of 1-20 " + + "characters a-z, A-Z, 0-9, -, _, and accented letters.", null); return; } @@ -121,7 +121,7 @@ module.exports = { if (taken) { delete registrationLock[lname]; - callback(new Error("Username is already registered"), null); + callback("Username is already registered", null); return; } @@ -161,7 +161,7 @@ module.exports = { } if (typeof name !== "string" || typeof pw !== "string") { - callback(new Error("Invalid username/password combination"), null); + callback("Invalid username/password combination", null); return; } @@ -185,7 +185,7 @@ module.exports = { } if (rows.length === 0) { - callback(new Error("User does not exist"), null); + callback("User does not exist", null); return; } @@ -193,7 +193,7 @@ module.exports = { if (err) { callback(err, null); } else if (!match) { - callback(new Error("Invalid username/password combination"), null); + callback("Invalid username/password combination", null); } else { callback(null, { name: rows[0].name, @@ -212,15 +212,15 @@ module.exports = { if (typeof callback !== "function") { return; } - + if (typeof auth !== "string") { - callback(new Error("Invalid auth string"), null); + callback("Invalid auth string", null); return; } var split = auth.split(":"); if (split.length !== 2) { - callback(new Error("Invalid auth string"), null); + callback("Invalid auth string", null); return; } @@ -235,7 +235,7 @@ module.exports = { } if (rows.length === 0) { - callback(new Error("Auth string does not match an existing user"), null); + callback("Auth string does not match an existing user", null); return; } @@ -256,7 +256,7 @@ module.exports = { } if (typeof name !== "string" || typeof pw !== "string") { - callback(new Error("Invalid username/password combination"), null); + callback("Invalid username/password combination", null); return; } @@ -289,7 +289,7 @@ module.exports = { } if (typeof name !== "string") { - callback(new Error("Invalid username"), null); + callback("Invalid username", null); return; } @@ -298,7 +298,7 @@ module.exports = { if (err) { callback(err, null); } else if (rows.length === 0) { - callback(new Error("User does not exist"), null); + callback("User does not exist", null); } else { callback(null, rows[0].global_rank); } @@ -314,12 +314,12 @@ module.exports = { } if (typeof name !== "string") { - callback(new Error("Invalid username"), null); + callback("Invalid username", null); return; } if (typeof rank !== "number") { - callback(new Error("Invalid rank"), null); + callback("Invalid rank", null); return; } @@ -338,7 +338,7 @@ module.exports = { } if (!(names instanceof Array)) { - callback(new Error("Expected array of names, got " + typeof names), null); + callback("Expected array of names, got " + typeof names, null); return; } @@ -365,7 +365,7 @@ module.exports = { } if (typeof name !== "string") { - callback(new Error("Invalid username"), null); + callback("Invalid username", null); return; } @@ -374,7 +374,7 @@ module.exports = { if (err) { callback(err, null); } else if (rows.length === 0) { - callback(new Error("User does not exist"), null); + callback("User does not exist", null); } else { callback(null, rows[0].email); } @@ -390,12 +390,12 @@ module.exports = { } if (typeof name !== "string") { - callback(new Error("Invalid username"), null); + callback("Invalid username", null); return; } if (typeof email !== "string") { - callback(new Error("Invalid email"), null); + callback("Invalid email", null); return; } @@ -414,7 +414,7 @@ module.exports = { } if (typeof name !== "string") { - callback(new Error("Invalid username"), null); + callback("Invalid username", null); return; } @@ -423,12 +423,18 @@ module.exports = { if (err) { callback(err, null); } else if (rows.length === 0) { - callback(new Error("User does not exist"), null); + callback("User does not exist", null); } else { var userprof = { image: "", text: "" }; + + if (rows[0].profile === "") { + callback(null, userprof); + return; + } + try { var profile = JSON.parse(rows[0].profile); userprof.image = profile.image || ""; @@ -450,12 +456,12 @@ module.exports = { } if (typeof name !== "string") { - callback(new Error("Invalid username"), null); + callback("Invalid username", null); return; } if (typeof profile !== "object") { - callback(new Error("Invalid profile"), null); + callback("Invalid profile", null); return; } @@ -484,7 +490,7 @@ module.exports = { return; } - callback(new Error("generatePasswordReset is not implemented"), null); + callback("generatePasswordReset is not implemented", null); }, recoverPassword: function (hash, callback) { @@ -492,7 +498,7 @@ module.exports = { return; } - callback(new Error("recoverPassword is not implemented"), null); + callback("recoverPassword is not implemented", null); }, /** diff --git a/lib/database/channels.js b/lib/database/channels.js index 691b902c..a0c75de5 100644 --- a/lib/database/channels.js +++ b/lib/database/channels.js @@ -4,7 +4,7 @@ var valid = require("../utilities").isValidChannelName; var blackHole = function () { }; function dropTable(name, callback) { - db.query("DROP TABLE `" + name + "`"); + db.query("DROP TABLE `" + name + "`", callback); } function createRanksTable(name, callback) { @@ -116,7 +116,7 @@ module.exports = { return; } - if (!valid(chan)) { + if (!valid(name)) { callback("Invalid channel name", null); return; } @@ -128,7 +128,12 @@ module.exports = { callback(err, null); return; } - callback(null, rows); + + if (rows.length === 0) { + callback("No such channel", null); + } else { + callback(null, rows[0]); + } }); }, @@ -212,7 +217,7 @@ module.exports = { callback = blackHole; } - if (!valid(chan)) { + if (!valid(name)) { callback("Invalid channel name", null); return; } diff --git a/lib/web/account.js b/lib/web/account.js index 8b238d5d..d17ab2cb 100644 --- a/lib/web/account.js +++ b/lib/web/account.js @@ -167,15 +167,14 @@ function handleChangeEmail(req, res) { * Handles a GET request for /account/channels */ function handleAccountChannelPage(req, res) { - res.send(500); - return; logRequest(req); var loginName = false; if (req.cookies.auth) { loginName = req.cookies.auth.split(':')[0]; } + if (loginName) { - dbchannels.listUserChannels(loginName, function (err, channels) { + db.channels.listUserChannels(loginName, function (err, channels) { sendJade(res, 'account-channels', { loggedIn: true, loginName: loginName, @@ -194,8 +193,6 @@ function handleAccountChannelPage(req, res) { * Handles a POST request to modify a user's channels */ function handleAccountChannel(req, res) { - res.send(500); - return; logRequest(req); var action = req.body.action; switch(action) { @@ -215,26 +212,162 @@ function handleAccountChannel(req, res) { * Handles a request to register a new channel */ function handleNewChannel(req, res) { - res.send(500); + logRequest(req); + + var name = req.body.name; + if (typeof name !== 'string') { + res.send(400); + return; + } + + var loginName = false; + if (req.cookies.auth) { + loginName = req.cookies.auth.split(':')[0]; + } else { + sendJade(res, 'account-channels', { + loggedIn: false, + channels: [] + }); + return; + } + db.users.verifyAuth(req.cookies.auth, function (err, user) { + if (err) { + sendJade(res, 'account-channels', { + loggedIn: false, + channels: [], + newChannelError: err + }); + return; + } + + db.channels.register(name, user.name, function (err, channel) { + db.channels.listUserChannels(loginName, function (err2, channels) { + sendJade(res, 'account-channels', { + loggedIn: true, + loginName: loginName, + channels: err2 ? [] : channels, + newChannelError: err ? err : undefined + }); + }); + }); + }); } /** * Handles a request to delete a new channel */ function handleDeleteChannel(req, res) { + logRequest(req); + + var name = req.body.name; + if (typeof name !== 'string') { + res.send(400); + return; + } + + var loginName = false; + if (req.cookies.auth) { + loginName = req.cookies.auth.split(':')[0]; + } else { + sendJade(res, 'account-channels', { + loggedIn: false, + channels: [], + }); + return; + } + db.users.verifyAuth(req.cookies.auth, function (err, user) { + if (err) { + sendJade(res, 'account-channels', { + loggedIn: false, + channels: [], + deleteChannelError: err + }); + return; + } + + db.channels.lookup(name, function (err, channel) { + if (channel.owner !== user.name && user.global_rank < 255) { + db.channels.listUserChannels(loginName, function (err2, channels) { + sendJade(res, 'account-channels', { + loggedIn: true, + loginName: loginName, + channels: err2 ? [] : channels, + deleteChannelError: 'You do not have permission to delete this channel' + }); + }); + return; + } + db.channels.drop(name, function (err) { + db.channels.listUserChannels(loginName, function (err2, channels) { + sendJade(res, 'account-channels', { + loggedIn: true, + loginName: loginName, + channels: err2 ? [] : channels, + deleteChannelError: err ? err : undefined + }); + }); + }); + }); + }); +} + +/** + * Handles a GET request for /account/profile + */ +function handleAccountProfilePage(req, res) { + logRequest(req); + + var loginName = false; + if (req.cookies.auth) { + loginName = req.cookies.auth.split(':')[0]; + } else { + sendJade(res, 'account-profile', { + loggedIn: false, + profileImage: '', + profileText: '' + }); + return; + } + + db.users.getProfile(loginName, function (err, profile) { + if (err) { + sendJade(res, 'account-profile', { + loggedIn: true, + loginName: loginName, + profileError: err, + profileImage: '', + profileText: '' + }); + return; + } + + sendJade(res, 'account-profile', { + loggedIn: true, + loginName: loginName, + profileImage: profile.image, + profileText: profile.text, + profileError: false + }); + }); +} + +/** + * Handles a POST request to edit a profile + */ +function handleAccountProfile(req, res) { res.send(500); } module.exports = { /** - * Initializes the module - * - * @param app - The Express server to initialize + * Initialize the module */ init: function (app) { app.get('/account/edit', handleAccountEditPage); app.post('/account/edit', handleAccountEdit); app.get('/account/channels', handleAccountChannelPage); app.post('/account/channels', handleAccountChannel); + app.get('/account/profile', handleAccountProfilePage); + app.post('/account/profile', handleAccountProfile); } }; diff --git a/templates/account-channels.jade b/templates/account-channels.jade index 5604b0f1..a173f826 100644 --- a/templates/account-channels.jade +++ b/templates/account-channels.jade @@ -40,6 +40,7 @@ html(lang="en") th form.form-inline.pull-right(action="/account/channels", method="post", onsubmit="return confirm('Are you sure you want to delete #{c.name}? This cannot be undone');") input(type="hidden", name="action", value="delete_channel") + input(type="hidden", name="name", value="#{c.name}") button.btn.btn-xs.btn-danger(type="submit") Delete span.glyphicon.glyphicon-trash a(href="/r/#{c.name}", style="margin-left: 5px")= c.name diff --git a/templates/account-profile.jade b/templates/account-profile.jade new file mode 100644 index 00000000..ec853e04 --- /dev/null +++ b/templates/account-profile.jade @@ -0,0 +1,45 @@ +doctype html +html(lang="en") + head + include head + mixin head() + body + #wrap + nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation") + include nav + mixin navheader() + #nav-collapsible.collapse.navbar-collapse + ul.nav.navbar-nav + mixin navdefaultlinks("/account/profile") + mixin navloginlogout("/account/profile") + section#mainpage + .container + if !loggedIn + .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 + .alert.alert-danger.messagebox.center + strong Authorization Required + p You must be logged in to view this page. + else + .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 + h3 Profile + if profileError + .alert.alert-danger.center.messagebox + strong Profile Error + p= profileError + .media + a.pull-left(href="#") + img.media-object(src=profileImage, alt="Profile Image") + .media-body + = profileText + h3 Edit Profile + form(action="/account/profile", method="post", role="form") + .form-group + label.control-label(for="profileimage") Image + input#profileimage.form-control(type="text", name="image") + .form-group + label.control-label(for="profiletext") Text + textarea#profiletext.form-control(cols="10") + button.btn.btn-primary.btn-block(type="submit") Save + + include footer + mixin footer()