diff --git a/app/pages/apply.jsx b/app/pages/apply.jsx index 39b31c2f..340c91b1 100644 --- a/app/pages/apply.jsx +++ b/app/pages/apply.jsx @@ -190,6 +190,30 @@ class Apply extends React.Component { theme={this.props.theme} onSubmit={this.onSubmit} /> +

+ By applying, you confirm you have read and agree to + the{' '} + + MLH Code of Conduct + + , the{' '} + + MLH Privacy Policy + + , the{' '} + + MLH Contest Terms and Conditions + + , the{' '} + + MHacks Code of Conduct + + , and the{' '} + + MHacks Liability Waiver + + . +

) : null} + {isLoggedIn && isAccepted ? ( + + Confirm + + ) : null} {isLoggedIn ? ( Dashboard diff --git a/deploy/development.yml b/deploy/development.yml index 2e549bd1..13c1c67b 100644 --- a/deploy/development.yml +++ b/deploy/development.yml @@ -25,5 +25,6 @@ services: - NEWRELIC_ENABLED - NEWRELIC_APP_NAME - NEWRELIC_LICENSE_KEY + - SLACKBOT_TOKEN links: - mhacks_db diff --git a/server/db/model/Application.js b/server/db/model/Application.js index df5cc72f..0127c097 100644 --- a/server/db/model/Application.js +++ b/server/db/model/Application.js @@ -406,6 +406,25 @@ var schema = new mongoose.Schema( auth_groups: ['admin', 'reader'] } ] + }, + mlh_coc_agreement: { + type: Boolean, + required: true, + form: { + user_editable: true, + label: 'I have read and agree to the MLH Code of Conduct.', + required_value: true + } + }, + mlh_affiliation_agreement: { + type: Boolean, + required: true, + form: { + user_editable: true, + label: + 'I authorize you to share my application/registration information for event administration, ranking, MLH administration, pre- and post-event informational e-mails, and occasional messages about hackathons in-line with the MLH Privacy Policy. I further agree to the terms of both the MLH Contest Terms and Conditions and the MLH Privacy Policy.', + required_value: true + } } }, defaultEndSchema diff --git a/server/db/model/Confirmation.js b/server/db/model/Confirmation.js index e793bf3d..90a8c991 100644 --- a/server/db/model/Confirmation.js +++ b/server/db/model/Confirmation.js @@ -179,25 +179,6 @@ var schema = new mongoose.Schema( auth_groups: ['admin', 'reader', 'sponsor'] } ] - }, - mlh_coc_agreement: { - type: Boolean, - required: true, - form: { - user_editable: true, - label: 'I have read and agree to the MLH Code of Conduct.', - required_value: true - } - }, - mlh_affiliation_agreement: { - type: Boolean, - required: true, - form: { - user_editable: true, - label: - 'I authorize you to share my application/registration information for event administration, ranking, MLH administration, pre- and post-event informational e-mails, and occasional messages about hackathons in-line with the MLH Privacy Policy. I further agree to the terms of both the MLH Contest Terms and Conditions and the MLH Privacy Policy.', - required_value: true - } } }, defaultEndSchema diff --git a/server/interactors/slack.js b/server/interactors/slack.js index 7bb1b2d5..c38f3ac0 100644 --- a/server/interactors/slack.js +++ b/server/interactors/slack.js @@ -18,7 +18,8 @@ function sendMessage(location, message) { channel: message.channel, text: message.text, blocks: message.blocks - } + }, + json: true }); } } @@ -30,7 +31,8 @@ function createGroupDM(token, users) { form: { token: token, users: users.join() - } + }, + json: true }); } @@ -41,7 +43,20 @@ function getBotUserID(token, bot) { form: { token: token, bot: bot - } + }, + json: true + }); +} + +function getUserForID(token, user_id) { + return request({ + method: 'POST', + uri: 'https://slack.com/api/users.info', + form: { + token: token, + user: user_id + }, + json: true }); } @@ -54,7 +69,8 @@ function postSnippet(token, message) { channels: message.channels, content: message.content, title: message.title - } + }, + json: true }); } @@ -62,5 +78,6 @@ module.exports = { sendMessage, createGroupDM, getBotUserID, + getUserForID, postSnippet }; diff --git a/server/routes/api/mentorshipbot.js b/server/routes/api/mentorshipbot.js index 16e5a7f0..473d057a 100644 --- a/server/routes/api/mentorshipbot.js +++ b/server/routes/api/mentorshipbot.js @@ -2,19 +2,19 @@ var router = require('express').Router(), config = require('../../../config/default.js'), slack = require('../../interactors/slack.js'); -const createBlockWithButton = (user_name, text) => { +const createBlockWithButton = (user_id, user_name, text) => { return JSON.stringify([ { type: 'section', text: { type: 'mrkdwn', - text: formatInquiry(user_name, text) + text: formatInquiry(user_id, text) }, accessory: { type: 'button', text: { type: 'plain_text', - text: `Help User ${user_name}`, + text: `Help User @${user_name}`, emoji: true }, value: 'pair_user_with_mentor' @@ -23,30 +23,43 @@ const createBlockWithButton = (user_name, text) => { ]); }; -const formatInquiry = (user_name, text) => - `*${user_name} wants help with:* ${text}`; +const formatInquiry = (user_id, text) => + `*<@${user_id}> wants help with:* ${text}`; const strikeThroughInquiry = text => `~${text}~`; router.post('/', function(req, res) { let inquiry = req.body || ''; if (inquiry.text && inquiry.command == '/helpmewith') { slack - .sendMessage(config.slackbot_token, { - channel: config.slack_mentorship_channel, - text: inquiry.user_id, // NOTE: using text object is currently the best way to pass this id, but Slack is phasing out usernames. Check API in future. - blocks: createBlockWithButton(inquiry.user_name, inquiry.text) // defines message content and appearance - }) + .getUserForID(config.slackbot_token, inquiry.user_id) .then(response => { - response = JSON.parse(response); - if (!response.ok) throw Error(response.error); - res.send({ - response_type: 'in_channel', - text: `Your inquiry: '${inquiry.text}' was sent to the ${config.slack_mentorship_channel} channel` - }); + slack + .sendMessage(config.slackbot_token, { + channel: config.slack_mentorship_channel, + text: inquiry.user_id, // NOTE: using text object is currently the best way to pass this id, but Slack is phasing out usernames. Check API in future. + blocks: createBlockWithButton( + inquiry.user_id, + response.user.real_name, + inquiry.text + ) // defines message content and appearance + }) + .then(() => { + res.send({ + response_type: 'in_channel', + text: `Your inquiry: '${inquiry.text}' was sent to the ${config.slack_mentorship_channel} channel` + }); + }) + .catch(e => { + console.error(e); + res.status(500).json(e); + }); }) .catch(e => { + console.error(e); res.status(500).json(e); }); + } else { + res.status(400).send({ status: false }); } }); @@ -69,19 +82,13 @@ router.post('/interactions/', function(req, res) { slack .createGroupDM(config.slackbot_token, users) .then(response => { - response = JSON.parse(response); - if (!response.ok) throw Error(response.error); - // Post question in GroupDM. slack .sendMessage(config.slackbot_token, { channel: response.channel.id, - text: `${payload.user.username},\n${inquiry}\nThank you for helping!` + text: `<@${payload.user.id}>,\n\n${inquiry}\n\nThank you for helping!` }) - .then(response => { - response = JSON.parse(response); - if (!response.ok) throw Error(response.error); - + .then(() => { // Cross-out inquiry in mentorship channel slack .sendMessage(payload.response_url, {