initial commit
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 29 Aug 2019 23:53:59 +0000 (18:53 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 29 Aug 2019 23:53:59 +0000 (18:53 -0500)
73 files changed:
.gitignore [new file with mode: 0644]
codebox/.gitignore [new file with mode: 0644]
codebox/Tupfile [new file with mode: 0644]
codebox/Tuprules.tup [new file with mode: 0644]
codebox/app.moon [new file with mode: 0644]
codebox/app/Tupfile [new file with mode: 0644]
codebox/app/app.moon [new file with mode: 0644]
codebox/config.moon [new file with mode: 0644]
codebox/controllers/Tupfile [new file with mode: 0644]
codebox/controllers/account/Tupfile [new file with mode: 0644]
codebox/controllers/account/login.moon [new file with mode: 0644]
codebox/controllers/account/logout.moon [new file with mode: 0644]
codebox/controllers/account/register.moon [new file with mode: 0644]
codebox/controllers/controller.moon [new file with mode: 0644]
codebox/controllers/executer/Tupfile [new file with mode: 0644]
codebox/controllers/executer/request.moon [new file with mode: 0644]
codebox/controllers/executer/status_update.moon [new file with mode: 0644]
codebox/controllers/index.moon [new file with mode: 0644]
codebox/facades/Tupfile [new file with mode: 0644]
codebox/facades/executer.moon [new file with mode: 0644]
codebox/flows/Tupfile [new file with mode: 0644]
codebox/flows/csrf_setup.moon [new file with mode: 0644]
codebox/flows/csrf_validate.moon [new file with mode: 0644]
codebox/middleware/Tupfile [new file with mode: 0644]
codebox/middleware/internal_request.moon [new file with mode: 0644]
codebox/middleware/logged_in.moon [new file with mode: 0644]
codebox/middleware/logged_out.moon [new file with mode: 0644]
codebox/migrations.moon [new file with mode: 0644]
codebox/mime.types [new file with mode: 0644]
codebox/models.moon [new file with mode: 0644]
codebox/models/Tupfile [new file with mode: 0644]
codebox/models/jobs.moon [new file with mode: 0644]
codebox/models/problems.moon [new file with mode: 0644]
codebox/models/users.moon [new file with mode: 0644]
codebox/nginx.conf [new file with mode: 0644]
codebox/services/Tupfile [new file with mode: 0644]
codebox/services/crypto.moon [new file with mode: 0644]
codebox/static/Tupfile [new file with mode: 0644]
codebox/static/coffee/main.coffee [new file with mode: 0644]
codebox/static/css/core.css [new file with mode: 0644]
codebox/static/css/core.css.map [new file with mode: 0644]
codebox/static/imgs/grain_background.png [new file with mode: 0644]
codebox/static/imgs/logo.png [new file with mode: 0644]
codebox/static/js/main.js [new file with mode: 0644]
codebox/static/js/main.js.map [new file with mode: 0644]
codebox/static/scss/_elevate.scss [new file with mode: 0644]
codebox/static/scss/_navbar.scss [new file with mode: 0644]
codebox/static/scss/_utils.scss [new file with mode: 0644]
codebox/static/scss/_vars.scss [new file with mode: 0644]
codebox/static/scss/core.scss [new file with mode: 0644]
codebox/static/scss/problem/_list.scss [new file with mode: 0644]
codebox/static/scss/problem/_sidebar.scss [new file with mode: 0644]
codebox/utils/Tupfile [new file with mode: 0644]
codebox/utils/binding.moon [new file with mode: 0644]
codebox/views/Tupfile [new file with mode: 0644]
codebox/views/account/Tupfile [new file with mode: 0644]
codebox/views/account/login.moon [new file with mode: 0644]
codebox/views/account/register.moon [new file with mode: 0644]
codebox/views/index.moon [new file with mode: 0644]
codebox/views/partials/Tupfile [new file with mode: 0644]
codebox/views/partials/layout.moon [new file with mode: 0644]
codebox/views/partials/navbar.moon [new file with mode: 0644]
config.env.example [new file with mode: 0644]
docker-compose.yaml [new file with mode: 0644]
docker/codebox/Dockerfile [new file with mode: 0644]
docker/executer/Dockerfile [new file with mode: 0644]
executer/.gitignore [new file with mode: 0644]
executer/Tupfile [new file with mode: 0644]
executer/Tuprules.tup [new file with mode: 0644]
executer/app/Tupfile [new file with mode: 0644]
executer/app/routes.coffee [new file with mode: 0644]
executer/main.coffee [new file with mode: 0644]
executer/package.json [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..2549b3d
--- /dev/null
@@ -0,0 +1 @@
+config.env
diff --git a/codebox/.gitignore b/codebox/.gitignore
new file mode 100644 (file)
index 0000000..536871b
--- /dev/null
@@ -0,0 +1,4 @@
+logs/
+nginx.conf.compiled
+*.lua
+.tup
diff --git a/codebox/Tupfile b/codebox/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/Tuprules.tup b/codebox/Tuprules.tup
new file mode 100644 (file)
index 0000000..5fa92eb
--- /dev/null
@@ -0,0 +1 @@
+: foreach *.moon |> moonc %f |> %B.lua
diff --git a/codebox/app.moon b/codebox/app.moon
new file mode 100644 (file)
index 0000000..f3e5c87
--- /dev/null
@@ -0,0 +1,3 @@
+-- Doing this allows for the app/ folder to be mounted
+-- via a docker container for faster reloading
+require "app.app"
diff --git a/codebox/app/Tupfile b/codebox/app/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/app/app.moon b/codebox/app/app.moon
new file mode 100644 (file)
index 0000000..25200f7
--- /dev/null
@@ -0,0 +1,34 @@
+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!
diff --git a/codebox/config.moon b/codebox/config.moon
new file mode 100644 (file)
index 0000000..f6819e2
--- /dev/null
@@ -0,0 +1,15 @@
+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')
diff --git a/codebox/controllers/Tupfile b/codebox/controllers/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/controllers/account/Tupfile b/codebox/controllers/account/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/controllers/account/login.moon b/codebox/controllers/account/login.moon
new file mode 100644 (file)
index 0000000..c6caa48
--- /dev/null
@@ -0,0 +1,33 @@
+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'
+
+
diff --git a/codebox/controllers/account/logout.moon b/codebox/controllers/account/logout.moon
new file mode 100644 (file)
index 0000000..23bd44f
--- /dev/null
@@ -0,0 +1,7 @@
+import make_controller from require "controllers.controller"
+
+make_controller {
+       get: =>
+               @session.user_id = nil
+               return redirect_to: @url_for 'index'
+}
diff --git a/codebox/controllers/account/register.moon b/codebox/controllers/account/register.moon
new file mode 100644 (file)
index 0000000..9bb399b
--- /dev/null
@@ -0,0 +1,48 @@
+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'
+
diff --git a/codebox/controllers/controller.moon b/codebox/controllers/controller.moon
new file mode 100644 (file)
index 0000000..a9519e1
--- /dev/null
@@ -0,0 +1,20 @@
+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(@)
+               }
+}
diff --git a/codebox/controllers/executer/Tupfile b/codebox/controllers/executer/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/controllers/executer/request.moon b/codebox/controllers/executer/request.moon
new file mode 100644 (file)
index 0000000..aad1c7a
--- /dev/null
@@ -0,0 +1,25 @@
+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 }
+
+
+
diff --git a/codebox/controllers/executer/status_update.moon b/codebox/controllers/executer/status_update.moon
new file mode 100644 (file)
index 0000000..3a934ff
--- /dev/null
@@ -0,0 +1,8 @@
+import make_controller from require "controllers.controller"
+
+make_controller
+       middleware: { 'internal_request' }
+
+       post: =>
+               print 'Hit status'
+               json: { status: 'success' }
diff --git a/codebox/controllers/index.moon b/codebox/controllers/index.moon
new file mode 100644 (file)
index 0000000..a788ddb
--- /dev/null
@@ -0,0 +1,11 @@
+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"
diff --git a/codebox/facades/Tupfile b/codebox/facades/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/facades/executer.moon b/codebox/facades/executer.moon
new file mode 100644 (file)
index 0000000..f14ec60
--- /dev/null
@@ -0,0 +1,13 @@
+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
+
+
diff --git a/codebox/flows/Tupfile b/codebox/flows/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/flows/csrf_setup.moon b/codebox/flows/csrf_setup.moon
new file mode 100644 (file)
index 0000000..a360fe3
--- /dev/null
@@ -0,0 +1,5 @@
+csrf = require "lapis.csrf"
+
+=>
+       @csrf_token = csrf.generate_token @
+       return
diff --git a/codebox/flows/csrf_validate.moon b/codebox/flows/csrf_validate.moon
new file mode 100644 (file)
index 0000000..54ca956
--- /dev/null
@@ -0,0 +1,5 @@
+csrf = require "lapis.csrf"
+
+=>
+       csrf.assert_token @
+       @csrf_token = csrf.generate_token @
diff --git a/codebox/middleware/Tupfile b/codebox/middleware/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/middleware/internal_request.moon b/codebox/middleware/internal_request.moon
new file mode 100644 (file)
index 0000000..edca0af
--- /dev/null
@@ -0,0 +1,8 @@
+config = (require 'lapis.config').get!
+
+=>
+       if @params.request_token != config.req_secret
+               @write {
+                       status: 401
+                       json: { status: 'Unauthorized' }
+               }
diff --git a/codebox/middleware/logged_in.moon b/codebox/middleware/logged_in.moon
new file mode 100644 (file)
index 0000000..55b17ad
--- /dev/null
@@ -0,0 +1,12 @@
+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
diff --git a/codebox/middleware/logged_out.moon b/codebox/middleware/logged_out.moon
new file mode 100644 (file)
index 0000000..4d80975
--- /dev/null
@@ -0,0 +1,6 @@
+import Users from require 'models'
+
+=>
+       if @session.user_id
+               @user = Users\find(@session.user_id)
+               @write redirect_to: @url_for 'index' if @user
diff --git a/codebox/migrations.moon b/codebox/migrations.moon
new file mode 100644 (file)
index 0000000..74e2f8d
--- /dev/null
@@ -0,0 +1,38 @@
+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)"
+               }
+}
diff --git a/codebox/mime.types b/codebox/mime.types
new file mode 100644 (file)
index 0000000..292f886
--- /dev/null
@@ -0,0 +1,81 @@
+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;
+}
diff --git a/codebox/models.moon b/codebox/models.moon
new file mode 100644 (file)
index 0000000..70be8f2
--- /dev/null
@@ -0,0 +1,2 @@
+import autoload from require "lapis.util"
+autoload "models"
diff --git a/codebox/models/Tupfile b/codebox/models/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/models/jobs.moon b/codebox/models/jobs.moon
new file mode 100644 (file)
index 0000000..45be721
--- /dev/null
@@ -0,0 +1,7 @@
+import Model from require "lapis.db.model"
+
+class Jobs extends Model
+       @relations: {
+               { 'user', belongs_to: 'Users' }
+               { 'problem', belongs_to: 'Problems' }
+       }
diff --git a/codebox/models/problems.moon b/codebox/models/problems.moon
new file mode 100644 (file)
index 0000000..577e475
--- /dev/null
@@ -0,0 +1,12 @@
+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' }
+       }
diff --git a/codebox/models/users.moon b/codebox/models/users.moon
new file mode 100644 (file)
index 0000000..d8b29e9
--- /dev/null
@@ -0,0 +1,10 @@
+import Model from require "lapis.db.model"
+
+class Users extends Model
+       @relations: {
+               { 'jobs', has_many: 'Jobs' }
+               { 'c_jobs'
+                       has_many: 'Jobs'
+                       where: { lang: 'C' }
+               }
+       }
diff --git a/codebox/nginx.conf b/codebox/nginx.conf
new file mode 100644 (file)
index 0000000..c90f83e
--- /dev/null
@@ -0,0 +1,62 @@
+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;
+       }
+  }
+}
diff --git a/codebox/services/Tupfile b/codebox/services/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/services/crypto.moon b/codebox/services/crypto.moon
new file mode 100644 (file)
index 0000000..1ebedaa
--- /dev/null
@@ -0,0 +1,14 @@
+bcrypt = require "bcrypt"
+
+import Users from require "models"
+
+ROUNDS = 10
+
+{
+       encrypt: (data) ->
+               bcrypt.digest(data, ROUNDS)
+
+       verify: (data, digest) ->
+               bcrypt.verify(data, digest)
+}
+
diff --git a/codebox/static/Tupfile b/codebox/static/Tupfile
new file mode 100644 (file)
index 0000000..a7ec031
--- /dev/null
@@ -0,0 +1,2 @@
+: 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
diff --git a/codebox/static/coffee/main.coffee b/codebox/static/coffee/main.coffee
new file mode 100644 (file)
index 0000000..478d195
--- /dev/null
@@ -0,0 +1,2 @@
+main = ->
+       console.log "Hello world!"
diff --git a/codebox/static/css/core.css b/codebox/static/css/core.css
new file mode 100644 (file)
index 0000000..5b2439b
--- /dev/null
@@ -0,0 +1,105 @@
+.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 */
diff --git a/codebox/static/css/core.css.map b/codebox/static/css/core.css.map
new file mode 100644 (file)
index 0000000..ce00981
--- /dev/null
@@ -0,0 +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
diff --git a/codebox/static/imgs/grain_background.png b/codebox/static/imgs/grain_background.png
new file mode 100644 (file)
index 0000000..765bd27
Binary files /dev/null and b/codebox/static/imgs/grain_background.png differ
diff --git a/codebox/static/imgs/logo.png b/codebox/static/imgs/logo.png
new file mode 100644 (file)
index 0000000..16fc502
Binary files /dev/null and b/codebox/static/imgs/logo.png differ
diff --git a/codebox/static/js/main.js b/codebox/static/js/main.js
new file mode 100644 (file)
index 0000000..695d933
--- /dev/null
@@ -0,0 +1,11 @@
+// Generated by CoffeeScript 2.4.1
+(function() {
+  var main;
+
+  main = function() {
+    return console.log("Hello world!");
+  };
+
+}).call(this);
+
+//# sourceMappingURL=main.js.map
diff --git a/codebox/static/js/main.js.map b/codebox/static/js/main.js.map
new file mode 100644 (file)
index 0000000..7e307dd
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  "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
diff --git a/codebox/static/scss/_elevate.scss b/codebox/static/scss/_elevate.scss
new file mode 100644 (file)
index 0000000..7a212bc
--- /dev/null
@@ -0,0 +1,3 @@
+@mixin elevate($e, $col) {
+    box-shadow: 0px $e (3 * $e) ($e / 4) $col;
+}
diff --git a/codebox/static/scss/_navbar.scss b/codebox/static/scss/_navbar.scss
new file mode 100644 (file)
index 0000000..36ef2d1
--- /dev/null
@@ -0,0 +1,52 @@
+.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;
+                       }
+               }
+       }
+}
diff --git a/codebox/static/scss/_utils.scss b/codebox/static/scss/_utils.scss
new file mode 100644 (file)
index 0000000..3d48d4b
--- /dev/null
@@ -0,0 +1,21 @@
+.content {
+       width: 100%;
+       padding: 10px 5%;
+}
+
+.right {
+       float: right;
+}
+
+.left {
+       float: left;
+}
+
+.hidden {
+       visibility: hidden;
+}
+
+a {
+       text-decoration: none;
+       color: inherit;
+}
diff --git a/codebox/static/scss/_vars.scss b/codebox/static/scss/_vars.scss
new file mode 100644 (file)
index 0000000..ccd82bf
--- /dev/null
@@ -0,0 +1,21 @@
+$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;
diff --git a/codebox/static/scss/core.scss b/codebox/static/scss/core.scss
new file mode 100644 (file)
index 0000000..d76fe8c
--- /dev/null
@@ -0,0 +1,24 @@
+@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;
+}
diff --git a/codebox/static/scss/problem/_list.scss b/codebox/static/scss/problem/_list.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/codebox/static/scss/problem/_sidebar.scss b/codebox/static/scss/problem/_sidebar.scss
new file mode 100644 (file)
index 0000000..663b739
--- /dev/null
@@ -0,0 +1,55 @@
+.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;
+       }
+}
diff --git a/codebox/utils/Tupfile b/codebox/utils/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/utils/binding.moon b/codebox/utils/binding.moon
new file mode 100644 (file)
index 0000000..2f673e0
--- /dev/null
@@ -0,0 +1,23 @@
+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()
diff --git a/codebox/views/Tupfile b/codebox/views/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/views/account/Tupfile b/codebox/views/account/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/views/account/login.moon b/codebox/views/account/login.moon
new file mode 100644 (file)
index 0000000..0dc3213
--- /dev/null
@@ -0,0 +1,11 @@
+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', ''
diff --git a/codebox/views/account/register.moon b/codebox/views/account/register.moon
new file mode 100644 (file)
index 0000000..c0cc4ce
--- /dev/null
@@ -0,0 +1,18 @@
+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', ''
diff --git a/codebox/views/index.moon b/codebox/views/index.moon
new file mode 100644 (file)
index 0000000..be44bc7
--- /dev/null
@@ -0,0 +1,19 @@
+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}"
diff --git a/codebox/views/partials/Tupfile b/codebox/views/partials/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/codebox/views/partials/layout.moon b/codebox/views/partials/layout.moon
new file mode 100644 (file)
index 0000000..79d5a08
--- /dev/null
@@ -0,0 +1,14 @@
+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"
diff --git a/codebox/views/partials/navbar.moon b/codebox/views/partials/navbar.moon
new file mode 100644 (file)
index 0000000..b55b4d6
--- /dev/null
@@ -0,0 +1,12 @@
+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'
diff --git a/config.env.example b/config.env.example
new file mode 100644 (file)
index 0000000..6e4578d
--- /dev/null
@@ -0,0 +1,6 @@
+APP_SECRET=
+REQ_SECRET=
+
+POSTGRES_DB=codebox
+POSTGRES_USER=username
+POSTGRES_PASSWORD=bigsecretpassword
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644 (file)
index 0000000..195f128
--- /dev/null
@@ -0,0 +1,71 @@
+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
diff --git a/docker/codebox/Dockerfile b/docker/codebox/Dockerfile
new file mode 100644 (file)
index 0000000..30a1925
--- /dev/null
@@ -0,0 +1,29 @@
+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
diff --git a/docker/executer/Dockerfile b/docker/executer/Dockerfile
new file mode 100644 (file)
index 0000000..efd1e54
--- /dev/null
@@ -0,0 +1,16 @@
+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
diff --git a/executer/.gitignore b/executer/.gitignore
new file mode 100644 (file)
index 0000000..c2f7987
--- /dev/null
@@ -0,0 +1,4 @@
+node_modules/
+.tup/
+yarn.lock
+*.js
diff --git a/executer/Tupfile b/executer/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/executer/Tuprules.tup b/executer/Tuprules.tup
new file mode 100644 (file)
index 0000000..9591588
--- /dev/null
@@ -0,0 +1 @@
+: *.coffee |> coffee -c -o %B.js %f |> %B.js
diff --git a/executer/app/Tupfile b/executer/app/Tupfile
new file mode 100644 (file)
index 0000000..f0fe651
--- /dev/null
@@ -0,0 +1 @@
+include_rules
diff --git a/executer/app/routes.coffee b/executer/app/routes.coffee
new file mode 100644 (file)
index 0000000..75ea4a5
--- /dev/null
@@ -0,0 +1,22 @@
+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'
+               }
diff --git a/executer/main.coffee b/executer/main.coffee
new file mode 100644 (file)
index 0000000..6216e2d
--- /dev/null
@@ -0,0 +1,15 @@
+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'
diff --git a/executer/package.json b/executer/package.json
new file mode 100644 (file)
index 0000000..a7fa920
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "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"
+  }
+}