├── keys ├── .gitkeep ├── mg_k │ ├── mg_k_1 │ ├── mg_k_2 │ ├── mg_k_3 │ └── mg_k_4 └── mg_pk │ ├── mg_pk_1 │ ├── mg_pk_2 │ ├── mg_pk_3 │ └── mg_pk_4 ├── app ├── dist │ └── .gitkeep ├── favicon │ └── .gitkeep ├── constants │ ├── index.js │ ├── routes.js │ └── endpoints.js ├── fonts │ └── FF_DIN_Web_Pro │ │ ├── webfonts │ │ ├── 373A54_0_0.eot │ │ ├── 373A54_0_0.ttf │ │ ├── 373A54_0_0.woff │ │ ├── 373A54_0_0.woff2 │ │ ├── 373A54_1_0.eot │ │ ├── 373A54_1_0.ttf │ │ ├── 373A54_1_0.woff │ │ └── 373A54_1_0.woff2 │ │ └── MyFontsWebfontsKit.css ├── styles │ ├── index.js │ ├── devices.js │ ├── global_styles.js │ └── theme.js ├── pages │ ├── admin │ │ ├── index.js │ │ ├── filter.json │ │ ├── document.jsx │ │ ├── configuration.jsx │ │ └── models.jsx │ ├── reader │ │ ├── util.js │ │ ├── index.js │ │ └── components │ │ │ └── index.jsx │ ├── blackout │ │ ├── section_components.jsx │ │ ├── header.jsx │ │ ├── index.jsx │ │ ├── sponsorship.jsx │ │ └── what_is_mhacks.jsx │ ├── dashboard │ │ ├── section_components.jsx │ │ ├── profile_section.jsx │ │ └── application_status_bar.jsx │ ├── logout.jsx │ ├── live │ │ ├── components.jsx │ │ ├── hardware.jsx │ │ ├── index.jsx │ │ ├── link_list.jsx │ │ └── resources.jsx │ ├── index.js │ ├── navigator.jsx │ └── home │ │ ├── section_components.jsx │ │ ├── about.jsx │ │ ├── index.jsx │ │ └── welcome.jsx ├── components │ ├── Container.jsx │ ├── PageContainer.jsx │ ├── Input.jsx │ ├── RoundedButton.jsx │ ├── LabeledTextarea.jsx │ ├── Alert.jsx │ ├── FontAwesome.jsx │ ├── index.js │ ├── LabeledInput.jsx │ ├── ProfilePicture.jsx │ ├── Countdown.jsx │ ├── TabGroup.jsx │ └── InputText.jsx ├── actions │ ├── requests │ │ ├── sponsor.js │ │ ├── announcements.js │ │ ├── subscribe.js │ │ ├── mentor.js │ │ ├── speaker.js │ │ ├── index.js │ │ ├── teams.js │ │ ├── game.js │ │ ├── confirmation.js │ │ ├── configuration.js │ │ ├── profile.js │ │ ├── application.js │ │ ├── reader.js │ │ └── auth.js │ ├── index.js │ └── thunks │ │ ├── sponsor.js │ │ ├── announcements.js │ │ ├── subscribe.js │ │ └── events.js ├── reducers │ ├── initial_states.js │ ├── theme.js │ ├── events.js │ ├── subscribe.js │ ├── sponsor.js │ ├── announcements.js │ ├── index.js │ ├── game.js │ ├── configuration.js │ └── admin.js ├── index-dev.html ├── index.html └── util │ ├── user.js │ └── actions.js ├── static ├── mx │ ├── ios.png │ ├── ai-ml.png │ ├── ar-vr.png │ ├── android.png │ ├── game-dev.png │ ├── hardware.png │ └── web-dev.png ├── m11 │ ├── logo.png │ ├── media.png │ ├── favicon.png │ ├── cortices │ │ ├── web.svg │ │ ├── ios.svg │ │ ├── vr.svg │ │ ├── android.svg │ │ ├── hardware.svg │ │ ├── game.svg │ │ └── ai.svg │ ├── favicon.svg │ └── logo.svg ├── m12 │ ├── logo.png │ ├── media.png │ ├── favicon.png │ ├── logo-landing.png │ ├── background-video.mp4 │ ├── cortices │ │ ├── web.svg │ │ ├── ios.svg │ │ ├── vr.svg │ │ ├── android.svg │ │ ├── hardware.svg │ │ ├── game.svg │ │ └── ai.svg │ └── logo.svg ├── m13 │ ├── logo.png │ ├── media.png │ ├── favicon.png │ ├── landing.png │ ├── background.mp4 │ ├── logo-landing.png │ ├── subtracks │ │ ├── Medical.png │ │ ├── Social.png │ │ ├── Educational.png │ │ ├── Professional.png │ │ └── SocialJustice.png │ └── logo.svg ├── blackout │ ├── orb-1.png │ ├── orb-2.png │ ├── favicon.png │ └── video-placeholder.png ├── icons │ ├── x-logo.png │ ├── quote_end.png │ ├── blackout-logo.png │ ├── play-button.png │ ├── quote_start.png │ └── x-logo-title.png ├── nano │ └── favicon.png ├── backgrounds │ └── night.jpg ├── misc │ ├── states.json │ ├── skills.json │ └── majors.json └── logos │ └── google.svg ├── server ├── responses │ ├── api │ │ ├── shortener.js │ │ ├── deploy.js │ │ ├── scan.js │ │ ├── mentorship.js │ │ ├── application.js │ │ ├── game.js │ │ ├── announcement.js │ │ ├── email.js │ │ ├── auth.js │ │ ├── team.js │ │ └── index.js │ └── middleware │ │ └── auth.js ├── routes │ ├── portal.js │ ├── index.js │ ├── shortener.js │ ├── api │ │ ├── reader.js │ │ ├── email.js │ │ └── location.js │ ├── portal │ │ ├── reader.js │ │ └── sponsor.js │ └── api.js ├── interactors │ ├── qr.js │ ├── crypto.js │ ├── push.js │ ├── newrelic.js │ └── slack.js └── db │ └── model │ ├── Device.js │ ├── Location.js │ ├── Team.js │ ├── Shortener.js │ ├── Floor.js │ ├── MentorshipTicket.js │ ├── ScanEvent.js │ └── Sponsor.js ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── scripts ├── unchained-damage-report └── unchained-deploy ├── CONTRIBUTING.md ├── .babelrc ├── Dockerfile ├── ci └── prettier.sh ├── deploy ├── docker-compose.yml ├── production.yml └── development.yml ├── .travis.yml ├── .dockerignore ├── .gitignore ├── newrelic.js ├── .eslintrc.js └── README.md /keys/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/dist/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/favicon/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /keys/mg_k/mg_k_1: -------------------------------------------------------------------------------- 1 | key-9f799 -------------------------------------------------------------------------------- /keys/mg_k/mg_k_2: -------------------------------------------------------------------------------- 1 | fc9960037 -------------------------------------------------------------------------------- /keys/mg_k/mg_k_3: -------------------------------------------------------------------------------- 1 | 9f2662834 -------------------------------------------------------------------------------- /keys/mg_k/mg_k_4: -------------------------------------------------------------------------------- 1 | ad78deb66 -------------------------------------------------------------------------------- /keys/mg_pk/mg_pk_1: -------------------------------------------------------------------------------- 1 | pubkey-b36 -------------------------------------------------------------------------------- /keys/mg_pk/mg_pk_2: -------------------------------------------------------------------------------- 1 | 42aad749d6 -------------------------------------------------------------------------------- /keys/mg_pk/mg_pk_3: -------------------------------------------------------------------------------- 1 | 2a926bab6d -------------------------------------------------------------------------------- /keys/mg_pk/mg_pk_4: -------------------------------------------------------------------------------- 1 | 1d87699ee -------------------------------------------------------------------------------- /static/mx/ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/mx/ios.png -------------------------------------------------------------------------------- /static/m11/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m11/logo.png -------------------------------------------------------------------------------- /static/m11/media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m11/media.png -------------------------------------------------------------------------------- /static/m12/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m12/logo.png -------------------------------------------------------------------------------- /static/m12/media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m12/media.png -------------------------------------------------------------------------------- /static/m13/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/logo.png -------------------------------------------------------------------------------- /static/m13/media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/media.png -------------------------------------------------------------------------------- /static/mx/ai-ml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/mx/ai-ml.png -------------------------------------------------------------------------------- /static/mx/ar-vr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/mx/ar-vr.png -------------------------------------------------------------------------------- /server/responses/api/shortener.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ERROR: 'URL not created' 3 | }; 4 | -------------------------------------------------------------------------------- /static/m11/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m11/favicon.png -------------------------------------------------------------------------------- /static/m12/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m12/favicon.png -------------------------------------------------------------------------------- /static/m13/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/favicon.png -------------------------------------------------------------------------------- /static/m13/landing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/landing.png -------------------------------------------------------------------------------- /static/mx/android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/mx/android.png -------------------------------------------------------------------------------- /static/mx/game-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/mx/game-dev.png -------------------------------------------------------------------------------- /static/mx/hardware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/mx/hardware.png -------------------------------------------------------------------------------- /static/mx/web-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/mx/web-dev.png -------------------------------------------------------------------------------- /static/blackout/orb-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/blackout/orb-1.png -------------------------------------------------------------------------------- /static/blackout/orb-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/blackout/orb-2.png -------------------------------------------------------------------------------- /static/icons/x-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/icons/x-logo.png -------------------------------------------------------------------------------- /static/m13/background.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/background.mp4 -------------------------------------------------------------------------------- /static/nano/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/nano/favicon.png -------------------------------------------------------------------------------- /static/blackout/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/blackout/favicon.png -------------------------------------------------------------------------------- /static/icons/quote_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/icons/quote_end.png -------------------------------------------------------------------------------- /static/m12/logo-landing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m12/logo-landing.png -------------------------------------------------------------------------------- /static/m13/logo-landing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/logo-landing.png -------------------------------------------------------------------------------- /server/responses/api/deploy.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | EXECUTING: 'Executing request to deploy: ' 3 | }; 4 | -------------------------------------------------------------------------------- /static/backgrounds/night.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/backgrounds/night.jpg -------------------------------------------------------------------------------- /static/icons/blackout-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/icons/blackout-logo.png -------------------------------------------------------------------------------- /static/icons/play-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/icons/play-button.png -------------------------------------------------------------------------------- /static/icons/quote_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/icons/quote_start.png -------------------------------------------------------------------------------- /static/icons/x-logo-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/icons/x-logo-title.png -------------------------------------------------------------------------------- /static/m12/background-video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m12/background-video.mp4 -------------------------------------------------------------------------------- /static/m13/subtracks/Medical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/subtracks/Medical.png -------------------------------------------------------------------------------- /static/m13/subtracks/Social.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/subtracks/Social.png -------------------------------------------------------------------------------- /static/blackout/video-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/blackout/video-placeholder.png -------------------------------------------------------------------------------- /static/m13/subtracks/Educational.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/subtracks/Educational.png -------------------------------------------------------------------------------- /static/m13/subtracks/Professional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/subtracks/Professional.png -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Bug 2 | ### Expected function 3 | 4 | ### Actual function 5 | 6 | ### Steps to reproduce the bug 7 | -------------------------------------------------------------------------------- /static/m13/subtracks/SocialJustice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/static/m13/subtracks/SocialJustice.png -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes # . 2 | 3 | ### PR Description 4 | 5 | ### What needs to be reviewed? 6 | 7 | ### Context? 8 | -------------------------------------------------------------------------------- /app/constants/index.js: -------------------------------------------------------------------------------- 1 | import routes from './routes'; 2 | import endpoints from './endpoints'; 3 | 4 | export { routes, endpoints }; 5 | -------------------------------------------------------------------------------- /server/responses/api/scan.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | TOO_MANY_VALIDATIONS: 'This code has been validated too many times.' 3 | }; 4 | -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.eot -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.ttf -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.woff -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_0_0.woff2 -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.eot -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.ttf -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.woff -------------------------------------------------------------------------------- /app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhacks/mhacks-web/HEAD/app/fonts/FF_DIN_Web_Pro/webfonts/373A54_1_0.woff2 -------------------------------------------------------------------------------- /server/responses/middleware/auth.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | UNAUTHORIZED: 'Unauthorized', 3 | USER_ALREADY_CONNECTED: 'User is already connected.' 4 | }; 5 | -------------------------------------------------------------------------------- /app/styles/index.js: -------------------------------------------------------------------------------- 1 | import Theme from './theme.js'; 2 | import devices from './devices.js'; 3 | import GlobalStyle from './global_styles.js'; 4 | 5 | export { Theme, devices, GlobalStyle }; 6 | -------------------------------------------------------------------------------- /scripts/unchained-damage-report: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd ~/mhacks-web/ && git status && git --no-pager log --stat -n 2 4 | 5 | cd ~/mhacks-web/deploy/ && /opt/bin/docker-compose -f production.yml logs --tail 100 -------------------------------------------------------------------------------- /server/responses/api/mentorship.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | MENTOR_ALREADY_ASSIGNED: 'A mentor is already assigned to this ticket', 3 | ONE_TICKET: 'You may only have one incomplete ticket at a time.' 4 | }; 5 | -------------------------------------------------------------------------------- /app/pages/admin/index.js: -------------------------------------------------------------------------------- 1 | import Model from './model.jsx'; 2 | import Models from './models.jsx'; 3 | import ModelForm from './modelform.jsx'; 4 | 5 | export default { 6 | Model, 7 | Models, 8 | ModelForm 9 | }; 10 | -------------------------------------------------------------------------------- /app/pages/admin/filter.json: -------------------------------------------------------------------------------- 1 | { 2 | "search": { 3 | "type": 0, 4 | "label": "Search", 5 | "placeholder": "By name, uni, email, anything", 6 | "required": false, 7 | "key": "search" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/pages/reader/util.js: -------------------------------------------------------------------------------- 1 | import { parse } from 'json2csv'; 2 | import fileDownload from 'react-file-download'; 3 | 4 | export function generateCSV(arr, fileName) { 5 | const csvString = parse(arr); 6 | fileDownload(csvString, fileName); 7 | } 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # PRs 2 | Pull requests are welcome from all. They will be test against our CI and linter to ensure it meets our coding standards. After which, it will be reviewed and will either be merged or changes requested by one of the project leads. 3 | -------------------------------------------------------------------------------- /app/components/Container.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Container = styled.div` 4 | width: calc(100% - 60px); 5 | max-width: 1200px; 6 | margin: 0 auto; 7 | z-index: 98; 8 | `; 9 | 10 | export default Container; 11 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [[ 3 | "@babel/preset-env", 4 | { 5 | "useBuiltIns": "usage", 6 | "corejs": 3 7 | } 8 | ], "@babel/preset-react"], 9 | "plugins": ["@babel/plugin-proposal-object-rest-spread"] 10 | } 11 | -------------------------------------------------------------------------------- /app/pages/reader/index.js: -------------------------------------------------------------------------------- 1 | import Hacker from './hacker.jsx'; 2 | import Mentor from './mentor.jsx'; 3 | import Speaker from './speaker.jsx'; 4 | import Sponsor from './sponsor.jsx'; 5 | 6 | export default { 7 | Hacker, 8 | Mentor, 9 | Speaker, 10 | Sponsor 11 | }; 12 | -------------------------------------------------------------------------------- /app/components/PageContainer.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const verticalMargin = 80; 4 | 5 | const PageContainer = styled.div` 6 | margin: ${verticalMargin}px auto 0 auto; 7 | height: 100%; 8 | width: 100%; 9 | `; 10 | 11 | export default PageContainer; 12 | -------------------------------------------------------------------------------- /app/components/Input.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Input = styled.input` 4 | height: 36px; 5 | width: 100%; 6 | padding-left: 10px; 7 | border: 1px solid #ccc; 8 | border-radius: 4px; 9 | font-size: 1em; 10 | `; 11 | 12 | export default Input; 13 | -------------------------------------------------------------------------------- /server/routes/portal.js: -------------------------------------------------------------------------------- 1 | var router = require('express').Router(), 2 | adminHandler = require('./portal/admin.js'), 3 | sponsorHandler = require('./portal/sponsor.js'), 4 | readerHandler = require('./portal/reader.js'); 5 | 6 | router.use('/admin', adminHandler); 7 | router.use('/sponsor', sponsorHandler); 8 | router.use('/reader', readerHandler); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12 2 | 3 | LABEL maintainer="MHacks Team " 4 | 5 | ARG NODE_ENV 6 | ENV NODE_ENV $NODE_ENV 7 | WORKDIR /usr/src/app 8 | 9 | RUN npm install -g nodemon 10 | RUN npm install mailgun-js 11 | 12 | ADD yarn.lock . 13 | ADD package.json . 14 | 15 | RUN yarn install 16 | 17 | ADD . . 18 | 19 | RUN yarn run build 20 | 21 | CMD ["yarn", "start"] 22 | EXPOSE 3000 23 | -------------------------------------------------------------------------------- /app/actions/requests/sponsor.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | import { endpoints } from '../../constants'; 3 | 4 | export default class SponsorRequests { 5 | static loadSponsors() { 6 | return fetch(endpoints.SPONSOR, { 7 | method: 'get', 8 | headers: new Headers({ 9 | 'Content-Type': 'application/json' 10 | }) 11 | }); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/actions/requests/announcements.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | import { endpoints } from '../../constants'; 3 | 4 | export default class AnnouncementsRequests { 5 | static loadAnnouncements() { 6 | return fetch(endpoints.ANNOUNCEMENTS, { 7 | method: 'get', 8 | headers: new Headers({ 9 | 'Content-Type': 'application/json' 10 | }) 11 | }); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/pages/blackout/section_components.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const SectionHeader = styled.h2` 4 | font-size: 50px; 5 | text-transform: uppercase; 6 | color: ${props => props.theme.teal}; 7 | text-shadow: 0px 0px 50px ${props => props.theme.teal}; 8 | `; 9 | 10 | const SectionBody = styled.p` 11 | color: white; 12 | font-size: 20px; 13 | `; 14 | 15 | export { SectionHeader, SectionBody }; 16 | -------------------------------------------------------------------------------- /server/responses/api/application.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ALREADY_SUBMITTED: 'You have already submitted an application', 3 | NOT_ACCEPTED: 'You have not been accepted to the hackathon yet!', 4 | NOT_CONFIRMED: 'You have not confirmed your application yet!', 5 | NOT_SUBMITTED: 'You have not submitted your application yet!', 6 | ALREADY_REGISTERED: 'You have already registered!', 7 | APPLICATION_CLOSED: 'Applications are now closed.' 8 | }; 9 | -------------------------------------------------------------------------------- /app/actions/requests/subscribe.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | import { endpoints } from '../../constants'; 3 | 4 | export default class SubscribeRequests { 5 | static subscribe(body) { 6 | return fetch(endpoints.SUBSCRIBE, { 7 | method: 'post', 8 | headers: new Headers({ 9 | 'Content-Type': 'application/json' 10 | }), 11 | body: JSON.stringify(body) 12 | }); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /server/responses/api/game.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NO_ANSWERS: 3 | 'You must fill out the questionnaire before attempting to scan users', 4 | INCORRECT_ANSWER: 5 | 'This user does not have the required answer for this quest', 6 | ALREADY_SCANNED: 'You have already scanned this user', 7 | SELF_SCAN: 'You cannot scan yourself!', 8 | SCANS_DISABLED: 'Scans are currently disabled', 9 | RESPONSES_DISABLED: 'Responses are currently disabled' 10 | }; 11 | -------------------------------------------------------------------------------- /app/pages/dashboard/section_components.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const SectionHeader = styled.h2` 4 | font-size: 25px; 5 | color: ${props => props.theme.primary}; 6 | text-transform: uppercase; 7 | //display: inline; 8 | margin-bottom: 5px; 9 | `; 10 | 11 | const SectionBody = styled.p` 12 | color: ${props => props.theme.primary}; 13 | font-size: 16px; 14 | max-width: 600px; 15 | `; 16 | 17 | export { SectionHeader, SectionBody }; 18 | -------------------------------------------------------------------------------- /app/components/RoundedButton.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const RoundedButton = styled.button` 4 | padding: 10px 0; 5 | border-radius: 20px; 6 | background-color: transparent; 7 | color: ${props => props.color}; 8 | font-weight: 500; 9 | font-size: 16px; 10 | padding: 8px 60px; 11 | border: 3px solid ${props => props.color}; 12 | 13 | &:hover { 14 | background-color: ${props => props.color}; 15 | color: white; 16 | ${props => props.hover}; 17 | } 18 | `; 19 | 20 | export default RoundedButton; 21 | -------------------------------------------------------------------------------- /app/pages/logout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AuthThunks } from '../actions'; 3 | import { routes } from '../constants'; 4 | import { connect } from 'react-redux'; 5 | import { replace } from 'connected-react-router'; 6 | 7 | class Logout extends React.Component { 8 | componentDidMount() { 9 | this.props.dispatch(AuthThunks.logout()); 10 | window.localStorage.clear(); 11 | this.props.dispatch(replace(routes.HOME)); 12 | } 13 | 14 | render() { 15 | return
; 16 | } 17 | } 18 | 19 | export default connect()(Logout); 20 | -------------------------------------------------------------------------------- /app/actions/requests/mentor.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../../constants'; 2 | import { getResponseFromRoute, postFormData } from '../../util/actions.js'; 3 | 4 | export default class MentorRequests { 5 | static uploadApplication(token, body, files) { 6 | return postFormData(endpoints.MENTOR_APPLICATION, token, body, files); 7 | } 8 | 9 | static loadApplication() { 10 | return getResponseFromRoute(endpoints.MENTOR_APPLICATION); 11 | } 12 | 13 | static loadForm() { 14 | return getResponseFromRoute(endpoints.MENTOR_APPLICATION_FORM); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/actions/requests/speaker.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../../constants'; 2 | import { getResponseFromRoute, postFormData } from '../../util/actions.js'; 3 | 4 | export default class SpeakerRequests { 5 | static uploadApplication(token, body, files) { 6 | return postFormData(endpoints.SPEAKER_APPLICATION, token, body, files); 7 | } 8 | 9 | static loadApplication() { 10 | return getResponseFromRoute(endpoints.SPEAKER_APPLICATION); 11 | } 12 | 13 | static loadForm() { 14 | return getResponseFromRoute(endpoints.SPEAKER_APPLICATION_FORM); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | var router = require('express').Router(), 2 | path = require('path'), 3 | portalHandler = require('./portal.js'); 4 | 5 | router.get('/logo.png', function(req, res) { 6 | res.sendFile(path.join(__dirname, '../../build/logo.png')); 7 | }); 8 | 9 | router.get('/logo-title.png', function(req, res) { 10 | res.sendFile(path.join(__dirname, '../../build/logo-title.png')); 11 | }); 12 | 13 | router.get('/logo-media.png', function(req, res) { 14 | res.sendFile(path.join(__dirname, '../../build/logo-media.png')); 15 | }); 16 | 17 | router.use('/portal', portalHandler); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /static/m11/cortices/web.svg: -------------------------------------------------------------------------------- 1 | Asset 6 -------------------------------------------------------------------------------- /static/m12/cortices/web.svg: -------------------------------------------------------------------------------- 1 | Asset 6 -------------------------------------------------------------------------------- /scripts/unchained-deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd ~/mhacks-web/ && git pull 4 | 5 | cd deploy/ && \ 6 | /opt/bin/docker-compose -f production.yml pull --ignore-pull-failures && \ 7 | /opt/bin/docker-compose -f production.yml build --pull mhacks_website mhacks_shortener && \ 8 | /opt/bin/docker-compose -f production.yml up --no-deps -d mhacks_website mhacks_shortener 9 | 10 | docker rm -v $(docker ps --filter status=exited -q 2>/dev/null) 2>/dev/null 11 | docker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2>/dev/null 12 | 13 | docker system prune -a --volumes -f 14 | 15 | cd ~/mhacks-web/ && git --no-pager log --stat -n 2 16 | -------------------------------------------------------------------------------- /server/responses/api/announcement.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | PERMISSIONS_REQUIRED: 'You do not have the correct permissions.', 3 | PARAMS_NOT_FOUND: 'Unauthorized, some fields not set.', 4 | UNKNOWN_ERROR: 5 | 'There was an error with the request, please try again later', 6 | METHOD_NOT_ALLOWED: 'Method not allowed', 7 | SUCCESSFUL_AUTH: 'Successfully authenticated', 8 | INVALID_PASSWORD: 9 | 'Unauthorized, email and password combination is invalid.', 10 | USER_NOT_FOUND: 'Unauthorized, email and password combination is invalid.', 11 | USER_EXISTS: 'You are not allowed to register with that email.' 12 | }; 13 | -------------------------------------------------------------------------------- /ci/prettier.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true; do 4 | output=$(prettier --single-quote --trailing-comma none --tab-width 4 "{app,config,server}/**/*.js*" "*.js" -l) 5 | echo "$output" 6 | 7 | if [ -n "$output" ] 8 | then 9 | read -t 10 -p "Do you wish to run prettier on these files? [y/n]" yn 10 | 11 | case $yn in 12 | [Yy]* ) prettier --single-quote --trailing-comma none --tab-width 4 "{app,config,server}/**/*.js*" "*.js" --write; exit $?;; 13 | [Nn]* ) exit 1;; 14 | * ) echo "Please answer yes or no.";; 15 | esac 16 | 17 | exit 1; 18 | else 19 | exit 0; 20 | fi 21 | done -------------------------------------------------------------------------------- /static/m11/cortices/ios.svg: -------------------------------------------------------------------------------- 1 | Asset 5 -------------------------------------------------------------------------------- /static/m12/cortices/ios.svg: -------------------------------------------------------------------------------- 1 | Asset 5 -------------------------------------------------------------------------------- /app/components/LabeledTextarea.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const InputField = styled.div` 5 | width: 100%; 6 | margin: 10px 0; 7 | display: flex; 8 | flex-direction: column; 9 | justify-content: space-between; 10 | 11 | textarea { 12 | padding: 10px; 13 | border-color: rgb(215, 215, 215); 14 | flex-grow: 1; 15 | height: 120px; 16 | border-radius: 5px; 17 | } 18 | `; 19 | 20 | const LabeledTextarea = props => ( 21 | 22 |

{props.label}

23 | {React.Children.toArray(props.children)} 24 |
25 | ); 26 | 27 | export default LabeledTextarea; 28 | -------------------------------------------------------------------------------- /server/interactors/qr.js: -------------------------------------------------------------------------------- 1 | var qrcode = require('qrcode'), 2 | config = require('../../config/default.js'), 3 | options = { 4 | scale: 20, 5 | color: { 6 | dark: config.color_dark, 7 | light: config.color_light 8 | } 9 | }; 10 | 11 | function generateQRCode(text, cb) { 12 | qrcode.toDataURL(text, options, cb); 13 | } 14 | 15 | function generateQRCodeString(text, cb) { 16 | qrcode.toString(text, options, cb); 17 | } 18 | 19 | function writeQRCodeToStream(text, stream) { 20 | qrcode.toFileStream(stream, text, options); 21 | } 22 | 23 | module.exports = { 24 | generateQRCode, 25 | writeQRCodeToStream, 26 | generateQRCodeString 27 | }; 28 | -------------------------------------------------------------------------------- /server/responses/api/email.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | METHOD_NOT_ALLOWED: 'Method not allowed', 3 | SUBSCRIBE_SUCCESSFUL: 'Subscribed!', 4 | ALREADY_SUBSCRIBED: 5 | 'You are already subscribed to the list! We will let you know when something new happens!', 6 | UNKNOWN_ERROR: 7 | 'An unknown error occurred. Get in contact at hackathon@umich.edu', 8 | EMAIL_NOT_PROVIDED: 'Please provide a valid email', 9 | MISSING_CONFIG: 'The configuration is missing necessary values', 10 | VERIFICATION_URL_CONSOLE: 11 | 'Access this link in your browser to verify your account:', 12 | PASSWORDRESET_URL_CONSOLE: 13 | 'Access this link in your browser to reset your password:' 14 | }; 15 | -------------------------------------------------------------------------------- /server/responses/api/auth.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | METHOD_NOT_ALLOWED: 'Method not allowed', 3 | SUCCESSFUL_AUTH: 'Successfully authenticated', 4 | INVALID_PASSWORD: 5 | 'Unauthorized, email and password combination is invalid.', 6 | USER_NOT_FOUND: 'Unauthorized, email and password combination is invalid.', 7 | UNKNOWN_ERROR: 8 | 'There was an error with the request, please try again later', 9 | PARAMS_NOT_FOUND: 'Unauthorized, required fields are not set.', 10 | USER_EXISTS: 'You are not allowed to register with that email.', 11 | UNAUTHORIZED: 'Unauthorized', 12 | CHECK_EMAIL: 'Check your email for the required link.', 13 | PASSWORD_CHANGED: 'Sucessfully changed password.' 14 | }; 15 | -------------------------------------------------------------------------------- /deploy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | mhacks_db: 4 | image: mongo 5 | restart: always 6 | mhacks_website: 7 | build: 8 | context: .. 9 | image: mhacks_website 10 | environment: 11 | MONGO_HOSTNAME: mhacks_db 12 | restart: always 13 | mhacks_nginx: 14 | image: jwilder/nginx-proxy 15 | volumes: 16 | - /etc/nginx/certs 17 | - /etc/nginx/vhost.d 18 | - /usr/share/nginx/html 19 | - /var/run/docker.sock:/tmp/docker.sock:ro 20 | ports: 21 | - "80:80" 22 | - "443:443" 23 | restart: always 24 | mhacks_nginx_letsencrypt: 25 | image: jrcs/letsencrypt-nginx-proxy-companion 26 | volumes: 27 | - /var/run/docker.sock:/var/run/docker.sock 28 | restart: always -------------------------------------------------------------------------------- /static/misc/states.json: -------------------------------------------------------------------------------- 1 | [ 2 | "AL", 3 | "AK", 4 | "AZ", 5 | "AR", 6 | "CA", 7 | "CO", 8 | "CT", 9 | "DE", 10 | "DC", 11 | "FL", 12 | "GA", 13 | "HI", 14 | "ID", 15 | "IL", 16 | "IN", 17 | "IA", 18 | "KS", 19 | "KY", 20 | "LA", 21 | "ME", 22 | "MT", 23 | "NE", 24 | "NV", 25 | "NH", 26 | "NJ", 27 | "NM", 28 | "NY", 29 | "NC", 30 | "ND", 31 | "OH", 32 | "OK", 33 | "OR", 34 | "MD", 35 | "MA", 36 | "MI", 37 | "MN", 38 | "MS", 39 | "MO", 40 | "PA", 41 | "RI", 42 | "SC", 43 | "SD", 44 | "TN", 45 | "TX", 46 | "UT", 47 | "VT", 48 | "VA", 49 | "WA", 50 | "WV", 51 | "WI", 52 | "WY" 53 | ] -------------------------------------------------------------------------------- /deploy/production.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | mhacks_nginx: 4 | extends: 5 | file: docker-compose.yml 6 | service: mhacks_nginx 7 | mhacks_db: 8 | extends: 9 | file: docker-compose.yml 10 | service: mhacks_db 11 | volumes: 12 | - /data/mongodb:/data/db 13 | mhacks_website: 14 | extends: 15 | file: docker-compose.yml 16 | service: mhacks_website 17 | links: 18 | - mhacks_db 19 | env_file: 20 | - production.env 21 | mhacks_shortener: 22 | extends: 23 | file: docker-compose.yml 24 | service: mhacks_website 25 | links: 26 | - mhacks_db 27 | env_file: 28 | - production.env 29 | environment: 30 | - SERVICE=shortener 31 | - VIRTUAL_HOST=mha.cx 32 | -------------------------------------------------------------------------------- /static/m12/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 13 | 15 | 16 | -------------------------------------------------------------------------------- /static/m13/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 13 | 15 | 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "12" 4 | script: yarn run test 5 | notifications: 6 | slack: 7 | secure: LKVaP+L0XYI3kBovNM02GT7I7S+46XbNSa+St7W85EgX7Zfe1P5lrpd18+HvQXz8NMXZUiJb7y8n+w8uE9Jqi1EKLWocJt7drmtkW2Qd4TfqaKAInB+Ghn6oEFIXBbDb6wDYvoJDAqQnev7DdcpFQRuTW2F4Y6RrcBQ8owRJd+hBlxuwZwQVGWX9/il3y4GzvUx26/30OtJUZ16kMlUBXr+xOjNBzHLg7+tVfQbZKl/zs1QJ/IqrVBXv+oHEAS5eS+jJ1tC9ZP4NjjbnCm2zRurACsQDPMhD/PRFYaTDLL8TQkw7MheKRtG3OvPlYrX8/DwzumLtHHINMXxAAjrA2Vy9xY2Sp/OtHQjHkw9veJolrw2EY2lPJ5HMpon2UhoNZxs3OP7yOobsxTy/BAb6VytEx7Mr+6vManDEjWcKnKo5bPBVL33pC3VViMRaBRIHXyRmFlMposbUG6doKh//sXZVMdr6Z3L57Rw6F1o3tq6HwuDKqD9ZHpsuLl3GcDaFTvkWYLH2KZ3yUhkyuUUasmKxWD3DlMVuJ91ewOMHKMcytBgV0h0OHjCLdWOCTItD7MtzGsISJAD1d8ZPla+KWV7gXVWefk/VqspAo2+2WvsNtrQlQrPzLfGbL41viIZkGn+LPU78qJs2kTh6qDHDZdJyDOutpSDyM48znmSscjI= 8 | -------------------------------------------------------------------------------- /deploy/development.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | mhacks_db: 4 | extends: 5 | file: docker-compose.yml 6 | service: mhacks_db 7 | mhacks_website: 8 | extends: 9 | file: docker-compose.yml 10 | service: mhacks_website 11 | ports: 12 | - "3000:3000" 13 | volumes: 14 | - ..:/usr/src/app 15 | command: sh -c "yarn install && nodemon --ignore app/ app.js" 16 | environment: 17 | - DEBUG 18 | - APIWORK 19 | - MAILCHIMP_TOKEN 20 | - MANDRILL_TOKEN 21 | - HOST 22 | - DEPLOYMENT_SECRET 23 | - AWS_ACCESS_KEY_ID 24 | - AWS_SECRET_ACCESS_KEY 25 | - NEWRELIC_ENABLED 26 | - NEWRELIC_APP_NAME 27 | - NEWRELIC_LICENSE_KEY 28 | - SLACKBOT_TOKEN 29 | links: 30 | - mhacks_db 31 | -------------------------------------------------------------------------------- /app/reducers/initial_states.js: -------------------------------------------------------------------------------- 1 | const defaultState = { 2 | fetching: false, 3 | fetched: false, 4 | error: null 5 | }; 6 | 7 | const arrayState = { 8 | fetching: false, 9 | fetched: false, 10 | error: null, 11 | data: [] 12 | }; 13 | 14 | const objectState = { 15 | fetching: false, 16 | fetched: false, 17 | error: null, 18 | data: {} 19 | }; 20 | 21 | const initialUserState = { 22 | fetching: false, 23 | fetched: false, 24 | error: null, 25 | data: { 26 | isLoggedIn: false, 27 | isEmailVerified: false, 28 | isApplicationSubmitted: false, 29 | token: null, 30 | email: null, 31 | user: {}, 32 | app: {} 33 | } 34 | }; 35 | 36 | export { defaultState, arrayState, objectState, initialUserState }; 37 | -------------------------------------------------------------------------------- /static/m11/cortices/vr.svg: -------------------------------------------------------------------------------- 1 | Asset 3 -------------------------------------------------------------------------------- /static/m12/cortices/vr.svg: -------------------------------------------------------------------------------- 1 | Asset 3 -------------------------------------------------------------------------------- /static/misc/skills.json: -------------------------------------------------------------------------------- 1 | [ 2 | ".Net", 3 | "Android Development", 4 | "Arduino", 5 | "ASP", 6 | "Bash", 7 | "C", 8 | "C#", 9 | "C++", 10 | "CSS", 11 | "Data Testing", 12 | "Database Experience", 13 | "Eclipse", 14 | "Hadoop", 15 | "Hive", 16 | "HTML", 17 | "iOS Development", 18 | "Java", 19 | "JavaScript", 20 | "JUnit", 21 | "LaTeX", 22 | "LINDO", 23 | "Linux Development", 24 | "Mac OSX Development", 25 | "MATLAB", 26 | "MySQL", 27 | "Node.js", 28 | "Objective C", 29 | "Oozie", 30 | "Perl", 31 | "PHP", 32 | "Python", 33 | "R", 34 | "Ruby", 35 | "SASS", 36 | "SQL", 37 | "Sqoop", 38 | "Swift", 39 | "Visual C++", 40 | "Web Development", 41 | "Windows Development" 42 | ] -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | build/* 40 | !build/.gitkeep 41 | 42 | .idea/ 43 | 44 | .vscode/ 45 | -------------------------------------------------------------------------------- /app/constants/routes.js: -------------------------------------------------------------------------------- 1 | // react-router routes 2 | export default { 3 | HOME: '/', 4 | SUBSCRIBE: '/subscribe', 5 | LOGIN: '/login', 6 | LOGOUT: '/logout', 7 | APPLY: '/apply', 8 | PROFILE: '/profile', 9 | DASHBOARD: '/dashboard', 10 | GAME: '/game', 11 | LIVE: '/live', 12 | HACKER_READER: '/reader/hacker', 13 | MENTOR_READER: '/reader/mentor', 14 | SPEAKER_READER: '/reader/speaker', 15 | SPONSOR_READER: '/reader/sponsor', 16 | CONFIRM: '/confirm', 17 | ADMIN: '/admin', 18 | ADMIN_PORTAL: '/portal/admin', 19 | READER_PORTAL: '/portal/reader', 20 | SPONSOR_PORTAL: '/portal/sponsor', 21 | MENTOR_APPLICATION: '/mentor/apply', 22 | SPEAKER_APPLICATION: '/speaker/apply', 23 | TEAM_BUILDING: '/blueprinting', 24 | PASSWORD_RESET: '/auth/passwordreset' 25 | }; 26 | -------------------------------------------------------------------------------- /app/actions/requests/index.js: -------------------------------------------------------------------------------- 1 | export { default as SubscribeRequests } from './subscribe.js'; 2 | export { default as AuthRequests } from './auth.js'; 3 | export { default as ProfileRequests } from './profile.js'; 4 | export { default as ApplicationRequests } from './application.js'; 5 | export { default as AnnouncementsRequests } from './announcements.js'; 6 | export { default as ConfigurationRequests } from './configuration.js'; 7 | export { default as ReaderRequests } from './reader.js'; 8 | export { default as ConfirmationRequests } from './confirmation.js'; 9 | export { default as SponsorRequests } from './sponsor.js'; 10 | export { default as MentorRequests } from './mentor.js'; 11 | export { default as SpeakerRequests } from './speaker.js'; 12 | export { default as TeamsRequests } from './teams.js'; 13 | export { default as GameRequests } from './game.js'; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | build/* 40 | !build/.gitkeep 41 | 42 | .idea/ 43 | 44 | *.env 45 | 46 | .vscode/ 47 | 48 | !keys/.gitkeep 49 | -------------------------------------------------------------------------------- /newrelic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var localConfig = require('./config/default.js'); 3 | 4 | /** 5 | * New Relic agent configuration. 6 | * 7 | * See lib/config.default.js in the agent distribution for a more complete 8 | * description of configuration variables and their potential values. 9 | */ 10 | exports.config = { 11 | /** 12 | * Array of application names. 13 | */ 14 | app_name: [localConfig.newrelic_app_name], 15 | /** 16 | * Your New Relic license key. 17 | */ 18 | license_key: localConfig.newrelic_license_key, 19 | logging: { 20 | /** 21 | * Level at which to log. 'trace' is most useful to New Relic when diagnosing 22 | * issues with the agent, 'info' and higher will impose the least overhead on 23 | * production applications. 24 | */ 25 | level: 'info' 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /app/pages/live/components.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { devices } from '../../styles'; 3 | 4 | const SectionWrapper = styled.div` 5 | height: 100%; 6 | border-radius: 20px; 7 | padding: 20px; 8 | background: ${props => 9 | props.theme.generateBackgroundGradient( 10 | 45, 11 | 0.2, 12 | props.theme.highlightOpposite, 13 | props.theme.highlightSecondaryOpposite 14 | )}; 15 | `; 16 | 17 | const SectionHeader = styled.h3` 18 | color: ${props => props.theme.highlight}; 19 | text-align: center; 20 | text-transform: uppercase; 21 | font-size: 20px; 22 | font-weight: bold; 23 | margin: 0 0 20px 0; 24 | 25 | ${devices.small` 26 | font-size: 24px; 27 | `}; 28 | `; 29 | 30 | export default { 31 | SectionWrapper, 32 | SectionHeader 33 | }; 34 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'eslint:recommended', 3 | parserOptions: { 4 | ecmaVersion: 9, 5 | ecmaFeatures: { 6 | jsx: true, 7 | experimentalObjectRestSpread: true 8 | }, 9 | sourceType: 'module' 10 | }, 11 | env: { 12 | es6: true, 13 | browser: true, 14 | node: true 15 | }, 16 | globals: { 17 | Promise: false 18 | }, 19 | plugins: ['react'], 20 | rules: { 21 | 'no-console': 0, 22 | 'new-cap': 0, 23 | strict: 0, 24 | 'no-underscore-dangle': 0, 25 | 'no-use-before-define': 0, 26 | 'eol-last': 0, 27 | quotes: [2, 'single'], 28 | 'jsx-quotes': [1, 'prefer-double'], 29 | 'react/jsx-no-undef': 1, 30 | 'react/jsx-uses-react': 1, 31 | 'react/jsx-uses-vars': 1 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /app/pages/admin/document.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import styled from 'styled-components'; 4 | import { PageContainer } from '../../components'; 5 | //import { AdminThunks } from '../../actions'; 6 | 7 | const PagePulled = styled(PageContainer)` 8 | min-height: calc(100vh - 146px); 9 | `; 10 | 11 | /* Page Component */ 12 | class Document extends React.Component { 13 | render() { 14 | const document = this.props.document; 15 | 16 | return ( 17 | 18 |

{document.id}

19 |
20 | ); 21 | } 22 | } 23 | 24 | function mapStateToProps(state) { 25 | return { 26 | theme: state.theme.data, 27 | adminState: state.adminState 28 | }; 29 | } 30 | 31 | export default connect(mapStateToProps)(Document); 32 | -------------------------------------------------------------------------------- /server/routes/shortener.js: -------------------------------------------------------------------------------- 1 | var router = require('express').Router(), 2 | Shortener = require('../db/model/Shortener.js'), 3 | config = require('../../config/default.js'); 4 | 5 | router.get('/', function(req, res) { 6 | res.redirect(config.host); 7 | }); 8 | 9 | router.get('/:id', function(req, res) { 10 | if (req.params.id) { 11 | Shortener.find() 12 | .byShortCode(req.params.id) 13 | .then(short_url => { 14 | if (short_url) { 15 | res.redirect(short_url.long_url); 16 | short_url.click(req.headers['x-forwarded-for'] || req.ip); 17 | } else { 18 | res.redirect(config.host); 19 | } 20 | }) 21 | .catch(() => { 22 | res.redirect(config.host); 23 | }); 24 | } 25 | }); 26 | 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /app/components/Alert.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const Wrapper = styled.div` 5 | color: ${props => props.color}; 6 | background-color: ${props => props.backgroundColor}; 7 | text-align: center; 8 | border-radius: 10px; 9 | `; 10 | 11 | const Message = styled.p` 12 | padding: 10px; 13 | margin: 0; 14 | `; 15 | 16 | class Alert extends React.Component { 17 | render() { 18 | // default to negative colors 19 | var backgroundColor = '#ffbaba'; 20 | var color = '01ff70'; 21 | 22 | if (this.props.positive) { 23 | backgroundColor = '#01ff70'; 24 | } 25 | 26 | return ( 27 | 28 | {this.props.message} 29 | 30 | ); 31 | } 32 | } 33 | 34 | export default Alert; 35 | -------------------------------------------------------------------------------- /app/components/FontAwesome.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const Wrapper = styled.div` 5 | text-align: center; 6 | `; 7 | 8 | const Icon = styled.i` 9 | height: 100%; 10 | margin: auto; 11 | `; 12 | 13 | class FontAwesome extends React.Component { 14 | render() { 15 | return ( 16 | 17 | 24 | 25 | ); 26 | } 27 | } 28 | 29 | FontAwesome.defaultProps = { 30 | brand: false, 31 | style: {}, 32 | name: '', 33 | size: '1x' 34 | }; 35 | 36 | export default FontAwesome; 37 | -------------------------------------------------------------------------------- /app/styles/devices.js: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | 3 | // device media queries for non-mobile -- design mobile first 4 | export default { 5 | tiny: (...args) => 6 | css` 7 | @media (min-width: 192px) { 8 | ${css(...args)}; 9 | } 10 | `, 11 | small: (...args) => 12 | css` 13 | @media (min-width: 576px) { 14 | ${css(...args)}; 15 | } 16 | `, 17 | tablet: (...args) => 18 | css` 19 | @media (min-width: 768px) { 20 | ${css(...args)}; 21 | } 22 | `, 23 | desktop: (...args) => 24 | css` 25 | @media (min-width: 992px) { 26 | ${css(...args)}; 27 | } 28 | `, 29 | giant: (...args) => 30 | css` 31 | @media (min-width: 1200px) { 32 | ${css(...args)}; 33 | } 34 | ` 35 | }; 36 | -------------------------------------------------------------------------------- /app/reducers/theme.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../actions'; 2 | import { objectState } from './initial_states.js'; 3 | import { Theme } from '../styles'; 4 | 5 | const defaultTheme = { 6 | ...objectState, 7 | data: Theme 8 | }; 9 | 10 | export function theme(state = defaultTheme, action) { 11 | switch (action.type) { 12 | case actions.GET_THEME_REQUEST: 13 | return { ...state, fetching: true, fetched: false, error: null }; 14 | case actions.GET_THEME_ERROR: 15 | return { 16 | ...state, 17 | fetching: false, 18 | fetched: false, 19 | error: action.error.status 20 | }; 21 | case actions.RETURN_THEME: 22 | return { 23 | ...state, 24 | fetching: false, 25 | fetched: true, 26 | data: action.data 27 | }; 28 | default: 29 | return state; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /static/m11/favicon.svg: -------------------------------------------------------------------------------- 1 | MHacksFavicon -------------------------------------------------------------------------------- /app/actions/requests/teams.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../../constants'; 2 | import { 3 | getResponseFromRoute, 4 | postRequest, 5 | deleteRequest 6 | } from '../../util/actions.js'; 7 | 8 | export default class TeamsRequests { 9 | static loadTeams() { 10 | return getResponseFromRoute(endpoints.TEAM_BUILDING); 11 | } 12 | 13 | static createTeam(token, body) { 14 | return postRequest(endpoints.TEAM_BUILDING, token, body); 15 | } 16 | 17 | static deleteTeam(token, body) { 18 | return deleteRequest(endpoints.TEAM_BUILDING, token, body); 19 | } 20 | 21 | static joinTeam(token, body) { 22 | return postRequest(endpoints.TEAM_BUILDING + 'member', token, body); 23 | } 24 | 25 | static leaveTeam(token, body) { 26 | return deleteRequest(endpoints.TEAM_BUILDING + 'member', token, body); 27 | } 28 | 29 | static loadTeamForm() { 30 | return getResponseFromRoute(endpoints.TEAM_BUILDING_FORM); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /static/m11/logo.svg: -------------------------------------------------------------------------------- 1 | Asset 8 -------------------------------------------------------------------------------- /app/pages/live/hardware.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { connect } from 'react-redux'; 4 | 5 | import Components from './components.jsx'; 6 | const { SectionWrapper, SectionHeader } = Components; 7 | 8 | const P = styled.p` 9 | color: ${props => props.theme.highlight}; 10 | `; 11 | 12 | class Hardware extends React.Component { 13 | render() { 14 | return ( 15 | 16 | Hardware 17 |

18 | Come learn more about MHacks 12 hardware at our hardware 19 | table! 20 |

21 |
22 | ); 23 | } 24 | } 25 | 26 | function mapStateToProps(state) { 27 | return { 28 | theme: state.theme.data, 29 | configurationState: state.configurationState 30 | }; 31 | } 32 | 33 | export default connect(mapStateToProps)(Hardware); 34 | -------------------------------------------------------------------------------- /app/actions/requests/game.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | import { endpoints } from '../../constants'; 3 | 4 | export default class GameRequests { 5 | static loadQuestions(token) { 6 | return fetch(endpoints.GAME_QUESTIONS, { 7 | method: 'get', 8 | headers: new Headers({ 9 | Authorization: 'Bearer ' + token 10 | }) 11 | }); 12 | } 13 | 14 | static loadGameState(token) { 15 | return fetch(endpoints.GAME, { 16 | method: 'get', 17 | headers: new Headers({ 18 | Authorization: 'Bearer ' + token 19 | }) 20 | }); 21 | } 22 | 23 | static uploadAnswers(token, answers) { 24 | return fetch(endpoints.GAME, { 25 | method: 'post', 26 | headers: new Headers({ 27 | 'Content-Type': 'application/json', 28 | Authorization: 'Bearer ' + token 29 | }), 30 | body: JSON.stringify({ answers: answers }) 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/pages/index.js: -------------------------------------------------------------------------------- 1 | import Navigator from './navigator.jsx'; 2 | import BlackoutPage from './blackout'; 3 | import HomePage from './home'; 4 | import Login from './login.jsx'; 5 | import Logout from './logout.jsx'; 6 | import EditProfile from './edit_profile.jsx'; 7 | import Dashboard from './dashboard'; 8 | import Game from './game.jsx'; 9 | import Apply from './apply.jsx'; 10 | import LivePage from './live'; 11 | import Reader from './reader'; 12 | import Confirm from './confirm'; 13 | import MentorApply from './mentor/apply'; 14 | import SpeakerApply from './speaker/apply'; 15 | import AdminPage from './admin'; 16 | import TeamBuilding from './team_building'; 17 | import PasswordReset from './passwordreset'; 18 | 19 | export { 20 | Navigator, 21 | HomePage, 22 | BlackoutPage, 23 | Login, 24 | Logout, 25 | EditProfile, 26 | Dashboard, 27 | Game, 28 | Apply, 29 | LivePage, 30 | Reader, 31 | Confirm, 32 | MentorApply, 33 | SpeakerApply, 34 | AdminPage, 35 | TeamBuilding, 36 | PasswordReset 37 | }; 38 | -------------------------------------------------------------------------------- /app/reducers/events.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../actions'; 2 | import { arrayState } from './initial_states.js'; 3 | 4 | export function eventsState(state = arrayState, action) { 5 | switch (action.type) { 6 | case actions.LOAD_EVENTS_REQUEST: 7 | return { 8 | ...state, 9 | fetching: true, 10 | fetched: false, 11 | error: null 12 | }; 13 | 14 | case actions.LOAD_EVENTS_ERROR: 15 | return { 16 | ...state, 17 | fetching: false, 18 | fetched: false, 19 | error: action.error, 20 | message: action.message 21 | }; 22 | 23 | case actions.LOAD_EVENTS_SUCCESS: 24 | return { 25 | ...state, 26 | fetching: false, 27 | fetched: true, 28 | data: action.data, 29 | message: action.message 30 | }; 31 | 32 | default: 33 | return state; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/reducers/subscribe.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../actions'; 2 | import { objectState } from './initial_states.js'; 3 | 4 | export function subscribeState(state = objectState, action) { 5 | switch (action.type) { 6 | case actions.SUBSCRIBE_REQUEST: 7 | return { 8 | ...state, 9 | fetching: true, 10 | fetched: false, 11 | error: null 12 | }; 13 | 14 | case actions.SUBSCRIBE_ERROR: 15 | return { 16 | ...state, 17 | fetching: false, 18 | fetched: false, 19 | error: action.error, 20 | message: action.message 21 | }; 22 | 23 | case actions.SUBSCRIBE_SUCCESS: 24 | return { 25 | ...state, 26 | fetching: false, 27 | fetched: true, 28 | data: action.data, 29 | message: action.message 30 | }; 31 | 32 | default: 33 | return state; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/reducers/sponsor.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../actions'; 2 | import { arrayState } from './initial_states.js'; 3 | 4 | export function sponsorState(state = arrayState, action) { 5 | switch (action.type) { 6 | case actions.LOAD_SPONSOR_REQUEST: 7 | return { 8 | ...state, 9 | fetching: true, 10 | fetched: false, 11 | error: null 12 | }; 13 | 14 | case actions.LOAD_SPONSOR_ERROR: 15 | return { 16 | ...state, 17 | fetching: false, 18 | fetched: false, 19 | error: action.error, 20 | message: action.message 21 | }; 22 | 23 | case actions.LOAD_SPONSOR_SUCCESS: 24 | return { 25 | ...state, 26 | fetching: false, 27 | fetched: true, 28 | data: action.data, 29 | message: action.message 30 | }; 31 | 32 | default: 33 | return state; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/pages/navigator.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { ThemeProvider } from 'styled-components'; 4 | import { withRouter } from 'react-router-dom'; 5 | import { IntlProvider } from 'react-intl'; 6 | import Header from './header.jsx'; 7 | import Footer from './footer.jsx'; 8 | 9 | class Navigator extends React.Component { 10 | render() { 11 | return ( 12 | 13 | 14 |
15 | {this.props.renderHeaderFooter ?
: null} 16 | {React.Children.toArray(this.props.children)} 17 | {this.props.renderHeaderFooter ?
: null} 18 |
19 |
20 |
21 | ); 22 | } 23 | } 24 | 25 | function mapStateToProps(state) { 26 | return { 27 | theme: state.theme.data 28 | }; 29 | } 30 | 31 | export default withRouter(connect(mapStateToProps)(Navigator)); 32 | -------------------------------------------------------------------------------- /app/pages/blackout/header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { Container } from '../../components'; 5 | 6 | const HeaderLogoImage = require('../../../static/icons/blackout-logo.png'); 7 | 8 | /* Header Section */ 9 | const HeaderWrapper = styled.div` 10 | display: flex; 11 | height: 90px; 12 | align-items: center; 13 | justify-content: center; 14 | `; 15 | 16 | const HeaderLogoWrapper = styled.div` 17 | display: flex; 18 | align-items: center; 19 | height: 90%; 20 | `; 21 | 22 | const HeaderLogo = styled.img` 23 | height: 90px; 24 | display: block; 25 | `; 26 | 27 | class BlackoutHeader extends React.Component { 28 | render() { 29 | return ( 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ); 38 | } 39 | } 40 | 41 | export default BlackoutHeader; 42 | -------------------------------------------------------------------------------- /app/reducers/announcements.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../actions'; 2 | import { arrayState } from './initial_states.js'; 3 | 4 | export function announcementsState(state = arrayState, action) { 5 | switch (action.type) { 6 | case actions.LOAD_ANNOUNCEMENTS_REQUEST: 7 | return { 8 | ...state, 9 | fetching: true, 10 | fetched: false, 11 | error: null 12 | }; 13 | 14 | case actions.LOAD_ANNOUNCEMENTS_ERROR: 15 | return { 16 | ...state, 17 | fetching: false, 18 | fetched: false, 19 | error: action.error, 20 | message: action.message 21 | }; 22 | 23 | case actions.LOAD_ANNOUNCEMENTS_SUCCESS: 24 | return { 25 | ...state, 26 | fetching: false, 27 | fetched: true, 28 | data: action.data, 29 | message: action.message 30 | }; 31 | 32 | default: 33 | return state; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { connectRouter } from 'connected-react-router'; 3 | 4 | import { theme } from './theme.js'; 5 | import { subscribeState } from './subscribe.js'; 6 | import { userState } from './user.js'; 7 | import { announcementsState } from './announcements.js'; 8 | import { configurationState } from './configuration.js'; 9 | import { readerState } from './reader.js'; 10 | import { sponsorState } from './sponsor.js'; 11 | import { eventsState } from './events.js'; 12 | import { teamsState } from './teams.js'; 13 | import { adminState } from './admin.js'; 14 | import { mentorshipState } from './mentorship.js'; 15 | import { gameState } from './game.js'; 16 | 17 | export default history => 18 | combineReducers({ 19 | router: connectRouter(history), 20 | theme, 21 | subscribeState, 22 | userState, 23 | announcementsState, 24 | configurationState, 25 | readerState, 26 | sponsorState, 27 | eventsState, 28 | teamsState, 29 | adminState, 30 | mentorshipState, 31 | gameState 32 | }); 33 | -------------------------------------------------------------------------------- /app/actions/index.js: -------------------------------------------------------------------------------- 1 | export { default as actions } from './pure'; 2 | 3 | export { default as SubscribeThunks } from './thunks/subscribe.js'; 4 | export { default as AuthThunks } from './thunks/auth.js'; 5 | export { default as ProfileThunks } from './thunks/profile.js'; 6 | export { default as ApplicationThunks } from './thunks/application.js'; 7 | export { default as AnnouncementsThunks } from './thunks/announcements.js'; 8 | export { default as ConfigurationThunks } from './thunks/configuration.js'; 9 | export { default as ReaderThunks } from './thunks/reader.js'; 10 | export { default as ConfirmationThunks } from './thunks/confirmation.js'; 11 | export { default as SponsorThunks } from './thunks/sponsor.js'; 12 | export { default as MentorThunks } from './thunks/mentor.js'; 13 | export { default as SpeakerThunks } from './thunks/speaker.js'; 14 | export { default as EventsThunks } from './thunks/events.js'; 15 | export { default as TeamsThunks } from './thunks/teams.js'; 16 | export { default as AdminThunks } from './thunks/admin.js'; 17 | export { default as MentorshipThunks } from './thunks/mentorship.js'; 18 | export { default as GameThunks } from './thunks/game.js'; 19 | -------------------------------------------------------------------------------- /app/index-dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | MHacks 24 | 25 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /app/actions/requests/confirmation.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | import { endpoints } from '../../constants'; 3 | 4 | export default class ConfirmationRequests { 5 | static uploadConfirmation(token, body) { 6 | return fetch(endpoints.CONFIRMATION, { 7 | method: 'post', 8 | headers: new Headers({ 9 | 'Content-Type': 'application/json', 10 | Authorization: 'Bearer ' + token 11 | }), 12 | body: JSON.stringify(body) 13 | }); 14 | } 15 | 16 | static loadConfirmation(token) { 17 | return fetch(endpoints.CONFIRMATION, { 18 | method: 'get', 19 | headers: new Headers({ 20 | 'Content-Type': 'application/json', 21 | Authorization: 'Bearer ' + token 22 | }) 23 | }); 24 | } 25 | 26 | static loadForm(token) { 27 | return fetch(endpoints.FORM + 'confirmation', { 28 | method: 'get', 29 | headers: new Headers({ 30 | 'Content-Type': 'application/json', 31 | Authorization: 'Bearer ' + token 32 | }) 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/actions/requests/configuration.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | import { endpoints } from '../../constants'; 3 | 4 | export default class ConfigurationRequests { 5 | static loadConfiguration(token) { 6 | return fetch(endpoints.CONFIGURATION, { 7 | method: 'get', 8 | headers: new Headers({ 9 | 'Content-Type': 'application/json', 10 | Authorization: 'Bearer ' + token 11 | }) 12 | }); 13 | } 14 | 15 | static updateConfiguration(token, body) { 16 | return fetch(endpoints.CONFIGURATION + '/control', { 17 | method: 'post', 18 | headers: new Headers({ 19 | 'Content-Type': 'application/json', 20 | Authorization: 'Bearer ' + token 21 | }), 22 | body: JSON.stringify(body) 23 | }); 24 | } 25 | 26 | static loadForm(token) { 27 | return fetch(endpoints.FORM + 'configuration', { 28 | method: 'get', 29 | headers: new Headers({ 30 | 'Content-Type': 'application/json', 31 | Authorization: 'Bearer ' + token 32 | }) 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /server/responses/api/team.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | PERMISSIONS_REQUIRED: 'You do not have the correct permissions.', 3 | PARAMS_NOT_FOUND: 'Unauthorized, some fields not set.', 4 | UNKNOWN_ERROR: 5 | 'There was an error with the request, please try again later', 6 | METHOD_NOT_ALLOWED: 'Method not allowed', 7 | SUCCESSFUL_AUTH: 'Successfully authenticated', 8 | INVALID_PASSWORD: 9 | 'Unauthorized, email and password combination is invalid.', 10 | USER_NOT_FOUND: 'Unauthorized, email and password combination is invalid.', 11 | USER_EXISTS: 'You are not allowed to register with that email.', 12 | TEAM_FULL: 'The team you are trying to join is full or does not exist', 13 | TEAM_EMPTY: 'You cannot leave a team if you are the only member', 14 | NOT_LEADER: 'You are not the leader of this team', 15 | DESCRIPTION_SHORT: 'Team descriptions must be at least 40 characters', 16 | NOT_A_NOOB: 'You must be a novice to join this team', 17 | NOT_ACCEPTED: 'You have not been accepted to MHacks', 18 | NOT_QUALIFIED_NOOB: 19 | 'This team already has 4 members and is not qualified for adopt a noob', 20 | USER_IN_TEAM: 'You are already in a team' 21 | }; 22 | -------------------------------------------------------------------------------- /server/responses/api/index.js: -------------------------------------------------------------------------------- 1 | var authResponses = require('./auth.js'), 2 | emailResponses = require('./email.js'), 3 | applicationResponse = require('./application.js'), 4 | deployResponse = require('./deploy.js'), 5 | shortenerResponse = require('./shortener.js'), 6 | mentorshipResponse = require('./mentorship.js'), 7 | scanResponse = require('./scan.js'), 8 | gameResponse = require('./game.js'); 9 | 10 | var Responses = { 11 | METHOD_NOT_ALLOWED: 'Method not allowed', 12 | UNKNOWN_ERROR: 13 | 'An unknown error occurred. Get in contact at hackathon@umich.edu', 14 | MISSING_CONFIG: 'The configurations is missing necessary values', 15 | NOT_FOUND: 'Not found', 16 | INVALID_TYPE: 'Invalid type.', 17 | MISSING_PARAMETERS: 'Missing some required fields', 18 | CREATED: 'Created successfully', 19 | UPDATED: 'Updated successfully' 20 | }; 21 | 22 | Responses.Auth = authResponses; 23 | Responses.Email = emailResponses; 24 | Responses.Deploy = deployResponse; 25 | Responses.Application = applicationResponse; 26 | Responses.Shortener = shortenerResponse; 27 | Responses.Scan = scanResponse; 28 | Responses.Mentorship = mentorshipResponse; 29 | Responses.Game = gameResponse; 30 | module.exports = Responses; 31 | -------------------------------------------------------------------------------- /app/actions/thunks/sponsor.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../../actions'; 2 | import { SponsorRequests } from '../requests'; 3 | 4 | export default class SponsorThunks { 5 | static loadSponsors() { 6 | return dispatch => { 7 | dispatch({ type: actions.LOAD_SPONSOR_REQUEST }); 8 | return SponsorRequests.loadSponsors().then(response => { 9 | if (response.status === 200) { 10 | response.json().then(json => { 11 | const { sponsors, sponsorsList } = json; 12 | dispatch({ 13 | type: actions.LOAD_SPONSOR_SUCCESS, 14 | data: { sponsors, sponsorsList }, 15 | message: json.message 16 | }); 17 | }); 18 | } else { 19 | response.json().then(json => { 20 | dispatch({ 21 | type: actions.LOAD_SPONSOR_ERROR, 22 | error: response.status, 23 | message: json.message 24 | }); 25 | }); 26 | } 27 | }); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/actions/thunks/announcements.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../../actions'; 2 | import { AnnouncementsRequests } from '../requests'; 3 | 4 | export default class AnnouncementsThunks { 5 | static loadAnnouncements() { 6 | return dispatch => { 7 | dispatch({ type: actions.LOAD_ANNOUNCEMENTS_REQUEST }); 8 | return AnnouncementsRequests.loadAnnouncements().then(response => { 9 | if (response.status === 200) { 10 | response.json().then(json => { 11 | const { announcements } = json; 12 | dispatch({ 13 | type: actions.LOAD_ANNOUNCEMENTS_SUCCESS, 14 | data: announcements, 15 | message: json.message 16 | }); 17 | }); 18 | } else { 19 | response.json().then(json => { 20 | dispatch({ 21 | type: actions.LOAD_ANNOUNCEMENTS_ERROR, 22 | error: response.status, 23 | message: json.message 24 | }); 25 | }); 26 | } 27 | }); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/actions/thunks/subscribe.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../../actions'; 2 | import { SubscribeRequests } from '../requests'; 3 | 4 | export default class SubscribeThunks { 5 | static subscribe(email) { 6 | return dispatch => { 7 | dispatch({ 8 | type: actions.SUBSCRIBE_REQUEST, 9 | data: email 10 | }); 11 | 12 | return SubscribeRequests.subscribe({ email }).then(response => { 13 | if (response.status === 200) { 14 | response.json().then(json => { 15 | dispatch({ 16 | type: actions.SUBSCRIBE_SUCCESS, 17 | data: email, 18 | message: json.message 19 | }); 20 | }); 21 | } else { 22 | response.json().then(json => { 23 | dispatch({ 24 | type: actions.SUBSCRIBE_ERROR, 25 | data: email, 26 | error: response.status, 27 | message: json.message 28 | }); 29 | }); 30 | } 31 | }); 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /server/interactors/crypto.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'), 2 | config = require('../../config/default.js'), 3 | secret = crypto 4 | .createHash('sha256') 5 | .update(String(config.secret)) 6 | .digest('base64') 7 | .substr(0, 32), 8 | algo = 'aes-256-ctr'; 9 | 10 | function encrypt(text) { 11 | const iv = crypto.randomBytes(16); 12 | const cipher = crypto.createCipheriv(algo, secret, iv); 13 | let crypted = cipher.update(text, 'utf8', 'hex'); 14 | crypted += cipher.final('hex'); 15 | return Buffer.from(iv.toString('hex') + ':' + crypted).toString('base64'); 16 | } 17 | 18 | function decrypt(text) { 19 | const parts = Buffer.from(text, 'base64') 20 | .toString('ascii') 21 | .split(':'); 22 | const iv = Buffer.from(parts[0], 'hex'); 23 | const cipherText = parts[1]; 24 | const decipher = crypto.createDecipheriv(algo, secret, iv); 25 | let dec = decipher.update(cipherText, 'hex', 'utf8'); 26 | dec += decipher.final('utf8'); 27 | return dec; 28 | } 29 | 30 | function createHmac(secret, body) { 31 | return crypto 32 | .createHmac('sha1', secret) 33 | .update(body) 34 | .digest('hex'); 35 | } 36 | 37 | module.exports = { 38 | encrypt, 39 | decrypt, 40 | createHmac 41 | }; 42 | -------------------------------------------------------------------------------- /static/m11/cortices/android.svg: -------------------------------------------------------------------------------- 1 | Asset 7 -------------------------------------------------------------------------------- /static/m12/cortices/android.svg: -------------------------------------------------------------------------------- 1 | Asset 7 -------------------------------------------------------------------------------- /app/pages/home/section_components.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { devices } from '../../styles'; 3 | import theme from '../../styles/theme'; 4 | 5 | const CenteredContainer = styled.div` 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | 10 | width: calc(100% - 60px); 11 | max-width: 1200px; 12 | margin: 0 auto; 13 | 14 | z-index: 98; 15 | 16 | ${devices.tablet` 17 | width: calc(100% - 100px); 18 | `} ${devices.desktop` 19 | width: calc(100% - 140px); 20 | `} ${devices.giant` 21 | width: calc(100% - 160px); 22 | `}; 23 | `; 24 | 25 | const SectionHeader = styled.h2` 26 | display: block; 27 | font-size: 48px; 28 | font-weight: 900; 29 | min-width: 100%; 30 | text-align: center; 31 | color: ${theme.highlight}; 32 | padding-top: 50px; 33 | text-transform: uppercase; 34 | 35 | ${devices.tiny` 36 | font-size: 32px; 37 | `}; 38 | `; 39 | 40 | const SectionBody = styled.p` 41 | color: white; 42 | font-size: 16px; 43 | max-width: 600px; 44 | `; 45 | 46 | const Brick = styled.div` 47 | width: 100px; 48 | height: 12px; 49 | background: ${props => props.theme.highlight}; 50 | `; 51 | 52 | export { CenteredContainer, SectionHeader, SectionBody, Brick }; 53 | -------------------------------------------------------------------------------- /server/interactors/push.js: -------------------------------------------------------------------------------- 1 | var PushNotifications = require('node-pushnotifications'), 2 | config = require('../../config/default.js'), 3 | crypto = require('./crypto.js'), 4 | push; 5 | 6 | if (config.push_notifications.enabled) { 7 | push = new PushNotifications({ 8 | gcm: { 9 | id: crypto.decrypt(config.push_notifications.gcm.id) 10 | }, 11 | apn: { 12 | token: { 13 | key: crypto.decrypt(config.push_notifications.apns.key), 14 | keyId: crypto.decrypt(config.push_notifications.apns.key_id), 15 | teamId: crypto.decrypt(config.push_notifications.apns.team_id) 16 | }, 17 | production: config.push_notifications.apns.production 18 | } 19 | }); 20 | } 21 | 22 | function sendNotification(devices, title, message) { 23 | if (config.push_notifications.enabled) { 24 | var data = { 25 | title: title, 26 | body: message, 27 | retries: 5, 28 | topic: config.push_notifications.apns.topic 29 | }; 30 | 31 | return push.send(devices, data); 32 | } else { 33 | return new Promise(resolve => { 34 | resolve(true); 35 | }); 36 | } 37 | } 38 | 39 | module.exports = { 40 | sendNotification 41 | }; 42 | -------------------------------------------------------------------------------- /app/components/index.js: -------------------------------------------------------------------------------- 1 | import TextSubmit from './TextSubmit.jsx'; 2 | import Container from './Container.jsx'; 3 | import VideoPlayer from './VideoPlayer.jsx'; 4 | import ExpandingItem from './ExpandingItem.jsx'; 5 | import TabGroup from './TabGroup.jsx'; 6 | import RoundedButton from './RoundedButton.jsx'; 7 | import FileUpload from './FileUpload.jsx'; 8 | import Alert from './Alert.jsx'; 9 | import LabeledInput from './LabeledInput.jsx'; 10 | import LabeledTextarea from './LabeledTextarea.jsx'; 11 | import PageContainer from './PageContainer.jsx'; 12 | import Countdown from './Countdown.jsx'; 13 | import ProfilePicture from './ProfilePicture.jsx'; 14 | import MHForm from './MHForm.jsx'; 15 | import Input from './Input.jsx'; 16 | import InputText from './InputText'; 17 | import SponsorLogos from './SponsorLogos'; 18 | import FullScreenAnimation from './FullScreenAnimation.jsx'; 19 | import FontAwesome from './FontAwesome.jsx'; 20 | 21 | export { 22 | TextSubmit, 23 | Container, 24 | VideoPlayer, 25 | ExpandingItem, 26 | TabGroup, 27 | RoundedButton, 28 | FileUpload, 29 | Alert, 30 | LabeledInput, 31 | LabeledTextarea, 32 | PageContainer, 33 | Countdown, 34 | ProfilePicture, 35 | InputText, 36 | SponsorLogos, 37 | MHForm, 38 | Input, 39 | FullScreenAnimation, 40 | FontAwesome 41 | }; 42 | -------------------------------------------------------------------------------- /app/actions/requests/profile.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | import { endpoints } from '../../constants'; 3 | import { postFormResponseFromRoute } from '../../util/actions'; 4 | 5 | export default class ProfileRequests { 6 | static loadProfile(token) { 7 | return fetch(endpoints.PROFILE, { 8 | method: 'get', 9 | headers: new Headers({ 10 | 'Content-Type': 'application/json', 11 | Authorization: 'Bearer ' + token 12 | }) 13 | }); 14 | } 15 | 16 | static updateProfile(token, body, files) { 17 | return postFormResponseFromRoute(endpoints.PROFILE, body, files); 18 | } 19 | 20 | static sendVerificationEmail(token, email) { 21 | return fetch(endpoints.VERIFY, { 22 | method: 'post', 23 | headers: new Headers({ 24 | Authorization: 'Bearer ' + token, 25 | 'Content-Type': 'application/json' 26 | }), 27 | body: JSON.stringify({ email }) 28 | }); 29 | } 30 | 31 | static loadForm(token) { 32 | return fetch(endpoints.FORM + 'user', { 33 | method: 'get', 34 | headers: new Headers({ 35 | 'Content-Type': 'application/json', 36 | Authorization: 'Bearer ' + token 37 | }) 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/actions/thunks/events.js: -------------------------------------------------------------------------------- 1 | import { actions } from '../../actions'; 2 | import { endpoints } from '../../constants'; 3 | import { getResponseFromRoute } from '../../util/actions.js'; 4 | 5 | export default class EventsThunks { 6 | static loadEvents() { 7 | return dispatch => { 8 | dispatch({ type: actions.LOAD_EVENTS_REQUEST }); 9 | return getResponseFromRoute(endpoints.EVENTS, false).then( 10 | response => { 11 | if (response.status === 200) { 12 | response.json().then(json => { 13 | const { events } = json; 14 | dispatch({ 15 | type: actions.LOAD_EVENTS_SUCCESS, 16 | data: events, 17 | message: json.message 18 | }); 19 | }); 20 | } else { 21 | response.json().then(json => { 22 | dispatch({ 23 | type: actions.LOAD_EVENTS_ERROR, 24 | error: response.status, 25 | message: json.message 26 | }); 27 | }); 28 | } 29 | } 30 | ); 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/pages/home/about.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { SectionHeader, SectionBody } from './section_components.jsx'; 4 | import { Container } from '../../components'; 5 | 6 | const Wrapper = styled.div` 7 | background: ${props => props.theme.gradientOverlay}, 8 | ${props => props.theme.secondary}; 9 | padding: 80px 0; 10 | `; 11 | 12 | class About extends React.Component { 13 | render() { 14 | return ( 15 | 16 | 17 | About MHacks 18 | 19 | MHacks is a 36-hour hackathon run by University of 20 | Michigan students. At MHacks, we want to help you to 21 | turn your ideas into reality. We’ll give you the 22 | freedom, resources, and mentoring you need to do so and 23 | in return we hope you’ll be as curious, productive, and 24 | passionate as you can be. For newcomers and veterans 25 | alike, MHacks is a weekend experience you won’t want to 26 | miss. 27 | 28 | 29 | 30 | ); 31 | } 32 | } 33 | 34 | export default About; 35 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 28 | 29 | MHacks 30 | 31 | 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /app/util/user.js: -------------------------------------------------------------------------------- 1 | function getGroup(userData, groupName) { 2 | return ( 3 | userData.user && 4 | userData.user.groups && 5 | userData.user.groups.indexOf(groupName) !== -1 6 | ); 7 | } 8 | 9 | export function getUserMetadata(userData) { 10 | return { 11 | isLoggedIn: userData.isLoggedIn === true, 12 | isApplicationSubmitted: userData.isApplicationSubmitted === true, 13 | isApplicationReviewed: userData.user.status !== 'unread', 14 | isAccepted: userData.user.status === 'accepted', 15 | isWaitlisted: userData.user.status === 'waitlisted', 16 | isConfirmed: userData.user.isConfirmed === true, 17 | isEmailVerified: userData.isEmailVerified === true, 18 | isAdmin: getGroup(userData, 'admin'), 19 | isSponsor: getGroup(userData, 'sponsor'), 20 | isReader: getGroup(userData, 'reader'), 21 | needsReimbursement: userData.user.needs_reimbursement === true 22 | }; 23 | } 24 | 25 | export function isMinor(birthdate) { 26 | const now = new Date(); 27 | const birth = new Date(birthdate); 28 | 29 | var age = now.getFullYear() - birth.getFullYear(); 30 | const ageMonth = now.getMonth() - birth.getMonth(); 31 | const ageDay = now.getDate() - birth.getDate(); 32 | 33 | if (ageMonth < 0 || (ageMonth === 0 && ageDay < 0)) { 34 | age = parseInt(age) - 1; 35 | } 36 | 37 | return age < 18; 38 | } 39 | -------------------------------------------------------------------------------- /app/pages/blackout/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { Helmet } from 'react-helmet'; 4 | 5 | import Header from './header.jsx'; 6 | import Hero from './hero.jsx'; 7 | import WhatIsMHacks from './what_is_mhacks.jsx'; 8 | import Faq from './faq.jsx'; 9 | import Sponsorship from './sponsorship.jsx'; 10 | import QuoteSection from './quote_section'; 11 | import Footer from './footer.jsx'; 12 | 13 | const Favicon = require('../../../static/blackout/favicon.png'); 14 | 15 | /* Containers */ 16 | const Page = styled.div` 17 | background-color: black; 18 | width: 100%; 19 | height: 100%; 20 | color: #f1f7ff; 21 | overflowx: hidden; 22 | `; 23 | 24 | /* Styled elements */ 25 | const StyledHero = styled(Hero)` 26 | margin: 35px 0; 27 | `; 28 | 29 | /* Page Component */ 30 | class BlackoutPage extends React.Component { 31 | render() { 32 | return ( 33 | 34 | 35 | MHacks 36 | 37 | 38 | 39 | 40 |
41 | 42 | 43 | 44 | 45 | 46 |