From: Brendan Hansen Date: Mon, 2 Sep 2019 14:41:00 +0000 (-0500) Subject: Bug fixes and adding admin functionality X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=1cdc32aaf59091b0e1f8f3726f15f4d37c2d1756;p=codebox.git Bug fixes and adding admin functionality --- diff --git a/codebox/app/app.moon b/codebox/app/app.moon index 25200f7..adc70c9 100644 --- a/codebox/app/app.moon +++ b/codebox/app/app.moon @@ -4,8 +4,6 @@ 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' @@ -18,9 +16,10 @@ class extends lapis.Application @before_filter => @navbar = {} - @navbar.selected = 1 + @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" @@ -28,7 +27,13 @@ class extends lapis.Application ['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" + ['admin.user': "/admin/user"]: => "NOT IMPLEMENTED" + + ['admin.problem': "/admin/problem"]: require "controllers.admin.problem" + ['admin.problem.new': "/admin/problem/new"]: require "controllers.admin.problem.new" + ['admin.problem.edit': "/admin/problem/edit/:problem_name"]: require "controllers.admin.problem.edit" + + ['admin.submission': "/admin/submission"]: => "NOT IMPLEMENTED" + ['admin.competition': "/admin/competition"]: => "NOT IMPLEMENTED" "/console": console.make! diff --git a/codebox/controllers/account/login.moon b/codebox/controllers/account/login.moon index 99fdcaf..a44204d 100644 --- a/codebox/controllers/account/login.moon +++ b/codebox/controllers/account/login.moon @@ -1,6 +1,7 @@ import make_controller from require "controllers.controller" import Users from require 'models' import assert_valid from require "lapis.validate" +import capture_errors, yield_error from require "lapis.application" utils = require "lapis.util" @@ -14,7 +15,7 @@ make_controller @flow 'csrf_setup' render: 'account.login' - post: => + post: capture_errors => @flow 'csrf_validate' assert_valid @params, { @@ -22,11 +23,15 @@ make_controller { "password", exists: true, min_length: 2 } } - users = Users\find username: @params.username - if #users > 0 - if @crypto.verify @params.password, users[1].password_hash - @session.user_id = users[1].id + user = Users\find username: @params.username + if user != nil + if @crypto.verify @params.password, user.password_hash + @session.user_id = user.id return redirect_to: @url_for 'index' + else + yield_error "Password incorrect" + else + yield_error "User not found" render: 'account.login' diff --git a/codebox/controllers/account/register.moon b/codebox/controllers/account/register.moon index 9bb399b..c16d4b4 100644 --- a/codebox/controllers/account/register.moon +++ b/codebox/controllers/account/register.moon @@ -1,7 +1,7 @@ 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' +import capture_errors, yield_error from require 'lapis.application' make_controller inject: @@ -27,8 +27,7 @@ make_controller users = Users\find username: @params.username if users -- Account already exists - @errors or= {} - table.insert @errors, 'Username already taken' + yield_error 'Username already taken' return render: 'account.register' user_id = Users\create { diff --git a/codebox/controllers/admin/Tupfile b/codebox/controllers/admin/Tupfile new file mode 100644 index 0000000..f0fe651 --- /dev/null +++ b/codebox/controllers/admin/Tupfile @@ -0,0 +1 @@ +include_rules diff --git a/codebox/controllers/admin/problem.moon b/codebox/controllers/admin/problem.moon new file mode 100644 index 0000000..a12f810 --- /dev/null +++ b/codebox/controllers/admin/problem.moon @@ -0,0 +1,18 @@ +import make_controller from require "controllers.controller" +import assert_valid from require "lapis.validate" +import capture_errors from require 'lapis.application' +import Problems from require 'models' + +make_controller + layout: require 'views.partials.admin_layout' + + middleware: { 'logged_in', 'admin_required' } + + get: => + @navbar.selected = 1 + + @problems = Problems\select! + + render: 'admin.problem' + + diff --git a/codebox/controllers/admin/problem/Tupfile b/codebox/controllers/admin/problem/Tupfile new file mode 100644 index 0000000..f0fe651 --- /dev/null +++ b/codebox/controllers/admin/problem/Tupfile @@ -0,0 +1 @@ +include_rules diff --git a/codebox/controllers/admin/problem/edit.moon b/codebox/controllers/admin/problem/edit.moon new file mode 100644 index 0000000..7b14622 --- /dev/null +++ b/codebox/controllers/admin/problem/edit.moon @@ -0,0 +1,54 @@ +import make_controller from require "controllers.controller" +import assert_valid from require "lapis.validate" +import capture_errors, capture_errors_json, yield_error from require 'lapis.application' +import Problems from require 'models' + +make_controller + layout: require 'views.partials.admin_layout' + + middleware: { 'logged_in', 'admin_required' } + + get: capture_errors_json => + @flow 'csrf_setup' + + @navbar.selected = 1 + + assert_valid @params, { + { "problem_name", exists: true } + } + + @problem = Problems\find short_name: @params.problem_name + unless @problem + yield_error "Problem not found" + + render: true + + post: capture_errors => + @flow 'csrf_validate' + @navbar.selected = 1 + + assert_valid @params, { + { "problem_name", exists: true } + { "problem_id", exists: true } + { "name", exists: true } + { "short_name", exists: true } + { "description", exists: true } + { "time_limit", exists: true, is_integer: true } + } + + problem = Problems\find @params.problem_id + unless problem + yield_error "Problem with id '#{@params.problem_id}' not found" + return + + problem\update { + name: @params.name + short_name: @params.short_name + description: @params.description + time_limit: @params.time_limit + } + + redirect_to: (@url_for "admin.problem.edit", problem_name: @params.short_name) + + delete: capture_errors_json => + return json: @params diff --git a/codebox/controllers/admin/problem/new.moon b/codebox/controllers/admin/problem/new.moon new file mode 100644 index 0000000..75d7f34 --- /dev/null +++ b/codebox/controllers/admin/problem/new.moon @@ -0,0 +1,48 @@ +import make_controller from require "controllers.controller" +import assert_valid from require "lapis.validate" +import capture_errors, capture_errors_json, yield_error from require 'lapis.application' +import Problems from require 'models' + +make_controller + layout: require 'views.partials.admin_layout' + + middleware: { 'logged_in', 'admin_required' } + + get: => + @flow 'csrf_setup' + + @navbar.selected = 1 + + @problems = Problems\select! + + return { + layout: require 'views.partials.admin_layout' + render: 'admin.problem.new' + } + + post: capture_errors => + @flow 'csrf_validate' + + assert_valid @params, { + { 'short_name', exists: true } + { 'name', exists: true } + { 'description', exists: true } + { 'time_limit', exists: true, is_integer: true } + } + + if Problems\find short_name: @params.short_name + yield_error "Problem with short name, #{@params.short_name}, already exists" + return + + problem = Problems\create { + short_name: @params.short_name + name: @params.name + kind: Problems.kinds\for_db 'code' + description: @params.description + time_limit: @params.time_limit + } + + if problem then + yield_error success: true, msg: "Successfully created problem #{@params.name}" + else + yield_error "There was an error creating the problem" diff --git a/codebox/controllers/controller.moon b/codebox/controllers/controller.moon index a9519e1..34e77d0 100644 --- a/codebox/controllers/controller.moon +++ b/codebox/controllers/controller.moon @@ -14,7 +14,17 @@ bind = require 'utils.binding' for middleware in *routes.middleware require("#{@app.middleware_prefix}.#{middleware}") @ - GET: => routes.get(@) - POST: => routes.post(@) + GET: => + r = routes.get(@) + r.layout or= routes.layout + return r + POST: => + r = routes.post(@) + r.layout or= routes.layout + return r + DELETE: => + r = routes.delete(@) + r.layout or= routes.layout + return r } } diff --git a/codebox/middleware/admin_required.moon b/codebox/middleware/admin_required.moon new file mode 100644 index 0000000..ce4356b --- /dev/null +++ b/codebox/middleware/admin_required.moon @@ -0,0 +1,4 @@ +=> + unless @user.username == "admin" + @write redirect_to: @url_for 'index' + diff --git a/codebox/migrations.moon b/codebox/migrations.moon index eb29171..36ed5c0 100644 --- a/codebox/migrations.moon +++ b/codebox/migrations.moon @@ -1,4 +1,5 @@ import create_table, add_column, types from require "lapis.db.schema" +import insert from require "lapis.db" { [1]: => @@ -30,6 +31,7 @@ import create_table, add_column, types from require "lapis.db.schema" [3]: => create_table "problems", { { "id", types.serial }, + { "short_name", types.varchar unique: true }, { "name", types.varchar }, { "kind", types.enum }, { "description", types.text null: true }, @@ -47,4 +49,12 @@ import create_table, add_column, types from require "lapis.db.schema" "PRIMARY KEY (id)" } + + [5]: => + insert "users", { + username: "admin" + password_hash: "$2b$10$uZasTmdngnbGO4ogkvY9b.S7bn.YxLJseCc3MufyX7S0wr5UpgNxy" + nickname: "admin" + email: "admin@admin.org" + } } diff --git a/codebox/services/crypto.moon b/codebox/services/crypto.moon index 1ebedaa..e492a87 100644 --- a/codebox/services/crypto.moon +++ b/codebox/services/crypto.moon @@ -1,7 +1,5 @@ bcrypt = require "bcrypt" -import Users from require "models" - ROUNDS = 10 { diff --git a/codebox/static/css/core.css b/codebox/static/css/core.css index 5b2439b..27db62a 100644 --- a/codebox/static/css/core.css +++ b/codebox/static/css/core.css @@ -40,6 +40,28 @@ color: white; } +.content, .error-list { + width: 100%; + padding: 10px 10%; +} + +.right { + float: right; +} + +.left { + float: left; +} + +.hidden { + visibility: hidden; +} + +a { + text-decoration: none; + color: inherit; +} + .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); @@ -94,6 +116,12 @@ font-size: 16px; } +h1 { + width: 100%; + margin-top: 12px; + text-align: center; +} + body { font-family: sans-serif; background: url(/static/imgs/grain_background.png); @@ -102,4 +130,54 @@ body { color: white; } +button { + box-shadow: 0px 2px 6px 0.5px rgba(0, 0, 0, 0.7); + border: 1px solid #0077c2; + background-color: #0077c2; + color: white; + font-size: 1rem; + padding: 0.75rem; + margin-bottom: 12px; + display: inline-block; +} +button::placeholder { + color: #999; +} + +form input, form button, form textarea { + box-shadow: 0px 2px 6px 0.5px rgba(0, 0, 0, 0.7); + border: 1px solid #0077c2; + background-color: #0077c2; + color: white; + font-size: 1rem; + padding: 0.75rem; + margin-bottom: 12px; + display: inline-block; + width: 100%; +} +form input::placeholder, form button::placeholder, form textarea::placeholder { + color: #999; +} +form textarea { + background-color: #111; + height: 50vh; +} +form label { + display: inline-block; + padding-left: 12px; + margin-top: 16px; + margin-bottom: 8px; +} + +.error-list ul li { + box-shadow: 0px 2px 6px 0.5px rgba(0, 0, 0, 0.5); + list-style: none; + background-color: #998100; + padding: 0.5rem; + margin-bottom: 0.5rem; +} +.error-list ul li.success { + background-color: #0077c2; +} + /*# sourceMappingURL=core.css.map */ diff --git a/codebox/static/css/core.css.map b/codebox/static/css/core.css.map index ce00981..6008454 100644 --- a/codebox/static/css/core.css.map +++ b/codebox/static/css/core.css.map @@ -1 +1 @@ -{"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 +{"version":3,"sourceRoot":"","sources":["../scss/_navbar.scss","../scss/_vars.scss","../scss/_utils.scss","../scss/problem/_sidebar.scss","../scss/core.scss","../scss/_elevate.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;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;EACA;;;ACnBD;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;;;AC7CF;EACC;EACA;EACA;;;AAGD;EACC;;;AAGD;EACC;EACA;EACA;;;AAGD;EACC;EAEA;EACA;EACA;EACA;;;AAGD;EC/BI;EDiCH;EACA,kBH5Bc;EG6Bd;EAEA;EACA;EACA;EACA;;AAEA;EACC;;;AAKD;EChDG;EDkDF;EACA,kBH7Ca;EG8Cb;EAEA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAIF;EACC;EACA;;AAGD;EACC;EACA;EACA;EACA;;;AAOD;ECjFG;EDoFF;EACA,kBH3Ee;EG4Ef;EACA;;AAEA;EACC,kBHpFY","file":"core.css"} \ No newline at end of file diff --git a/codebox/static/scss/_utils.scss b/codebox/static/scss/_utils.scss index 3d48d4b..78fe864 100644 --- a/codebox/static/scss/_utils.scss +++ b/codebox/static/scss/_utils.scss @@ -1,6 +1,6 @@ -.content { +%content, .content { width: 100%; - padding: 10px 5%; + padding: 10px 10%; } .right { diff --git a/codebox/static/scss/core.scss b/codebox/static/scss/core.scss index d76fe8c..7b44fce 100644 --- a/codebox/static/scss/core.scss +++ b/codebox/static/scss/core.scss @@ -1,6 +1,7 @@ @import '_vars'; @import '_elevate'; @import '_navbar'; +@import '_utils'; @import 'problem/_list.scss'; @import 'problem/_sidebar.scss'; @@ -14,6 +15,12 @@ font-size: 16px; } +h1 { + width: 100%; + margin-top: 12px; + text-align: center; +} + body { font-family: sans-serif; @@ -22,3 +29,67 @@ body { background-repeat: repeat; color: white; } + +button { + @include elevate(2px, rgba(0, 0, 0, 0.7)); + border: 1px solid $primary-dark; + background-color: $primary-dark; + color: white; + + font-size: 1rem; + padding: .75rem; + margin-bottom: 12px; + display: inline-block; + + &::placeholder { + color: #999; + } +} + +form { + input, button, textarea { + @include elevate(2px, rgba(0, 0, 0, 0.7)); + border: 1px solid $primary-dark; + background-color: $primary-dark; + color: white; + + font-size: 1rem; + padding: .75rem; + margin-bottom: 12px; + display: inline-block; + width: 100%; + + &::placeholder { + color: #999; + } + } + + textarea { + background-color: #111; + height: 50vh; + } + + label { + display: inline-block; + padding-left: 12px; + margin-top: 16px; + margin-bottom: 8px; + } +} + +.error-list { + @extend .content; + + ul li { + @include elevate(2px, rgba(0, 0, 0, 0.5)); + + list-style: none; + background-color: $secondary-dark; + padding: .5rem; + margin-bottom: .5rem; + + &.success { + background-color: $primary-dark; + } + } +} diff --git a/codebox/views/account/login.moon b/codebox/views/account/login.moon index 0dc3213..7cb1195 100644 --- a/codebox/views/account/login.moon +++ b/codebox/views/account/login.moon @@ -1,11 +1,13 @@ html = require "lapis.html" +import to_json from require 'lapis.util' class Login extends html.Widget content: => - h1 style: "background-color:red", "Login!" + h1 "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', '' + div class: 'content', -> + 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', '' diff --git a/codebox/views/account/register.moon b/codebox/views/account/register.moon index c0cc4ce..c6123e3 100644 --- a/codebox/views/account/register.moon +++ b/codebox/views/account/register.moon @@ -3,16 +3,25 @@ import to_json from require 'lapis.util' class Register extends html.Widget content: => - h1 style: "background-color:red", "Register" + h1 "Register" - p -> - text (to_json @errors) + div class: 'content', -> + form method: 'POST', -> + input type: 'hidden', name: 'csrf_token', value: @csrf_token + + label for: 'username', 'Username' + p -> input type: 'text', placeholder: 'Username', name: 'username', required: true, '' - 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', '' + label for: 'password', 'Password' + p -> input type: 'password', placeholder: 'Password', name: 'password', required: true, '' + + label for: 'password_confirmation', 'Confirm Password' + p -> input type: 'password', placeholder: 'Confirm Password', name: 'password_confirmation', required: true, '' + + label for: 'email', 'Email' + p -> input type: 'text', placeholder: 'Email', name: 'email', required: true, '' + + label for: 'nickname', 'Display name' + p -> input type: 'text', placeholder: 'Display Name', name: 'nickname', required: true, '' + + input type: 'submit', value: 'Submit', '' diff --git a/codebox/views/admin/Tupfile b/codebox/views/admin/Tupfile new file mode 100644 index 0000000..f0fe651 --- /dev/null +++ b/codebox/views/admin/Tupfile @@ -0,0 +1 @@ +include_rules diff --git a/codebox/views/admin/problem.moon b/codebox/views/admin/problem.moon new file mode 100644 index 0000000..e71cbb3 --- /dev/null +++ b/codebox/views/admin/problem.moon @@ -0,0 +1,10 @@ +html = require "lapis.html" + +class AdminProblems extends html.Widget + content: => + ul -> + for problem in *@problems + li "#{problem.name} - #{problem.kind} - #{problem.time_limit}" + + a href: (@url_for 'admin.problem.new'), + -> text 'Create a problem' diff --git a/codebox/views/admin/problem/Tupfile b/codebox/views/admin/problem/Tupfile new file mode 100644 index 0000000..f0fe651 --- /dev/null +++ b/codebox/views/admin/problem/Tupfile @@ -0,0 +1 @@ +include_rules diff --git a/codebox/views/admin/problem/edit.moon b/codebox/views/admin/problem/edit.moon new file mode 100644 index 0000000..7046cad --- /dev/null +++ b/codebox/views/admin/problem/edit.moon @@ -0,0 +1,24 @@ +html = require "lapis.html" + +class AdminProblemEdit extends html.Widget + content: => + h1 "Editing '#{@problem.name}'" + + div class: 'content', -> + form method: 'POST', -> + input type: 'hidden', name: 'csrf_token', value: @csrf_token + input type: 'hidden', name: 'problem_id', value: @problem.id + + label for: 'name', 'Problem name' + input type: 'text', name: 'name', placeholder: 'Problem name', value: @problem.name, "" + + label for: 'name', 'Short name' + input type: 'text', name: 'short_name', placeholder: 'Short URL name', value: @problem.short_name, "" + + label for: 'name', 'Problem description' + textarea name: 'description', placeholder: 'Problem description', @problem.description + + label for: 'name', 'Time limit' + input type: 'number', value: 500, name: 'time_limit', value: @problem.time_limit, "" + + input type: 'submit', value: 'Update problem' diff --git a/codebox/views/admin/problem/new.moon b/codebox/views/admin/problem/new.moon new file mode 100644 index 0000000..f1d8f05 --- /dev/null +++ b/codebox/views/admin/problem/new.moon @@ -0,0 +1,24 @@ +html = require "lapis.html" + +class AdminProblems extends html.Widget + content: => + h1 "Create a problem" + + div class: 'content', -> + form method: 'POST', -> + input type: 'hidden', name: 'csrf_token', value: @csrf_token + + label for: 'name', 'Problem name' + input type: 'text', name: 'name', placeholder: 'Problem name', "" + + label for: 'name', 'Short name' + input type: 'text', name: 'short_name', placeholder: 'Short URL name', "" + + label for: 'name', 'Problem description' + textarea name: 'description', placeholder: 'Problem description', "" + + label for: 'name', 'Time limit' + input type: 'number', value: 500, name: 'time_limit', "" + + input type: 'submit', value: 'Create problem' + diff --git a/codebox/views/partials/admin_layout.moon b/codebox/views/partials/admin_layout.moon new file mode 100644 index 0000000..da11766 --- /dev/null +++ b/codebox/views/partials/admin_layout.moon @@ -0,0 +1,16 @@ +html = require "lapis.html" +AdminNavbar = require 'views.partials.admin_navbar' +ErrorList = require 'views.partials.error_list' + +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 AdminNavbar + widget ErrorList + @content_for "inner" diff --git a/codebox/views/partials/admin_navbar.moon b/codebox/views/partials/admin_navbar.moon new file mode 100644 index 0000000..6ea9487 --- /dev/null +++ b/codebox/views/partials/admin_navbar.moon @@ -0,0 +1,13 @@ +html = require 'lapis.html' + +class AdminNavigation extends html.Widget + content: => + div class: 'navbar', -> + div class: 'navbar-logo', -> + img src: '/static/imgs/logo.png' + + ul -> + a (href: @url_for 'admin.user'), -> li class: { 'selected': @navbar.selected == 0 }, 'Users' + a (href: @url_for 'admin.problem'), -> li class: { 'selected': @navbar.selected == 1 }, 'Problems' + a (href: @url_for 'admin.submission'), -> li class: { 'selected': @navbar.selected == 2 }, 'Submissions' + a (href: @url_for 'admin.competition'), -> li class: { 'selected': @navbar.selected == 3 }, 'Competitions' diff --git a/codebox/views/partials/error_list.moon b/codebox/views/partials/error_list.moon new file mode 100644 index 0000000..8cad3eb --- /dev/null +++ b/codebox/views/partials/error_list.moon @@ -0,0 +1,13 @@ +html = require 'lapis.html' + +class ErrorList extends html.Widget + content: => + return unless @errors + + div class: 'error-list', -> + ul -> + for err in *@errors + if err.success then + li class: 'success', -> text "Success: #{err.msg}" + else + li -> text "Error: #{err}" diff --git a/codebox/views/partials/layout.moon b/codebox/views/partials/layout.moon index 79d5a08..38cf9e0 100644 --- a/codebox/views/partials/layout.moon +++ b/codebox/views/partials/layout.moon @@ -1,14 +1,16 @@ html = require "lapis.html" Navbar = require 'views.partials.navbar' +ErrorList = require 'views.partials.error_list' class DefaultLayout extends html.Widget content: => html_5 -> head -> - link rel: "stylesheet", href: "static/css/core.css" + link rel: "stylesheet", href: "/static/css/core.css" - script type: "text/javascript", src: "static/js/main.js" + script type: "text/javascript", src: "/static/js/main.js" body -> widget Navbar + widget ErrorList @content_for "inner" diff --git a/docker/executer/Dockerfile b/docker/executer/Dockerfile index efd1e54..f4d0b9f 100644 --- a/docker/executer/Dockerfile +++ b/docker/executer/Dockerfile @@ -8,8 +8,6 @@ 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 diff --git a/docs/todo b/docs/todo new file mode 100644 index 0000000..736b240 --- /dev/null +++ b/docs/todo @@ -0,0 +1,5 @@ +[ ] Be able to add test cases to problems +[ ] Be able to delete problems +[ ] Be able to delete test cases +[ ] Be able to order test cases +[ ] diff --git a/executer/app/executer.coffee b/executer/app/executer.coffee index 7c57cb7..ada99d5 100644 --- a/executer/app/executer.coffee +++ b/executer/app/executer.coffee @@ -65,19 +65,21 @@ class Executer switch (res.status) when 'SUCCESS' + console.log test_case.output, res.output output = clean_output res.output expected = create_matchers (clean_output test_case.output) worked = true i = 0 for matcher in expected + console.log matcher.line, output[i] unless matcher.test output[i] worked = false break i++ - unless i == output.length + if worked && i != output.length worked = false run_times[completed] = res.run_time diff --git a/executer/app/executers/c_executer.coffee b/executer/app/executers/c_executer.coffee index 73b0636..0b58493 100644 --- a/executer/app/executers/c_executer.coffee +++ b/executer/app/executers/c_executer.coffee @@ -24,7 +24,7 @@ class CExecuter extends BaseExecuter return { status: 'SUCCESS', output: output, run_time: run_time } else if res_code == 124 or res_code == 137 bash_shell.kill() - return { status: 'TIME_LIMIT_EXECEED' } + return { status: 'TIME_LIMIT_EXCEEDED' } else bash_shell.kill() return { status: 'BAD_EXECUTION', err: err_output } diff --git a/executer/app/routes.coffee b/executer/app/routes.coffee index 2825dbf..2ce05f2 100644 --- a/executer/app/routes.coffee +++ b/executer/app/routes.coffee @@ -36,21 +36,6 @@ module.exports = (app) -> 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' - } - app.post '/request', (req, res) -> cases = JSON.parse req.body.test_cases job_id = uuid()