1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#!/usr/bin/env ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem "erb", "~> 4.0"
gem "grpc", "~> 1.0"
gem "json", "~> 2.0"
gem "logger", "~> 1.0"
gem "rack", "~> 3.0"
gem "rackup", "~> 2.0"
gem "securerandom", "~> 0.1"
gem "webrick", "~> 1.0"
end
lib_path = Pathname.new(__FILE__).parent.parent.join('lib').realpath.to_s
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
require 'authx'
GRPC.logger = Logger.new($stderr, level: :debug)
$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)
client = ::Authx::Rpc::Ability::Stub.new('localhost:50051', :this_channel_is_insecure) # TODO:: memorize client
reply = client.allowed(::Authx::Rpc::AllowRequest.new(subject: "", permission: permission, resource: ""))
puts "***" * 10
puts reply.inspect
puts "***" * 10
reply&.result
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::CommonLogger
use Rack::Reloader
run API.new
end.to_app
Rackup::Server.start(app: app, Port: $port)
end
|