#!/usr/bin/env ruby require 'bundler/inline' gemfile do source 'https://rubygems.org' gem "erb", "~> 4.0" gem "json", "~> 2.0" gem "rack", "~> 3.0" gem "rackup", "~> 2.0" gem "securerandom", "~> 0.1" gem "webrick", "~> 1.0" end $scheme = ENV.fetch("SCHEME", "http") $port = ENV.fetch("PORT", 8284).to_i $host = ENV.fetch("HOST", "localhost:#{$port}") class Project class << self def all @projects ||= [] end def create!(attributes) new({ id: SecureRandom.uuid }.merge(attributes)).tap do |item| all << item end end end def initialize(attributes = {}) @attributes = attributes end def to_h @attributes end end class API def call(env) request = Rack::Request.new(env) path = env['PATH_INFO'] case env['REQUEST_METHOD'] when 'GET' case path when '/projects.json' return json_ok(Project.all.map(&:to_h)) else return json_not_found end when 'POST' case path when "/projects" if authorized?(request, :create_project) return json_created(Project.create!(JSON.parse(request.body.read, symbolize_names: true))) else return json_unauthorized(:create_project) end else return json_not_found end end json_not_found end private def authorized?(request, permission) # TODO:: Check the JWT for the appropriate claim # Connect to the Authz RPC endpoint Ability.allowed?(subject, permission, resource) true end def json_not_found http_response(code: 404) end def json_ok(body) http_response(code: 200, body: JSON.pretty_generate(body)) end def json_created(body) http_response(code: 201, body: JSON.pretty_generate(body.to_h)) end def json_unauthorized(permission) http_response(code: 401, body: JSON.pretty_generate({ error: { code: 401, message: "`#{permission}` is required", } })) end def http_response(code:, headers: { 'Content-Type' => 'application/json' }, body: nil) [ code, headers.merge({ 'X-Backend-Server' => 'REST' }), [body].compact ] end end if __FILE__ == $0 app = Rack::Builder.new do use Rack::Reloader run API.new end.to_app Rackup::Server.start(app: app, Port: $port) end