tentd 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +9 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +49 -0
- data/Rakefile +8 -0
- data/bin/tent-server +3 -0
- data/lib/tentd.rb +31 -0
- data/lib/tentd/api.rb +58 -0
- data/lib/tentd/api/apps.rb +196 -0
- data/lib/tentd/api/authentication_finalize.rb +12 -0
- data/lib/tentd/api/authentication_lookup.rb +27 -0
- data/lib/tentd/api/authentication_verification.rb +50 -0
- data/lib/tentd/api/authorizable.rb +21 -0
- data/lib/tentd/api/authorization.rb +14 -0
- data/lib/tentd/api/core_profile_data.rb +45 -0
- data/lib/tentd/api/followers.rb +218 -0
- data/lib/tentd/api/followings.rb +241 -0
- data/lib/tentd/api/groups.rb +161 -0
- data/lib/tentd/api/middleware.rb +32 -0
- data/lib/tentd/api/posts.rb +373 -0
- data/lib/tentd/api/profile.rb +78 -0
- data/lib/tentd/api/router.rb +123 -0
- data/lib/tentd/api/router/caching_headers.rb +49 -0
- data/lib/tentd/api/router/extract_params.rb +88 -0
- data/lib/tentd/api/router/serialize_response.rb +38 -0
- data/lib/tentd/api/user_lookup.rb +10 -0
- data/lib/tentd/core_ext/hash/slice.rb +29 -0
- data/lib/tentd/datamapper/array_property.rb +23 -0
- data/lib/tentd/datamapper/query.rb +19 -0
- data/lib/tentd/json_patch.rb +181 -0
- data/lib/tentd/model.rb +30 -0
- data/lib/tentd/model/app.rb +68 -0
- data/lib/tentd/model/app_authorization.rb +113 -0
- data/lib/tentd/model/follower.rb +105 -0
- data/lib/tentd/model/following.rb +100 -0
- data/lib/tentd/model/group.rb +24 -0
- data/lib/tentd/model/mention.rb +19 -0
- data/lib/tentd/model/notification_subscription.rb +56 -0
- data/lib/tentd/model/permissible.rb +227 -0
- data/lib/tentd/model/permission.rb +28 -0
- data/lib/tentd/model/post.rb +178 -0
- data/lib/tentd/model/post_attachment.rb +27 -0
- data/lib/tentd/model/post_version.rb +64 -0
- data/lib/tentd/model/profile_info.rb +80 -0
- data/lib/tentd/model/random_public_id.rb +46 -0
- data/lib/tentd/model/serializable.rb +58 -0
- data/lib/tentd/model/type_properties.rb +36 -0
- data/lib/tentd/model/user.rb +39 -0
- data/lib/tentd/model/user_scoped.rb +14 -0
- data/lib/tentd/notifications.rb +13 -0
- data/lib/tentd/notifications/girl_friday.rb +30 -0
- data/lib/tentd/notifications/sidekiq.rb +50 -0
- data/lib/tentd/tent_type.rb +20 -0
- data/lib/tentd/tent_version.rb +41 -0
- data/lib/tentd/version.rb +3 -0
- data/spec/fabricators/app_authorizations_fabricator.rb +5 -0
- data/spec/fabricators/apps_fabricator.rb +11 -0
- data/spec/fabricators/followers_fabricator.rb +14 -0
- data/spec/fabricators/followings_fabricator.rb +17 -0
- data/spec/fabricators/groups_fabricator.rb +3 -0
- data/spec/fabricators/mentions_fabricator.rb +3 -0
- data/spec/fabricators/notification_subscriptions_fabricator.rb +4 -0
- data/spec/fabricators/permissions_fabricator.rb +1 -0
- data/spec/fabricators/post_attachments_fabricator.rb +8 -0
- data/spec/fabricators/post_versions_fabricator.rb +12 -0
- data/spec/fabricators/posts_fabricator.rb +12 -0
- data/spec/fabricators/profile_infos_fabricator.rb +30 -0
- data/spec/integration/api/apps_spec.rb +466 -0
- data/spec/integration/api/followers_spec.rb +535 -0
- data/spec/integration/api/followings_spec.rb +688 -0
- data/spec/integration/api/groups_spec.rb +207 -0
- data/spec/integration/api/posts_spec.rb +874 -0
- data/spec/integration/api/profile_spec.rb +285 -0
- data/spec/integration/api/router_spec.rb +102 -0
- data/spec/integration/model/app_authorization_spec.rb +59 -0
- data/spec/integration/model/app_spec.rb +63 -0
- data/spec/integration/model/follower_spec.rb +344 -0
- data/spec/integration/model/following_spec.rb +97 -0
- data/spec/integration/model/group_spec.rb +39 -0
- data/spec/integration/model/notification_subscription_spec.rb +145 -0
- data/spec/integration/model/post_spec.rb +658 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/expect_server.rb +3 -0
- data/spec/support/json_request.rb +54 -0
- data/spec/support/with_constant.rb +23 -0
- data/spec/support/with_warnings.rb +6 -0
- data/spec/unit/api/authentication_finalize_spec.rb +45 -0
- data/spec/unit/api/authentication_lookup_spec.rb +65 -0
- data/spec/unit/api/authentication_verification_spec.rb +50 -0
- data/spec/unit/api/authorizable_spec.rb +50 -0
- data/spec/unit/api/authorization_spec.rb +44 -0
- data/spec/unit/api/caching_headers_spec.rb +121 -0
- data/spec/unit/core_profile_data_spec.rb +64 -0
- data/spec/unit/json_patch_spec.rb +407 -0
- data/spec/unit/tent_type_spec.rb +28 -0
- data/spec/unit/tent_version_spec.rb +68 -0
- data/tentd.gemspec +36 -0
- metadata +435 -0
data/.gitignore
ADDED
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--color --backtrace
|
data/.travis.yml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
source_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBM2Nvc0tLYnJWQllHTlI5WEE5WTc1L2FJbndPUWZ6L1dzK29GblQrR1hhVzV0Y3poCnpybTlyckU4WkpTWmtOaEpQQkZaMEpLMjI2M3FWSHkxWW45MC9XdUZ0aEZxbGdVNUgxbS9TTHJuelgrUzd2NHcKZk9zWU1xV1VvNVNzVXpLV3B0REhXNjMvQjlCNjBtck9OZnkwRU0yZjM0b05GMTlLTFM5ZTZKQ2t0aWViQXg2VAppaXE2OEtkVW5rODNVZjhYRkVOWi9iK2p3N2FaekdQNVY0R0JvMmhud1hEbFUxanlwNkVnVFUzdThNWFpHRUU2CjV4MWJlYmtIYUdPZXlGRUNTQUJsTEZBUGwrMDZsNEluaE0rMC9RSmJUTnlWdUNHaUtDNStlU3FwREdtdlJxK3MKTC9sNG9zMTBOUEdLU0c1eDRXcFIycUVRQXVxYTZPV0dTMlE0SHdJREFRQUJBb0lCQVFDeXlrckV6cUtBVzJ6UApvQjhHUWNwekdRTlRwSXowZDZMOTBCYU1oK3dxUy9Ha1E3QjRkTFViUVZjZEFjbTF3UlZ3YmRCSVdpMDhkRHVsCnRnNkdnNWJzdjZPL2ZOUytjU0YyUzJQdkhuVEU3U1dtc1pTbTd1SEgya0V6aVNOTndrYzkzS29KRnYreTdmWkUKNzhLaU5MOTNtRHRiK2E3Sis1QVJVdEdnaXhHc29Fb3FYeU9xYVJNNFBmK1pwSHZYcVZLR2xUM0tNaDBCQVM4TQpuK1ZtblpzRDUyMFNETXR0SUJQYXg3U2pPb2NQQ3lmOEt5dHVxblRRSC9RMjVsSE5HcmI1VmQxYzd4dFJ1SlRDCnVGWmFhczAwSzZBUG5uZDZkak1rM3kxSTJSNG8vRUlBOFZhRWNoc0ZCUXd5ZGlxQThkL0gyZTd5czRBd1RHL0sKbVFBMzk0eDVBb0dCQVBwUnNRdStib1dvclFRWC9teTdyU0M4QzFRQmlYQVBNUGxhU3A1d29WMlEzbnQzL1l4TApYbVh6SFdBTlU2dWo2Q01vTHg3UWtXMGppOXFySk9aR2JUejZ0VTFBOHFHL28yRVVKSldJN3F0Qnh5R291YS8yCjcraDliOGJYZDBNZDVWYXp5S21hSEE5aHA3Qm04Y2hpaTlNUUhBTFVrNUIwbyt5azhoUHVFOXl6QW9HQkFPTFMKdXY5ZE8wdm9wTVA2aHpYYitIamJodkZJVXBudTNOR2srQVdWQ3Rlc2NHRzZkMUdqR1loaUxmN2p5eGdUQ3NBegpBek9kVEs3eXI5bXZpTHJKb2J2a05pbG5SNzBnRHNkckJuK2p0ajQvb1MwaUpRWTB6WlpSVTZ2bzhIM3cvSGxyCjVMRVFPOUVGOCs1bWRlT3lIMDI4b1lUY1IvaWNTcC9vV3RiTG53VGxBb0dBWWh5WXp5aVJ1ek9VdE5FT3VPR0sKaHhVTlA1em1tSlJydHFCTU5QT2lXOEVIWXM5eUFvWWI5c3VtVE5xTVcrNy9jcUF5YjlxQjFZd2tLYzRBeFh6LwpIZktLRTBDTW1SYzYyemNBNjlkaTdKNzRoTm5VQmdNOG54eGpMa1dQaWkveWp0d2luMDgzQmxSWlhJdk00cVMxCmQwR09LUkhXMEx6VzcwN3JUeUoyaUg4Q2dZRUF3cGdwNStWemRzZExlL3NXUHdYTjRObnRwbGoyekt0WmRONkUKRGozMHhGMWpPT1RCY3g5clMwOTN5SUpqZmU3d1BUNUdrK1J5b25FQW50QnlqRlZwMVFtUDBldVNaMVgyZCsyQQo4TVppRm50K2Fuc3RxbXBvcW5weFB6NGovTmhmc2tmM05sVUlER2FBQk5xUWIxMGtjQXZSd21zOXI3TmVibHZvCmV2ak1IMlVDZ1lFQWpnYlRGcnV0Ri9Kam82bW4zYW1HNVBWVGJ1S2NRUEdwUEZWRm1tZFlreCthRXk4b2xEV1EKcFF2Y0k0U0F4UVRnaGFXOUZkc3ZBUEtVMkdUbTZFR2VlR0ZuMERTZExPZ2ZLSW52UFMrbUo3NEhBTnllQWpmbApxR1diTWJRcXFtclQ4akVFemNRWENZYnVNZndZOTJyTVZwVXhRc3VVb1dzWXN2aVFkOGM5ZlN3PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
2
|
+
before_script:
|
|
3
|
+
- psql -c 'create database tentd_test;' -U postgres
|
|
4
|
+
env:
|
|
5
|
+
- TEST_DATABASE_URL=postgres://postgres@localhost/tentd_test
|
|
6
|
+
rvm:
|
|
7
|
+
- 1.9.3
|
|
8
|
+
- rbx-19mode
|
data/Gemfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
gem 'rack-test', :git => 'https://github.com/brynary/rack-test.git'
|
|
6
|
+
gem 'tent-client', :git => 'git://github.com/tent/tent-client-ruby.git', :branch => 'master'
|
|
7
|
+
gem 'rb-fsevent', '~> 0.9.1'
|
|
8
|
+
gem 'do_jdbc', :platform => :jruby
|
|
9
|
+
gem 'girl_friday', '~> 0.10'
|
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2012 Apollic Software, LLC
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# tentd 
|
|
2
|
+
|
|
3
|
+
tentd is an **alpha** implementation of a [Tent Protocol](http://tent.io) server.
|
|
4
|
+
It currently contains **broken code, ugly code, many bugs, and security flaws**.
|
|
5
|
+
The code should only be used to experiment with how Tent works. Under no
|
|
6
|
+
circumstances should the code in its current form be used for data that is
|
|
7
|
+
supposed to be private. All of the implemented APIs are in flux, and are
|
|
8
|
+
expected to change heavily before the Tent 1.0 release.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
TentD is written using Ruby 1.9 with Rack and Datamapper and is only tested with
|
|
14
|
+
PostgreSQL. The code needs a few fixes to work with 1.8 and other databases.
|
|
15
|
+
|
|
16
|
+
If you have Ruby 1.9, Bundler, and PostgreSQL installed, this should get the
|
|
17
|
+
tests running:
|
|
18
|
+
|
|
19
|
+
```shell
|
|
20
|
+
createdb tent_server_test
|
|
21
|
+
bundle install
|
|
22
|
+
rake
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If you want to run this as a Tent server, you should use
|
|
26
|
+
[tentd-admin](https://github.com/tent/tentd-admin).
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Contributions
|
|
30
|
+
|
|
31
|
+
If you want to help out with the TentD code instead of writing Tent clients and
|
|
32
|
+
applications, here are some areas that can be worked on:
|
|
33
|
+
|
|
34
|
+
- Fix database queries. There are a bunch of suboptimal uses of the database,
|
|
35
|
+
and basically no indexes. Low hanging fruit would be to turn on logging while
|
|
36
|
+
running the tests and index all the queries.
|
|
37
|
+
- Add data validation/normalization.
|
|
38
|
+
- Audit security.
|
|
39
|
+
- Refactor. The current code was hacked together quickly and is pretty ugly.
|
|
40
|
+
- Add tests. There are quite a few areas that aren't tested completely.
|
|
41
|
+
- Fix tests. A lot of tests are written as integration tests and depend on the
|
|
42
|
+
database, many would be much faster as unit tests that don't hit the database.
|
|
43
|
+
|
|
44
|
+
Please note that we are not looking for Pull Requests that make fundamental
|
|
45
|
+
changes to how the Tent Protocol works.
|
|
46
|
+
|
|
47
|
+
### Contributors
|
|
48
|
+
|
|
49
|
+
- [Jonas Schneider](https://github.com/jonasschneider)
|
data/Rakefile
ADDED
data/bin/tent-server
ADDED
data/lib/tentd.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'tentd/version'
|
|
2
|
+
require 'tent-client'
|
|
3
|
+
|
|
4
|
+
module TentD
|
|
5
|
+
autoload :API, 'tentd/api'
|
|
6
|
+
autoload :Action, 'tentd/action'
|
|
7
|
+
autoload :JsonPatch, 'tentd/json_patch'
|
|
8
|
+
autoload :TentVersion, 'tentd/tent_version'
|
|
9
|
+
autoload :TentType, 'tentd/tent_type'
|
|
10
|
+
|
|
11
|
+
def self.new(options={})
|
|
12
|
+
if options[:database] || ENV['DATABASE_URL']
|
|
13
|
+
DataMapper.setup(:default, options[:database] || ENV['DATABASE_URL'])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
require "tentd/notifications/#{options[:job_backend] || 'girl_friday'}"
|
|
17
|
+
|
|
18
|
+
@faraday_adapter = options[:faraday_adapter]
|
|
19
|
+
API.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.faraday_adapter
|
|
23
|
+
@faraday_adapter
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.faraday_adapter=(a)
|
|
27
|
+
@faraday_adapter = a
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
require 'tentd/model'
|
data/lib/tentd/api.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module TentD
|
|
2
|
+
class API
|
|
3
|
+
PER_PAGE = 50
|
|
4
|
+
MAX_PER_PAGE = 200
|
|
5
|
+
MEDIA_TYPE = 'application/vnd.tent.v0+json'.freeze
|
|
6
|
+
PROFILE_REL = 'https://tent.io/rels/profile'.freeze
|
|
7
|
+
|
|
8
|
+
autoload :Apps, 'tentd/api/apps'
|
|
9
|
+
autoload :Posts, 'tentd/api/posts'
|
|
10
|
+
autoload :Groups, 'tentd/api/groups'
|
|
11
|
+
autoload :Profile, 'tentd/api/profile'
|
|
12
|
+
autoload :Followers, 'tentd/api/followers'
|
|
13
|
+
autoload :Followings, 'tentd/api/followings'
|
|
14
|
+
autoload :CoreProfileData, 'tentd/api/core_profile_data'
|
|
15
|
+
autoload :UserLookup, 'tentd/api/user_lookup'
|
|
16
|
+
autoload :AuthenticationLookup, 'tentd/api/authentication_lookup'
|
|
17
|
+
autoload :AuthenticationVerification, 'tentd/api/authentication_verification'
|
|
18
|
+
autoload :AuthenticationFinalize, 'tentd/api/authentication_finalize'
|
|
19
|
+
autoload :Authorization, 'tentd/api/authorization'
|
|
20
|
+
autoload :Authorizable, 'tentd/api/authorizable'
|
|
21
|
+
autoload :Router, 'tentd/api/router'
|
|
22
|
+
autoload :Middleware, 'tentd/api/middleware'
|
|
23
|
+
include Router
|
|
24
|
+
|
|
25
|
+
mount Apps
|
|
26
|
+
mount Posts
|
|
27
|
+
mount Groups
|
|
28
|
+
mount Profile
|
|
29
|
+
mount Followers
|
|
30
|
+
mount Followings
|
|
31
|
+
|
|
32
|
+
class HelloWorld < Middleware
|
|
33
|
+
def action(env)
|
|
34
|
+
[200, { 'Link' => %(<%s>; rel="%s") % [File.join(env['SCRIPT_NAME'], 'profile'), PROFILE_REL] }, ['Tent!']]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class CorsPreflight < Middleware
|
|
39
|
+
def action(env)
|
|
40
|
+
headers = {
|
|
41
|
+
'Access-Control-Allow-Origin' => '*',
|
|
42
|
+
'Access-Control-Allow-Methods' => 'GET, POST, HEAD, PUT, DELETE, PATCH, OPTIONS',
|
|
43
|
+
'Access-Control-Allow-Headers' => 'Authorization',
|
|
44
|
+
'Access-Control-Max-Age' => '2592000' # 30 days
|
|
45
|
+
}
|
|
46
|
+
[200, headers, []]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
get '/' do |b|
|
|
51
|
+
b.use HelloWorld
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
options %r{/.*} do |b|
|
|
55
|
+
b.use CorsPreflight
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
module TentD
|
|
2
|
+
class API
|
|
3
|
+
class Apps
|
|
4
|
+
include Router
|
|
5
|
+
|
|
6
|
+
class GetActualId < Middleware
|
|
7
|
+
def action(env)
|
|
8
|
+
if env.params.app_id
|
|
9
|
+
if app = Model::App.first(:public_id => env.params.app_id)
|
|
10
|
+
env.params.app_id = app.id
|
|
11
|
+
else
|
|
12
|
+
env.params.app_id = nil
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if env.params.auth_id
|
|
17
|
+
if app_auth = Model::AppAuthorization.first(:public_id => env.params.auth_id)
|
|
18
|
+
env.params.auth_id = app_auth.id
|
|
19
|
+
else
|
|
20
|
+
env.params.auth_id = nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
env
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class AuthorizeReadOne < Middleware
|
|
29
|
+
def action(env)
|
|
30
|
+
authorize_env!(env, :read_apps) unless env.params.app_id && env.current_auth &&
|
|
31
|
+
env.current_auth.kind_of?(Model::App) &&
|
|
32
|
+
env.current_auth.id == env.params.app_id
|
|
33
|
+
env
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class AuthorizeReadAll < Middleware
|
|
38
|
+
def action(env)
|
|
39
|
+
authorize_env!(env, :read_apps)
|
|
40
|
+
env
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class AuthorizeWriteOne < Middleware
|
|
45
|
+
def action(env)
|
|
46
|
+
authorize_env!(env, :write_apps) unless env.params.app_id && env.current_auth &&
|
|
47
|
+
env.current_auth.kind_of?(Model::App) &&
|
|
48
|
+
env.current_auth.id == env.params.app_id
|
|
49
|
+
env
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class GetOne < Middleware
|
|
54
|
+
def action(env)
|
|
55
|
+
if app = Model::App.first(:id => env.params.app_id)
|
|
56
|
+
env.response = app
|
|
57
|
+
end
|
|
58
|
+
env
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class GetAll < Middleware
|
|
63
|
+
def action(env)
|
|
64
|
+
env.response = Model::App.all
|
|
65
|
+
env
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
class Create < Middleware
|
|
70
|
+
def action(env)
|
|
71
|
+
env.response = Model::App.create_from_params(env.params.data)
|
|
72
|
+
env.authorized_scopes << :read_secrets
|
|
73
|
+
env
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class CreateAuthorization < Middleware
|
|
78
|
+
def action(env)
|
|
79
|
+
unless authorize_env?(env, :write_apps)
|
|
80
|
+
if env.params.data.code
|
|
81
|
+
return AuthorizationTokenExchange.new(@app).call(env)
|
|
82
|
+
else
|
|
83
|
+
authorize_env!(env, :write_apps)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
if app = Model::App.first(:id => env.params.app_id)
|
|
88
|
+
env.authorized_scopes << :authorization_token
|
|
89
|
+
authorization = app.authorizations.create_from_params(
|
|
90
|
+
:app_id => env.params.app_id,
|
|
91
|
+
:notification_url => env.params.data.notification_url,
|
|
92
|
+
:post_types => env.params.data.post_types.to_a.map { |url| URI.decode(url) },
|
|
93
|
+
:profile_info_types => env.params.data.profile_info_types.to_a.map { |url| URI.decode(url) },
|
|
94
|
+
:scopes => env.params.data.scopes
|
|
95
|
+
)
|
|
96
|
+
env.response = authorization
|
|
97
|
+
end
|
|
98
|
+
env
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class AuthorizationTokenExchange < Middleware
|
|
103
|
+
def action(env)
|
|
104
|
+
if authorization = Model::AppAuthorization.first(:app_id => env.params.app_id, :token_code => env.params.data.code)
|
|
105
|
+
env.response = authorization.token_exchange!
|
|
106
|
+
else
|
|
107
|
+
raise Unauthorized
|
|
108
|
+
end
|
|
109
|
+
env
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class Update < Middleware
|
|
114
|
+
def action(env)
|
|
115
|
+
if app = Model::App.update_from_params(env.params.app_id, env.params.data)
|
|
116
|
+
env.response = app
|
|
117
|
+
end
|
|
118
|
+
env
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
class UpdateAppAuthorization < Middleware
|
|
123
|
+
def action(env)
|
|
124
|
+
authorize_env!(env, :write_apps)
|
|
125
|
+
if (auth = TentD::Model::AppAuthorization.first(:app_id => env.params.app_id, :id => env.params.auth_id)) &&
|
|
126
|
+
auth.update_from_params(env.params.data)
|
|
127
|
+
env.response = auth
|
|
128
|
+
end
|
|
129
|
+
env
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
class Destroy < Middleware
|
|
134
|
+
def action(env)
|
|
135
|
+
if (app = Model::App.get(env.params.app_id)) && app.destroy
|
|
136
|
+
env.response = ''
|
|
137
|
+
end
|
|
138
|
+
env
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
class DestroyAppAuthorization < Middleware
|
|
143
|
+
def action(env)
|
|
144
|
+
authorize_env!(env, :write_apps)
|
|
145
|
+
if (auth = TentD::Model::AppAuthorization.first(:app_id => env.params.app_id, :id => env.params.auth_id)) &&
|
|
146
|
+
auth.destroy
|
|
147
|
+
env.response = ''
|
|
148
|
+
end
|
|
149
|
+
env
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
get '/apps/:app_id' do |b|
|
|
154
|
+
b.use GetActualId
|
|
155
|
+
b.use AuthorizeReadOne
|
|
156
|
+
b.use GetOne
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
get '/apps' do |b|
|
|
160
|
+
b.use AuthorizeReadAll
|
|
161
|
+
b.use GetAll
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
post '/apps' do |b|
|
|
165
|
+
b.use Create
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
post '/apps/:app_id/authorizations' do |b|
|
|
169
|
+
b.use GetActualId
|
|
170
|
+
b.use CreateAuthorization
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
put '/apps/:app_id/authorizations/:auth_id' do |b|
|
|
174
|
+
b.use GetActualId
|
|
175
|
+
b.use UpdateAppAuthorization
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
delete '/apps/:app_id/authorizations/:auth_id' do |b|
|
|
179
|
+
b.use GetActualId
|
|
180
|
+
b.use DestroyAppAuthorization
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
put '/apps/:app_id' do |b|
|
|
184
|
+
b.use GetActualId
|
|
185
|
+
b.use AuthorizeWriteOne
|
|
186
|
+
b.use Update
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
delete '/apps/:app_id' do |b|
|
|
190
|
+
b.use GetActualId
|
|
191
|
+
b.use AuthorizeWriteOne
|
|
192
|
+
b.use Destroy
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module TentD
|
|
2
|
+
class API
|
|
3
|
+
class AuthenticationFinalize < Middleware
|
|
4
|
+
def action(env)
|
|
5
|
+
return env unless env.hmac? && env.hmac.verified
|
|
6
|
+
env.current_auth = env.potential_auth
|
|
7
|
+
env.current_auth.update(:mac_timestamp_delta => Time.now.to_i - env.hmac.ts.to_i) unless env.current_auth.mac_timestamp_delta
|
|
8
|
+
env
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module TentD
|
|
2
|
+
class API
|
|
3
|
+
class AuthenticationLookup < Middleware
|
|
4
|
+
def action(env)
|
|
5
|
+
return env unless env['HTTP_AUTHORIZATION']
|
|
6
|
+
env['hmac'] = Hash[env['HTTP_AUTHORIZATION'].scan(/([a-z]+)="([^"]+)"/i)]
|
|
7
|
+
mac_key_id = env['hmac']['id']
|
|
8
|
+
env.potential_auth = case mac_key_id.to_s[0,1]
|
|
9
|
+
when 's'
|
|
10
|
+
TentD::Model::Follower.first(:mac_key_id => mac_key_id)
|
|
11
|
+
when 'a'
|
|
12
|
+
TentD::Model::App.first(:mac_key_id => mac_key_id)
|
|
13
|
+
when 'u'
|
|
14
|
+
TentD::Model::AppAuthorization.first(:mac_key_id => mac_key_id)
|
|
15
|
+
end
|
|
16
|
+
env.potential_auth = Model::Following.first(:mac_key_id => mac_key_id) unless env.potential_auth
|
|
17
|
+
if env.potential_auth
|
|
18
|
+
env.hmac.secret = env.potential_auth.mac_key
|
|
19
|
+
env.hmac.algorithm = env.potential_auth.mac_algorithm
|
|
20
|
+
else
|
|
21
|
+
env.hmac = nil
|
|
22
|
+
end
|
|
23
|
+
env
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|