This repository has been archived by the owner on Jan 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.rb
126 lines (102 loc) · 2.88 KB
/
app.rb
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
# frozon_string_literal: true
ENV['RACK_ENV'] ||= 'development'
require 'bundler'
Bundler.require 'default', ENV['RACK_ENV']
require 'tilt/erb'
MONGO = Mongo::Client.new(ENV.fetch('MONGODB_URI', 'mongodb://localhost:27017/covfefe'), heartbeat_frequency: 60 * 60)
MONGO[:apps].indexes.create_many(
[
{ key: { name: 1 }, unique: true },
{ key: { name: 1, version: 1 }, unique: true },
]
)
MONGO[:hists].indexes.create_many(
[
{ key: { app_id: 1, version: 1 }, unique: true },
]
)
class App < Sinatra::Base
use Rack::Auth::Basic do |username, password|
username == ENV['AUTH_USERNAME'] && password == ENV['AUTH_PASSWORD']
end if ENV.key? 'AUTH_USERNAME' and ENV.key? 'AUTH_PASSWORD'
enable :method_override
helpers do
def apps_find_or_create(name)
name = name.to_s
app = MONGO[:apps].find(name: name).limit(1).first
[
app || { _id: BSON::ObjectId.new, name: name, version: 0, data: [] },
app.nil?
]
end
def sorted_json(obj)
obj.sort_by { |key, _| key }.to_h.to_json
end
end
get '/:name' do
name = params[:name]
app, = apps_find_or_create name
content_type :json
sorted_json app[:data]
end
post '/:name/set' do
name = params[:name]
app, is_new = apps_find_or_create name
payload = begin
JSON.parse request.body.read
ensure
request.body.rewind
end
payload ||= {}
payload = payload
.map { |key, val| [key.to_s, val.to_s] }
.reject { |key, _| key.empty? }
.to_h
if payload.size.positive?
old = app.dup
app[:version] += 1
app[:data] = app[:data].to_h.merge(payload).to_a
MONGO[:hists].insert_one(
_id: BSON::ObjectId.new,
app_id: old[:_id],
version: old[:version],
data: old[:data]
)
if is_new
MONGO[:apps].insert_one(app)
else
MONGO[:apps].update_one({ _id: app[:_id], version: old[:version] }, app)
end
end
content_type :json
sorted_json app[:data]
end
post '/:name/unset' do
name = params[:name]
app, is_new = apps_find_or_create name
payload = begin
JSON.parse request.body.read
ensure
request.body.rewind
end
keys = payload&.keys&.map(&:to_s) || []
if keys.size.positive?
old = app.dup
app[:version] += 1
app[:data] = app[:data].reject { |key, _| keys.include? key.to_s }
MONGO[:hists].insert_one(
_id: BSON::ObjectId.new,
app_id: old[:_id],
version: old[:version],
data: old[:data]
)
if is_new
MONGO[:apps].insert_one(app)
else
MONGO[:apps].update_one({ _id: app[:_id], version: old[:version] }, app)
end
end
content_type :json
sorted_json app[:data]
end
end