social_snippet-registry_core 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.components +9 -0
- data/.gitignore +18 -0
- data/.travis.yml +26 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +15 -0
- data/config.ru +9 -0
- data/config/apps.rb +26 -0
- data/config/boot.rb +50 -0
- data/config/database.rb +45 -0
- data/lib/social_snippet/registry/webapi.rb +5 -0
- data/lib/social_snippet/registry/webapi/controllers/v0/repositories_controller.rb +37 -0
- data/lib/social_snippet/registry/webapi/controllers/v0/token_controller.rb +13 -0
- data/lib/social_snippet/registry/webapi/controllers/v0/user_controller.rb +49 -0
- data/lib/social_snippet/registry/webapi/helpers/repository_helper.rb +18 -0
- data/lib/social_snippet/registry/webapi/helpers/url_helper.rb +29 -0
- data/lib/social_snippet/registry/webapi/models/repository.rb +75 -0
- data/lib/social_snippet/registry/webapi/models/user_account.rb +30 -0
- data/lib/social_snippet/registry/webapi/webapi_base.rb +12 -0
- data/lib/social_snippet/registry/webapi/webapi_v0.rb +3 -0
- data/lib/social_snippet/registry_core.rb +8 -0
- data/lib/social_snippet/registry_core/common_helpers.rb +11 -0
- data/lib/social_snippet/registry_core/config_helpers.rb +95 -0
- data/lib/social_snippet/registry_core/fetcher.rb +3 -0
- data/lib/social_snippet/registry_core/fetcher/fetcher_base.rb +19 -0
- data/lib/social_snippet/registry_core/fetcher/github_fetcher.rb +69 -0
- data/lib/social_snippet/registry_core/version.rb +5 -0
- data/lib/social_snippet/registry_core/version_helpers.rb +21 -0
- data/social_snippet-registry_core.gemspec +36 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/spec_helpers/database_cleaner_helper.rb +18 -0
- data/spec/spec_helpers/factory_girl_helper.rb +9 -0
- data/spec/spec_helpers/rack_test_helper.rb +18 -0
- data/spec/webapi/controllers/v0/repositories_controller_spec.rb +232 -0
- data/spec/webapi/helpers/url_helper_spec.rb +49 -0
- data/spec/webapi/models/repository_spec.rb +72 -0
- metadata +256 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
class Repository
|
2
|
+
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps # adds created_at and updated_at fields
|
5
|
+
|
6
|
+
# field <name>, :type => <type>, :default => <value>
|
7
|
+
|
8
|
+
# Repository's Name (e.g. "my-repo")
|
9
|
+
field :name, :type => String
|
10
|
+
|
11
|
+
# Repository's URL (e.g. "git://github.com/user/repo.git")
|
12
|
+
field :url, :type => String
|
13
|
+
|
14
|
+
# Repository's description (e.g. "This is my repository.")
|
15
|
+
field :desc, :type => String
|
16
|
+
|
17
|
+
# Repository's dependencies (e.g. ["dep-to-1", "dep-to-2", ...])
|
18
|
+
field :dependencies, :type => Array, :default => lambda { [] }
|
19
|
+
|
20
|
+
# You can define indexes on documents using the index macro:
|
21
|
+
# index :field <, :unique => true>
|
22
|
+
index({name: 1}, {unique: true})
|
23
|
+
|
24
|
+
# You can create a composite key in mongoid to replace the default id using the key macro:
|
25
|
+
# key :field <, :another_field, :one_more ....>
|
26
|
+
|
27
|
+
# validations
|
28
|
+
validates_presence_of :name
|
29
|
+
validates_presence_of :url
|
30
|
+
|
31
|
+
# methods
|
32
|
+
|
33
|
+
FIELD_KEYS = [
|
34
|
+
:name,
|
35
|
+
:url,
|
36
|
+
:desc,
|
37
|
+
:dependencies,
|
38
|
+
]
|
39
|
+
|
40
|
+
def to_object
|
41
|
+
FIELD_KEYS.reduce({}) do |obj, key|
|
42
|
+
obj[key.to_sym] = self[key]
|
43
|
+
obj
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def update_by_snippet_json(json_obj)
|
48
|
+
filter = %w(
|
49
|
+
desc
|
50
|
+
)
|
51
|
+
repo_info = json_obj.select {|k, v| filter.include? k }
|
52
|
+
write_attributes repo_info
|
53
|
+
# deps: hash to array
|
54
|
+
self.dependencies = json_obj["dependencies"] && json_obj["dependencies"].keys
|
55
|
+
end
|
56
|
+
|
57
|
+
class << self
|
58
|
+
|
59
|
+
def all_repos
|
60
|
+
all.map {|repo| repo.to_object }
|
61
|
+
end
|
62
|
+
|
63
|
+
def query(s)
|
64
|
+
where(:name => /#{s}/).map {|repo| repo.to_object } # TODO
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_by_snippet_json(json_obj)
|
68
|
+
model = find_or_create_by(:name => json_obj["name"])
|
69
|
+
model.update_by_snippet_json json_obj
|
70
|
+
return model
|
71
|
+
end
|
72
|
+
|
73
|
+
end # class << self
|
74
|
+
|
75
|
+
end # Repository
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class UserAccount
|
2
|
+
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps # adds created_at and updated_at fields
|
5
|
+
|
6
|
+
# field <name>, :type => <type>, :default => <value>
|
7
|
+
field :name, :type => String
|
8
|
+
field :github_user_id, :type => Integer
|
9
|
+
field :github_access_token, :type => String
|
10
|
+
field :github_repos, :type => Array
|
11
|
+
|
12
|
+
# You can define indexes on documents using the index macro:
|
13
|
+
# index :field <, :unique => true>
|
14
|
+
|
15
|
+
# You can create a composite key in mongoid to replace the default id using the key macro:
|
16
|
+
# key :field <, :another_field, :one_more ....>
|
17
|
+
|
18
|
+
def self.find_by_id(s)
|
19
|
+
if s.nil?
|
20
|
+
nil
|
21
|
+
else
|
22
|
+
begin
|
23
|
+
find s
|
24
|
+
rescue
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module SocialSnippt
|
2
|
+
module RegistryCore; end
|
3
|
+
end
|
4
|
+
require_relative "registry_core/common_helpers"
|
5
|
+
require_relative "registry_core/config_helpers"
|
6
|
+
require_relative "registry_core/version"
|
7
|
+
require_relative "registry_core/version_helpers"
|
8
|
+
require_relative "registry_core/fetcher"
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module SocialSnippet::RegistryCore::ConfigHelpers
|
2
|
+
|
3
|
+
require "padrino"
|
4
|
+
require "rack/session/dalli"
|
5
|
+
require "rack/parser"
|
6
|
+
require "rack/tracker"
|
7
|
+
require "omniauth-github"
|
8
|
+
|
9
|
+
#
|
10
|
+
# call from padrino-app
|
11
|
+
#
|
12
|
+
|
13
|
+
def sspm_enable_tracker
|
14
|
+
unless ENV["SSPM_GOOGLE_ANALYTICS"].nil?
|
15
|
+
use ::Rack::Tracker do
|
16
|
+
handler :google_analytics, { tracker: ENV["SSPM_GOOGLE_ANALYTICS"] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def sspm_enable_json_params
|
22
|
+
logger.info "Enable JSON Params: #{self}"
|
23
|
+
|
24
|
+
use ::Rack::Parser, :parsers => {
|
25
|
+
"application/json" => proc { |data| JSON.parse data },
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def sspm_enable_user_access_control
|
30
|
+
if settings.sspm_session
|
31
|
+
logger.info "Enable User Access Control: #{self}"
|
32
|
+
|
33
|
+
register ::Padrino::Admin::AccessControl
|
34
|
+
set :admin_model, "UserAccount"
|
35
|
+
set :login_page, :login
|
36
|
+
enable :authentication
|
37
|
+
enable :store_location
|
38
|
+
|
39
|
+
# check session
|
40
|
+
before do
|
41
|
+
if session[:user] && ( not logged_in? )
|
42
|
+
set_current_account session[:user]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def sspm_enable_omniauth
|
49
|
+
return if @sspm_enable_omniauth_visited
|
50
|
+
@sspm_enable_omniauth_visited = true
|
51
|
+
|
52
|
+
if settings.sspm_session
|
53
|
+
logger.info "Enable GitHub Authentication: #{self}"
|
54
|
+
|
55
|
+
use OmniAuth::Builder do
|
56
|
+
provider(
|
57
|
+
:github,
|
58
|
+
ENV["SSPM_GITHUB_CLIENT_ID"],
|
59
|
+
ENV["SSPM_GITHUB_CLIENT_SECRET"],
|
60
|
+
{
|
61
|
+
:provider_ignores_state => true, # TODO: re-check
|
62
|
+
}
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def sspm_enable_session
|
69
|
+
if settings.sspm_session
|
70
|
+
logger.info "Enable Session: #{self}"
|
71
|
+
|
72
|
+
set :protection, false
|
73
|
+
set :protect_from_csrf, false
|
74
|
+
disable :sessions
|
75
|
+
|
76
|
+
if ENV["SSPM_MEMCACHED_USERNAME"].nil?
|
77
|
+
memcached_client = Dalli::Client.new(ENV["SSPM_MEMCACHED_HOST"])
|
78
|
+
else
|
79
|
+
memcached_client = Dalli::Client.new(
|
80
|
+
ENV["SSPM_MEMCACHED_HOST"],
|
81
|
+
username: ENV["SSPM_MEMCACHED_USERNAME"],
|
82
|
+
password: ENV["SSPM_MEMCACHED_PASSWORD"],
|
83
|
+
)
|
84
|
+
end
|
85
|
+
use ::Rack::Session::Dalli, {
|
86
|
+
:cache => memcached_client,
|
87
|
+
:expire_after => 14 * 24 * 3600,
|
88
|
+
}
|
89
|
+
|
90
|
+
use ::Rack::Protection
|
91
|
+
use ::Rack::Protection::AuthenticityToken, :authenticity_param => '_csrf_token'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class SocialSnippet::RegistryCore::Fetcher::FetcherBase
|
2
|
+
|
3
|
+
require "version_sorter"
|
4
|
+
|
5
|
+
def latest_version(vers)
|
6
|
+
VersionSorter.rsort(vers).first
|
7
|
+
end
|
8
|
+
|
9
|
+
def versions(owner_id, repo_id)
|
10
|
+
refs_by(owner_id, repo_id).select do |ref|
|
11
|
+
VersionHelpers.is_version?(ref)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def snippet_json(url)
|
16
|
+
raise "not implemented"
|
17
|
+
end
|
18
|
+
|
19
|
+
end # FetcherBase
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module SocialSnippet::RegistryCore::Fetcher
|
2
|
+
|
3
|
+
class GitHubFetcher < FetcherBase
|
4
|
+
|
5
|
+
require "octokit"
|
6
|
+
require "json"
|
7
|
+
require "base64"
|
8
|
+
|
9
|
+
SNIPPET_JSON_NAME = "snippet.json"
|
10
|
+
|
11
|
+
def snippet_json(url)
|
12
|
+
info = parse_url(url)
|
13
|
+
snippet_json_by info[:owner_id], info[:repo_id]
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_github?(uri)
|
17
|
+
return uri.scheme === "git" &&
|
18
|
+
uri.host === "github.com" &&
|
19
|
+
/\/[a-z0-9\-]+\/[a-z0-9\-\.\_]+\.git/ === uri.path
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_url(url)
|
23
|
+
uri = URI.parse(url)
|
24
|
+
if is_github?(uri)
|
25
|
+
matches = /\/([a-z0-9\-]+)\/([a-z0-9\-\.\_]+)\.git/.match(uri.path)
|
26
|
+
return {
|
27
|
+
:owner_id => matches[1],
|
28
|
+
:repo_id => matches[2],
|
29
|
+
}
|
30
|
+
else
|
31
|
+
raise "should be passed GitHub URL"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def client
|
36
|
+
@client ||= ::Octokit::Client.new(
|
37
|
+
:client_id => ENV["SSPM_GITHUB_CLIENT_ID"],
|
38
|
+
:client_secret => ENV["SSPM_GITHUB_CLIENT_SECRET"],
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def snippet_json_by(owner_id, repo_id)
|
43
|
+
begin
|
44
|
+
opts = {}
|
45
|
+
opts[:path] = SNIPPET_JSON_NAME
|
46
|
+
|
47
|
+
# resolve version
|
48
|
+
vers = versions(owner_id, repo_id)
|
49
|
+
unless vers.empty?
|
50
|
+
opts[:ref] = latest_version(vers)
|
51
|
+
end
|
52
|
+
|
53
|
+
contents_info = client.contents("#{owner_id}/#{repo_id}", opts)
|
54
|
+
decoded_content = ::Base64.decode64(contents_info[:content])
|
55
|
+
return ::JSON.parse(decoded_content)
|
56
|
+
rescue ::Octokit::NotFound => error
|
57
|
+
raise "not found"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def refs_by(owner_id, repo_id)
|
62
|
+
client.refs("#{owner_id}/#{repo_id}")
|
63
|
+
.map {|ref_info| ref_info[:ref] }
|
64
|
+
.map {|ref| ref.gsub /^refs\/[a-z]+\//, "" }
|
65
|
+
end
|
66
|
+
|
67
|
+
end # GitHubFetcher
|
68
|
+
|
69
|
+
end # SocialSnippet
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SocialSnippet::RegistryCore::VersionHelpers
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# Check given text whether matches version pattern
|
6
|
+
def test_version(pattern, version)
|
7
|
+
return true if pattern == "" || pattern.nil?
|
8
|
+
return true if pattern == version
|
9
|
+
# "2.1.0" and "2.1.1" match "2.1"
|
10
|
+
# "2.11.0" and "2.11.1" do not match "2.1"
|
11
|
+
return version.start_with?("#{pattern}.")
|
12
|
+
end
|
13
|
+
|
14
|
+
# Check given text is version string
|
15
|
+
def is_version?(s)
|
16
|
+
return /^([0]|[1-9][0-9]*)\.([0]|[1-9][0-9]*)\.([0]|[1-9][0-9]*)$/ === s
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end # VersionHelpers
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'social_snippet/registry_core/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "social_snippet-registry_core"
|
8
|
+
spec.version = SocialSnippet::RegistryCore::VERSION
|
9
|
+
spec.authors = ["Hiroyuki Sano"]
|
10
|
+
spec.email = ["sh19910711@gmail.com"]
|
11
|
+
spec.summary = %q{The server-side core classes for social-snippet-registry}
|
12
|
+
spec.homepage = "https://sspm.herokuapp.com"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.required_ruby_version = ">= 1.9"
|
21
|
+
|
22
|
+
spec.add_runtime_dependency "bundler"
|
23
|
+
spec.add_runtime_dependency "rake"
|
24
|
+
|
25
|
+
spec.add_runtime_dependency "padrino", "~> 0.12"
|
26
|
+
spec.add_runtime_dependency "thin"
|
27
|
+
spec.add_runtime_dependency "mongoid", "~> 4.0"
|
28
|
+
spec.add_runtime_dependency "rack-parser"
|
29
|
+
spec.add_runtime_dependency "rack-tracker"
|
30
|
+
spec.add_runtime_dependency "slim"
|
31
|
+
spec.add_runtime_dependency "dalli"
|
32
|
+
|
33
|
+
spec.add_runtime_dependency "version_sorter"
|
34
|
+
spec.add_runtime_dependency "octokit"
|
35
|
+
spec.add_runtime_dependency "omniauth-github"
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "database_cleaner"
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
|
5
|
+
config.before(:suite) do
|
6
|
+
DatabaseCleaner.strategy = :truncation
|
7
|
+
DatabaseCleaner.clean_with :truncation
|
8
|
+
end
|
9
|
+
|
10
|
+
config.before(:each) do
|
11
|
+
DatabaseCleaner.start
|
12
|
+
end
|
13
|
+
|
14
|
+
config.after(:each) do
|
15
|
+
DatabaseCleaner.clean
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|