--- /dev/null
+config.env
--- /dev/null
+logs/
+nginx.conf.compiled
+*.lua
+.tup
--- /dev/null
+include_rules
--- /dev/null
+: foreach *.moon |> moonc %f |> %B.lua
--- /dev/null
+-- Doing this allows for the app/ folder to be mounted
+-- via a docker container for faster reloading
+require "app.app"
--- /dev/null
+include_rules
--- /dev/null
+lapis = require "lapis"
+console = require "lapis.console"
+
+import Users from require "models"
+bind = require "utils.binding"
+
+bind\bind 'test', -> 'Test called!!!'
+
+bind\bind_static 'executer', require 'facades.executer'
+bind\bind_static 'crypto', -> require 'services.crypto'
+
+class extends lapis.Application
+ layout: require "views.partials.layout"
+
+ views_prefix: 'views'
+ flows_prefix: 'flows'
+ middleware_prefix: 'middleware'
+
+ @before_filter =>
+ @navbar = {}
+ @navbar.selected = 1
+
+ ['index': "/"]: require "controllers.index"
+ ['account.login': "/login"]: require "controllers.account.login"
+ ['account.logout': "/logout"]: require "controllers.account.logout"
+ ['account.register': "/register"]: require "controllers.account.register"
+
+ ['executer.status_update': "/executer/status_update"]: require "controllers.executer.status_update"
+ ['executer.request': '/executer/request']: require "controllers.executer.request"
+
+ [test: "/test"]: =>
+ "Your value is over 10"
+
+ "/console": console.make!
--- /dev/null
+config = require "lapis.config"
+
+config "development", ->
+ port 8888
+
+ secret (os.getenv 'APP_SECRET')
+ req_secret (os.getenv 'REQ_SECRET')
+
+ postgres ->
+ -- Have to use a fixed ip since the container name
+ -- was not resolving correctly
+ host "192.168.0.2"
+ database (os.getenv 'POSTGRES_DB')
+ user (os.getenv 'POSTGRES_USER')
+ password (os.getenv 'POSTGRES_PASSWORD')
--- /dev/null
+include_rules
--- /dev/null
+include_rules
--- /dev/null
+import make_controller from require "controllers.controller"
+import Users from require 'models'
+import assert_valid from require "lapis.validate"
+
+utils = require "lapis.util"
+
+make_controller
+ inject:
+ crypto: 'crypto'
+
+ middleware: { 'logged_out' }
+
+ get: =>
+ @flow 'csrf_setup'
+ render: 'account.login'
+
+ post: =>
+ @flow 'csrf_validate'
+
+ assert_valid @params, {
+ { "username", exists: true, min_length: 2 }
+ { "password", exists: true, min_length: 2 }
+ }
+
+ users = Users\select "where username = ? limit 1", @params.username
+ if #users > 0
+ if @crypto.verify @params.password, users[1].password_hash
+ @session.user_id = users[1].id
+ return redirect_to: @url_for 'index'
+
+ render: 'account.login'
+
+
--- /dev/null
+import make_controller from require "controllers.controller"
+
+make_controller {
+ get: =>
+ @session.user_id = nil
+ return redirect_to: @url_for 'index'
+}
--- /dev/null
+import make_controller from require "controllers.controller"
+import Users from require 'models'
+import assert_valid from require "lapis.validate"
+import capture_errors from require 'lapis.application'
+
+make_controller
+ inject:
+ crypto: 'crypto'
+
+ middleware: { 'logged_out' }
+
+ get: =>
+ @flow 'csrf_validate'
+ render: 'account.register'
+
+ post: capture_errors =>
+ @flow 'csrf_validate'
+
+ assert_valid @params, {
+ { "username", exists: true, min_length: 2 }
+ { "nickname", exists: true, min_length: 2 }
+ { "email", exists: true, min_length: 4, matches_pattern: "%S+@%S+%.%S+" }
+ { "password", exists: true, min_length: 2 }
+ { "password_confirmation", exists: true, min_length: 2, equals: @params.password, 'Passwords must be the same' }
+ }
+
+ users = Users\find username: @params.username
+ if users
+ -- Account already exists
+ @errors or= {}
+ table.insert @errors, 'Username already taken'
+ return render: 'account.register'
+
+ user_id = Users\create {
+ username: @params.username
+ email: @params.email
+ nickname: @params.nickname
+ password_hash: @crypto.encrypt @params.password
+ }
+
+ unless user_id
+ @errors or= {}
+ table.insert @errors, 'Error creating account'
+ return render: 'account.register'
+
+ @session.user_id = user_id
+ redirect_to: @url_for 'index'
+
--- /dev/null
+import respond_to from require "lapis.application"
+bind = require 'utils.binding'
+
+{
+ make_controller: (routes) ->
+ respond_to {
+ before: =>
+ if routes.inject
+ for inj, dep in pairs routes.inject
+ @[inj] = bind\make dep
+
+ return if not routes.middleware
+
+ for middleware in *routes.middleware
+ require("#{@app.middleware_prefix}.#{middleware}") @
+
+ GET: => routes.get(@)
+ POST: => routes.post(@)
+ }
+}
--- /dev/null
+include_rules
--- /dev/null
+import make_controller from require "controllers.controller"
+import assert_valid from require "lapis.validate"
+import capture_errors from require 'lapis.application'
+
+make_controller
+ inject:
+ executer: 'executer'
+
+ middleware: { 'internal_request' }
+
+ post: capture_errors (=>
+ assert_valid @params, {
+ { 'lang', exists: true }
+ { 'code', exists: true }
+ { 'problem_id', exists: true, is_integer: true }
+ }
+
+ id = @executer\request @params.lang, @params.code
+
+ json: id
+ ), =>
+ json: { status: 'error occured', errors: @errors }
+
+
+
--- /dev/null
+import make_controller from require "controllers.controller"
+
+make_controller
+ middleware: { 'internal_request' }
+
+ post: =>
+ print 'Hit status'
+ json: { status: 'success' }
--- /dev/null
+import make_controller from require "controllers.controller"
+
+import Users, Jobs from require 'models'
+
+make_controller
+ middleware: { 'logged_in' }
+
+ get: =>
+ @users = Users\select!
+ @jobs = @user\get_c_jobs!
+ render: "index"
--- /dev/null
+include_rules
--- /dev/null
+http = require 'lapis.nginx.http'
+import from_json, to_json from require 'lapis.util'
+
+class ExecuterFacade
+ request: (lang, code) =>
+ body = http.simple 'http://192.168.0.4:8080/submit', {
+ lang: lang
+ code: code
+ }
+
+ from_json(body).id
+
+
--- /dev/null
+include_rules
--- /dev/null
+csrf = require "lapis.csrf"
+
+=>
+ @csrf_token = csrf.generate_token @
+ return
--- /dev/null
+csrf = require "lapis.csrf"
+
+=>
+ csrf.assert_token @
+ @csrf_token = csrf.generate_token @
--- /dev/null
+include_rules
--- /dev/null
+config = (require 'lapis.config').get!
+
+=>
+ if @params.request_token != config.req_secret
+ @write {
+ status: 401
+ json: { status: 'Unauthorized' }
+ }
--- /dev/null
+import Users from require 'models'
+
+=>
+ if not @session.user_id
+ @write redirect_to: @url_for 'account.login'
+ return
+
+ @user = Users\find(@session.user_id)
+ if not @user
+ @session.user_id = nil
+ @write redirect_to: @url_for 'account.login'
+ return
--- /dev/null
+import Users from require 'models'
+
+=>
+ if @session.user_id
+ @user = Users\find(@session.user_id)
+ @write redirect_to: @url_for 'index' if @user
--- /dev/null
+import create_table, types from require "lapis.db.schema"
+
+{
+ [1]: =>
+ create_table "users", {
+ { "id", types.serial },
+ { "username", types.varchar },
+ { "password_hash", types.varchar },
+ { "nickname", types.varchar },
+ { "email", types.varchar },
+
+ "PRIMARY KEY (id)"
+ }
+
+ [2]: =>
+ create_table "jobs", {
+ { "id", types.serial },
+ { "user_id", types.foreign_key },
+ { "problem_id", types.foreign_key },
+ { "status", types.text null: true },
+ { "lang", types.varchar },
+ { "code", types.text null: true },
+ { "time_initiated", types.time },
+
+ "PRIMARY KEY (id)"
+ }
+
+ [3]: =>
+ create_table "problems", {
+ { "id", types.serial },
+ { "name", types.varchar },
+ { "kind", types.enum },
+ { "description", types.text null: true },
+ { "time_limit", types.integer },
+
+ "PRIMARY KEY (id)"
+ }
+}
--- /dev/null
+types {
+ text/html html htm shtml;
+ text/css css;
+ text/xml xml;
+ image/gif gif;
+ image/jpeg jpeg jpg;
+ application/x-lua lua;
+ application/x-moonscript moon;
+ application/x-javascript js;
+ application/atom+xml atom;
+ application/rss+xml rss;
+
+ text/mathml mml;
+ text/plain txt;
+ text/vnd.sun.j2me.app-descriptor jad;
+ text/vnd.wap.wml wml;
+ text/x-component htc;
+
+ image/png png;
+ image/tiff tif tiff;
+ image/vnd.wap.wbmp wbmp;
+ image/x-icon ico;
+ image/x-jng jng;
+ image/x-ms-bmp bmp;
+ image/svg+xml svg svgz;
+ image/webp webp;
+
+ application/java-archive jar war ear;
+ application/mac-binhex40 hqx;
+ application/msword doc;
+ application/pdf pdf;
+ application/postscript ps eps ai;
+ application/rtf rtf;
+ application/vnd.ms-excel xls;
+ application/vnd.ms-powerpoint ppt;
+ application/vnd.wap.wmlc wmlc;
+ application/vnd.google-earth.kml+xml kml;
+ application/vnd.google-earth.kmz kmz;
+ application/x-7z-compressed 7z;
+ application/x-cocoa cco;
+ application/x-java-archive-diff jardiff;
+ application/x-java-jnlp-file jnlp;
+ application/x-makeself run;
+ application/x-perl pl pm;
+ application/x-pilot prc pdb;
+ application/x-rar-compressed rar;
+ application/x-redhat-package-manager rpm;
+ application/x-sea sea;
+ application/x-shockwave-flash swf;
+ application/x-stuffit sit;
+ application/x-tcl tcl tk;
+ application/x-x509-ca-cert der pem crt;
+ application/x-xpinstall xpi;
+ application/xhtml+xml xhtml;
+ application/zip zip;
+
+ application/octet-stream bin exe dll;
+ application/octet-stream deb;
+ application/octet-stream dmg;
+ application/octet-stream eot;
+ application/octet-stream iso img;
+ application/octet-stream msi msp msm;
+
+ audio/midi mid midi kar;
+ audio/mpeg mp3;
+ audio/ogg ogg;
+ audio/x-m4a m4a;
+ audio/x-realaudio ra;
+
+ video/3gpp 3gpp 3gp;
+ video/mp4 mp4;
+ video/mpeg mpeg mpg;
+ video/quicktime mov;
+ video/webm webm;
+ video/x-flv flv;
+ video/x-m4v m4v;
+ video/x-mng mng;
+ video/x-ms-asf asx asf;
+ video/x-ms-wmv wmv;
+ video/x-msvideo avi;
+}
--- /dev/null
+import autoload from require "lapis.util"
+autoload "models"
--- /dev/null
+include_rules
--- /dev/null
+import Model from require "lapis.db.model"
+
+class Jobs extends Model
+ @relations: {
+ { 'user', belongs_to: 'Users' }
+ { 'problem', belongs_to: 'Problems' }
+ }
--- /dev/null
+import Model, enum from require "lapis.db.model"
+
+class Problems extends Model
+ @kinds: enum {
+ code: 1
+ golf: 2
+ word: 3
+ }
+
+ @relations: {
+ { "jobs", has_many: 'Jobs' }
+ }
--- /dev/null
+import Model from require "lapis.db.model"
+
+class Users extends Model
+ @relations: {
+ { 'jobs', has_many: 'Jobs' }
+ { 'c_jobs'
+ has_many: 'Jobs'
+ where: { lang: 'C' }
+ }
+ }
--- /dev/null
+worker_processes ${{NUM_WORKERS}};
+error_log stderr notice;
+daemon off;
+pid logs/nginx.pid;
+
+events {
+ worker_connections 1024;
+}
+
+env APP_SECRET;
+env REQ_SECRET;
+env POSTGRES_DB;
+env POSTGRES_USER;
+env POSTGRES_PASSWORD;
+
+http {
+ include mime.types;
+
+ server {
+ listen ${{PORT}};
+ lua_code_cache ${{CODE_CACHE}};
+
+ location / {
+ set $_url "http://192.168.0.4:8080";
+
+ default_type text/html;
+ content_by_lua '
+ require("lapis").serve("app")
+ ';
+ }
+
+ location /static/ {
+ alias static/;
+ }
+
+ location /favicon.ico {
+ alias static/favicon.ico;
+ }
+ location /proxy {
+ internal;
+ rewrite_by_lua "
+ local req = ngx.req
+
+ for k,v in pairs(req.get_headers()) do
+ if k ~= 'content-length' then
+ req.clear_header(k)
+ end
+ end
+
+ if ngx.ctx.headers then
+ for k,v in pairs(ngx.ctx.headers) do
+ req.set_header(k, v)
+ end
+ end
+ ";
+
+ resolver 8.8.8.8;
+ proxy_http_version 1.1;
+ proxy_pass $_url;
+ }
+ }
+}
--- /dev/null
+include_rules
--- /dev/null
+bcrypt = require "bcrypt"
+
+import Users from require "models"
+
+ROUNDS = 10
+
+{
+ encrypt: (data) ->
+ bcrypt.digest(data, ROUNDS)
+
+ verify: (data, digest) ->
+ bcrypt.verify(data, digest)
+}
+
--- /dev/null
+: scss/core.scss |> sass %f:css/%B.css |> css/%B.css css/%B.css.map
+: coffee/*.coffee |> coffee -c -m -o js/%B.js %f |> js/%B.js js/%B.js.map
--- /dev/null
+main = ->
+ console.log "Hello world!"
--- /dev/null
+.navbar {
+ z-index: 10000;
+ width: 100%;
+ background: #0077c2;
+ height: 47px;
+ position: relative;
+ box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.7);
+ display: grid;
+ grid-template-columns: 1fr 6fr 1fr;
+}
+.navbar .navbar-logo {
+ padding-left: 8px;
+ text-align: center;
+}
+.navbar .navbar-logo img {
+ max-height: calc(47px - 2px);
+ display: inline;
+}
+.navbar ul {
+ display: block;
+ text-align: center;
+ font-size: 0;
+}
+.navbar ul a li {
+ margin: 0;
+ display: inline-block;
+ cursor: pointer;
+ font-size: 24px;
+ list-style: none;
+ line-height: 40px;
+ padding-left: 30px;
+ padding-right: 30px;
+ padding-top: 4px;
+ color: #f2f2f2;
+ border-top-color: #0077c2;
+ transition: 200ms all;
+}
+.navbar ul a li.selected, .navbar ul a li:hover {
+ border-bottom: 2px solid #ffe766;
+ color: white;
+}
+
+.sidebar-problem-list {
+ z-index: 50;
+ box-shadow: 0 10px 0 0 transparent, 0 10px 0 0 transparent, 10px 0 0 0 transparent, 0 8px 8px 2px rgba(0, 0, 0, 0.5);
+ background: #003252;
+ position: relative;
+ min-height: calc(100vh - 47px);
+}
+.sidebar-problem-list .sidebar-problem {
+ width: 100%;
+ display: grid;
+ grid-template-columns: 32px 1fr;
+ border-left-width: 24px;
+ border-left-style: solid;
+ transition: background-color 200ms east-in-out;
+ transition: width 200ms east-in-out;
+ background-color: inherit;
+ cursor: pointer;
+}
+.sidebar-problem-list .sidebar-problem[selected], .sidebar-problem-list .sidebar-problem:hover {
+ width: calc(100% + 24px);
+}
+.sidebar-problem-list .sidebar-problem[selected] {
+ background-color: #42a5f5 !important;
+}
+.sidebar-problem-list .sidebar-problem:hover {
+ background-color: #128ef2;
+}
+.sidebar-problem-list .sidebar-problem-letter {
+ text-align: center;
+ background-color: #001929;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ font-size: 1.2rem;
+}
+.sidebar-problem-list .sidebar-problem-name {
+ text-align: left;
+ font-size: 1.2rem;
+ padding-left: 5px;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ font-size: 16px;
+}
+
+body {
+ font-family: sans-serif;
+ background: url(/static/imgs/grain_background.png);
+ background-color: #111;
+ background-repeat: repeat;
+ color: white;
+}
+
+/*# sourceMappingURL=core.css.map */
--- /dev/null
+{"version":3,"sourceRoot":"","sources":["../scss/_navbar.scss","../scss/_vars.scss","../scss/problem/_sidebar.scss","../scss/core.scss"],"names":[],"mappings":"AAAA;EACC;EACA;EACA,YCIc;EDHd,QCgBe;EDff;EAEA;EAEA;EACA;;AAEA;EACC;EACA;;AAEA;EACC;EACA;;AAIF;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA,kBClCY;EDoCZ;;AAEA;EACC;EACA;;;AE/CJ;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EAEA;EACA;EAEA;EACA;EAEA;EACA;EACA;EAEA;;AAEA;EACC;;AAGD;EACC;;AAGD;EACC;;AAIF;EACC;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;EAEA;EACA;EACA;EAEA;EACA;;;AC9CF;EACC;EACA;EACA;;;AAGD;EACC;;;AAGD;EACC;EAEA;EACA;EACA;EACA","file":"core.css"}
\ No newline at end of file
--- /dev/null
+// Generated by CoffeeScript 2.4.1
+(function() {
+ var main;
+
+ main = function() {
+ return console.log("Hello world!");
+ };
+
+}).call(this);
+
+//# sourceMappingURL=main.js.map
--- /dev/null
+{
+ "version": 3,
+ "file": "main.js",
+ "sourceRoot": "..",
+ "sources": [
+ "coffee/main.coffee"
+ ],
+ "names": [],
+ "mappings": ";AAAA;AAAA,MAAA;;EAAA,IAAA,GAAO,QAAA,CAAA,CAAA;WACN,OAAO,CAAC,GAAR,CAAY,cAAZ;EADM;AAAP",
+ "sourcesContent": [
+ "main = ->\n\tconsole.log \"Hello world!\"\n"
+ ]
+}
\ No newline at end of file
--- /dev/null
+@mixin elevate($e, $col) {
+ box-shadow: 0px $e (3 * $e) ($e / 4) $col;
+}
--- /dev/null
+.navbar {
+ z-index: 10000;
+ width: 100%;
+ background: $primary-dark;
+ height: $navbar-height;
+ position: relative;
+
+ box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.7);
+
+ display: grid;
+ grid-template-columns: 1fr 6fr 1fr;
+
+ .navbar-logo {
+ padding-left: 8px;
+ text-align: center;
+
+ img {
+ max-height: calc(#{$navbar-height} - 2px);
+ display: inline;
+ }
+ }
+
+ ul {
+ display: block;
+ text-align: center;
+ font-size: 0;
+
+ a li {
+ margin: 0;
+ display: inline-block;
+ cursor: pointer;
+
+ font-size: 24px;
+
+ list-style: none;
+ line-height: 40px;
+ padding-left: 30px;
+ padding-right: 30px;
+ padding-top: 4px;
+
+ color: darken($white, 5);
+ border-top-color: $primary-dark;
+
+ transition: 200ms all;
+
+ &.selected, &:hover {
+ border-bottom: 2px solid $secondary-light;
+ color: white;
+ }
+ }
+ }
+}
--- /dev/null
+.content {
+ width: 100%;
+ padding: 10px 5%;
+}
+
+.right {
+ float: right;
+}
+
+.left {
+ float: left;
+}
+
+.hidden {
+ visibility: hidden;
+}
+
+a {
+ text-decoration: none;
+ color: inherit;
+}
--- /dev/null
+$white: #fff;
+$black: #000;
+
+$content-background: #232323;
+
+$primary: #42a5f5;
+$primary-light: #80d6ff;
+$primary-dark: #0077c2;
+
+$secondary: #FFD700;
+$secondary-light: lighten(#FFD700, 20);
+$secondary-dark: darken(#FFD700, 20);
+
+$primary-text: $white;
+$secondary-text: $black;
+
+$test-case-good: #50ff50;
+$test-case-bad: #ff5050;
+$test-case-pending: #5050ff;
+
+$navbar-height: 47px;
--- /dev/null
+@import '_vars';
+@import '_elevate';
+@import '_navbar';
+@import 'problem/_list.scss';
+@import 'problem/_sidebar.scss';
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ font-size: 16px;
+}
+
+body {
+ font-family: sans-serif;
+
+ background: url(/static/imgs/grain_background.png);
+ background-color: #111;
+ background-repeat: repeat;
+ color: white;
+}
--- /dev/null
+.sidebar-problem-list {
+ z-index: 50;
+ box-shadow: 0 10px 0 0 transparent, 0 10px 0 0 transparent, 10px 0 0 0 transparent, 0 8px 8px 2px rgba(0, 0, 0, 0.5);
+ background: darken($primary-dark, 22);
+ position: relative;
+ min-height: calc(100vh - #{$navbar-height});
+
+ .sidebar-problem {
+ width: 100%;
+
+ display: grid;
+ grid-template-columns: 32px 1fr;
+
+ border-left-width: 24px;
+ border-left-style: solid;
+
+ transition: background-color 200ms east-in-out;
+ transition: width 200ms east-in-out;
+ background-color: inherit;
+
+ cursor: pointer;
+
+ &[selected], &:hover {
+ width: calc(100% + 24px);
+ }
+
+ &[selected] {
+ background-color: $primary !important;
+ }
+
+ &:hover {
+ background-color: darken($primary, 10);
+ }
+ }
+
+ .sidebar-problem-letter {
+ text-align: center;
+ background-color: darken($primary-dark, 30);
+ padding-top: 20px;
+ padding-bottom: 20px;
+ font-size: 1.2rem;
+ }
+
+ .sidebar-problem-name {
+ text-align: left;
+ font-size: 1.2rem;
+
+ padding-left: 5px;
+ padding-top: 20px;
+ padding-bottom: 20px;
+
+ margin-left: 10px;
+ margin-right: 10px;
+ }
+}
--- /dev/null
+include_rules
--- /dev/null
+class Binding
+ new: =>
+ @bindings = {}
+ @static_bindings = {}
+ @statics = {}
+
+ bind: (name, service) =>
+ @bindings[name] = service
+
+ bind_static: (name, service) =>
+ @static_bindings[name] = service
+
+ make: (name) =>
+ if @bindings[name]
+ return @bindings[name]()
+ elseif @statics[name]
+ return @statics[name]
+ elseif @static_bindings[name]
+ stat = @static_bindings[name]()
+ @statics[name] = stat
+ return stat
+
+return Binding()
--- /dev/null
+include_rules
--- /dev/null
+include_rules
--- /dev/null
+html = require "lapis.html"
+
+class Login extends html.Widget
+ content: =>
+ h1 style: "background-color:red", "Login!"
+
+ form method: 'POST', ->
+ input type: 'hidden', name: 'csrf_token', value: @csrf_token
+ input type: 'text', placeholder: 'Username', name: 'username', ''
+ input type: 'password', placeholder: 'Password', name: 'password', ''
+ input type: 'submit', value: 'Submit', ''
--- /dev/null
+html = require 'lapis.html'
+import to_json from require 'lapis.util'
+
+class Register extends html.Widget
+ content: =>
+ h1 style: "background-color:red", "Register"
+
+ p ->
+ text (to_json @errors)
+
+ form method: 'POST', ->
+ p -> input type: 'hidden', name: 'csrf_token', value: @csrf_token
+ p -> input type: 'text', placeholder: 'Username', name: 'username', required: true, ''
+ p -> input type: 'password', placeholder: 'Password', name: 'password', required: true, ''
+ p -> input type: 'password', placeholder: 'Confirm Password', name: 'password_confirmation', required: true, ''
+ p -> input type: 'text', placeholder: 'Email', name: 'email', required: true, ''
+ p -> input type: 'text', placeholder: 'Display Name', name: 'nickname', required: true, ''
+ input type: 'submit', value: 'Submit', ''
--- /dev/null
+html = require "lapis.html"
+
+class Index extends html.Widget
+ content: =>
+ h1 style: "background-color:red", "Hello World!!!"
+ p "Hello #{@user.nickname}, #{@user.username}, #{@user.email}!"
+ p "The value is #{@val}"
+ p "API: #{@api_test}"
+
+ ul ->
+ for job in *@jobs
+ li "#{job.lang} - #{job.problem_id} - #{job\get_problem!.name}"
+
+ ul ->
+ for user in *@users
+ if user.username == @user.username
+ li style: "border: 2px solid yellow", "#{user.username} - #{user.email}"
+ else
+ li "#{user.username} - #{user.email}"
--- /dev/null
+include_rules
--- /dev/null
+html = require "lapis.html"
+Navbar = require 'views.partials.navbar'
+
+class DefaultLayout extends html.Widget
+ content: =>
+ html_5 ->
+ head ->
+ link rel: "stylesheet", href: "static/css/core.css"
+
+ script type: "text/javascript", src: "static/js/main.js"
+
+ body ->
+ widget Navbar
+ @content_for "inner"
--- /dev/null
+html = require 'lapis.html'
+
+class Navigation extends html.Widget
+ content: =>
+ div class: 'navbar', ->
+ div class: 'navbar-logo', ->
+ img src: '/static/imgs/logo.png'
+
+ ul ->
+ a -> li class: { 'selected': @navbar.selected == 0 }, 'Leaderboard'
+ a -> li class: { 'selected': @navbar.selected == 1 }, 'Problems'
+ a -> li class: { 'selected': @navbar.selected == 2 }, 'Submissions'
--- /dev/null
+APP_SECRET=
+REQ_SECRET=
+
+POSTGRES_DB=codebox
+POSTGRES_USER=username
+POSTGRES_PASSWORD=bigsecretpassword
--- /dev/null
+version: '3'
+
+services:
+ codebox:
+ env_file:
+ - config.env
+ build:
+ context: .
+ dockerfile: ./docker/codebox/Dockerfile
+ ports:
+ - 8888:8888
+ volumes:
+ - ./codebox/app:/app/app
+ - ./codebox/views:/app/views
+ - ./codebox/flows:/app/flows
+ - ./codebox/middleware:/app/middleware
+ - ./codebox/models:/app/models
+ - ./codebox/controllers:/app/controllers
+ - ./codebox/utils:/app/utils
+ - ./codebox/services:/app/services
+ - ./codebox/facades:/app/facades
+ - ./codebox/static:/app/static
+ command: lapis server development
+ networks:
+ appnet:
+ ipv4_address: 192.168.0.3
+
+ executer:
+ env_file:
+ - config.env
+ build:
+ context: .
+ dockerfile: ./docker/executer/Dockerfile
+ volumes:
+ - ./executer/app:/app/app
+ command: node main.js
+ networks:
+ appnet:
+ ipv4_address: 192.168.0.4
+
+ postgres:
+ env_file:
+ - config.env
+ image: "postgres:12-alpine"
+ restart: always
+ networks:
+ appnet:
+ ipv4_address: 192.168.0.2
+ logging:
+ driver: none
+
+networks:
+ appnet:
+ driver: bridge
+ ipam:
+ config:
+ - subnet: 192.168.0.0/16
+
+# mysql:
+# build:
+# context: .
+# dockerfile: ./docker/mysql/Dockerfile
+# environment:
+# MYSQL_ROOT_PASSWORD: secret
+# MYSQL_DATABASE: codebox
+# MYSQL_USER: mysql
+# MYSQL_PASSWORD: secret
+# ports:
+# - 3306:3306
+# logging:
+# driver: none
--- /dev/null
+FROM openresty/openresty:xenial
+
+RUN apt-get update \
+ && apt-get -y install openssl libssl-dev git \
+ && luarocks install lapis \
+ && luarocks install lapis-console \
+ && luarocks install moonscript \
+ # && luarocks install openssl \
+ # && luarocks install pgmoon \
+ # && luarocks install ansicolors \
+ # && luarocks install date \
+ # && luarocks install etlua \
+ # && luarocks install loadkit \
+ # && luarocks install lpeg \
+ # && luarocks install lua-cjson \
+ # && luarocks install luaossl \
+ # && luarocks install luafilesystem \
+ # && luarocks install luasocket \
+ # && luarocks install mimetypes \
+ && luarocks install luacrypto \
+ && luarocks install bcrypt
+
+COPY codebox/ /app
+
+ENV LAPIS_OPENRESTY "/opt/openresty/nginx/sbin/nginx"
+
+EXPOSE 8888 80
+
+WORKDIR /app
--- /dev/null
+FROM node:12.9.1
+
+RUN yarn global add coffeescript \
+ && apt-get update \
+ && apt-get install -y libseccomp-dev python3
+
+COPY ./executer/package.json /app/package.json
+WORKDIR /app
+RUN yarn
+
+COPY ./executer/Tupfile /app/Tupfile
+COPY ./executer/Tuprules.tup /app/Tuprules.tup
+COPY ./executer/main.js /app/main.js
+COPY ./executer/app /app/app
+
+ENV PATH $(yarn global bin):$PATH
--- /dev/null
+node_modules/
+.tup/
+yarn.lock
+*.js
--- /dev/null
+include_rules
--- /dev/null
+: *.coffee |> coffee -c -o %B.js %f |> %B.js
--- /dev/null
+include_rules
--- /dev/null
+request = require 'request'
+
+module.exports = (app) ->
+ app.get '/', (req, res) ->
+ res.json {
+ test: 'This is test data'
+ }
+
+ app.post '/submit', (req, res) ->
+ console.log req.body.lang, req.body.code
+
+ request.post 'http://192.168.0.3:8888/executer/status_update',
+ { json: true, form: { request_token: process.env.REQ_SECRET } },
+ (err, res, body) ->
+ if err
+ return console.log err
+
+ console.log body.status
+
+ res.json {
+ id: 'test'
+ }
--- /dev/null
+http = require 'http'
+express = require 'express'
+morgan = require 'morgan'
+bodyParser = require 'body-parser'
+
+app = express()
+app.use (morgan 'dev')
+app.use bodyParser.urlencoded { extended: true }
+
+routes = require './app/routes'
+routes(app)
+
+server = http.createServer(app)
+server.listen 8080, ->
+ console.log 'Started http server on port 8080'
--- /dev/null
+{
+ "name": "executer",
+ "version": "1.0.0",
+ "description": "Executes files",
+ "main": "main.js",
+ "author": "Brendan Hansen",
+ "license": "MIT",
+ "private": true,
+ "dependencies": {
+ "express": "^4.17.1",
+ "morgan": "^1.9.1",
+ "request": "^2.88.0"
+ }
+}