social_snippet-registry_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +15 -0
  2. data/.components +9 -0
  3. data/.gitignore +18 -0
  4. data/.travis.yml +26 -0
  5. data/Gemfile +17 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +31 -0
  8. data/Rakefile +15 -0
  9. data/config.ru +9 -0
  10. data/config/apps.rb +26 -0
  11. data/config/boot.rb +50 -0
  12. data/config/database.rb +45 -0
  13. data/lib/social_snippet/registry/webapi.rb +5 -0
  14. data/lib/social_snippet/registry/webapi/controllers/v0/repositories_controller.rb +37 -0
  15. data/lib/social_snippet/registry/webapi/controllers/v0/token_controller.rb +13 -0
  16. data/lib/social_snippet/registry/webapi/controllers/v0/user_controller.rb +49 -0
  17. data/lib/social_snippet/registry/webapi/helpers/repository_helper.rb +18 -0
  18. data/lib/social_snippet/registry/webapi/helpers/url_helper.rb +29 -0
  19. data/lib/social_snippet/registry/webapi/models/repository.rb +75 -0
  20. data/lib/social_snippet/registry/webapi/models/user_account.rb +30 -0
  21. data/lib/social_snippet/registry/webapi/webapi_base.rb +12 -0
  22. data/lib/social_snippet/registry/webapi/webapi_v0.rb +3 -0
  23. data/lib/social_snippet/registry_core.rb +8 -0
  24. data/lib/social_snippet/registry_core/common_helpers.rb +11 -0
  25. data/lib/social_snippet/registry_core/config_helpers.rb +95 -0
  26. data/lib/social_snippet/registry_core/fetcher.rb +3 -0
  27. data/lib/social_snippet/registry_core/fetcher/fetcher_base.rb +19 -0
  28. data/lib/social_snippet/registry_core/fetcher/github_fetcher.rb +69 -0
  29. data/lib/social_snippet/registry_core/version.rb +5 -0
  30. data/lib/social_snippet/registry_core/version_helpers.rb +21 -0
  31. data/social_snippet-registry_core.gemspec +36 -0
  32. data/spec/spec_helper.rb +9 -0
  33. data/spec/spec_helpers/database_cleaner_helper.rb +18 -0
  34. data/spec/spec_helpers/factory_girl_helper.rb +9 -0
  35. data/spec/spec_helpers/rack_test_helper.rb +18 -0
  36. data/spec/webapi/controllers/v0/repositories_controller_spec.rb +232 -0
  37. data/spec/webapi/helpers/url_helper_spec.rb +49 -0
  38. data/spec/webapi/models/repository_spec.rb +72 -0
  39. 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,12 @@
1
+ module SocialSnippet::Registry::WebAPI
2
+
3
+ require "social_snippet/registry_core/fetcher"
4
+ require "mongoid"
5
+ require "uri"
6
+
7
+ class WebAPIBase < ::Padrino::Application
8
+ register Padrino::Helpers
9
+ sspm_enable_json_params
10
+ end
11
+
12
+ end # WebAPI
@@ -0,0 +1,3 @@
1
+ module SocialSnippet::Registry::WebAPI
2
+ class WebAPIv0 < WebAPIBase; end
3
+ 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,11 @@
1
+ module SocialSnippet::RegistryCore::CommonHelpers
2
+
3
+ def assets_host
4
+ if ENV["SSPM_ASSETS_HOST"].nil?
5
+ ""
6
+ else
7
+ "//#{ENV["SSPM_ASSETS_HOST"]}"
8
+ end
9
+ end
10
+
11
+ end
@@ -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,3 @@
1
+ module SocialSnippet::RegistryCore::Fetcher; end
2
+ require_relative "fetcher/fetcher_base"
3
+ require_relative "fetcher/github_fetcher"
@@ -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,5 @@
1
+ module SocialSnippet
2
+ module RegistryCore
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ ENV["RACK_ENV"] = "test"
2
+
3
+ require "bundler/setup"
4
+ require "spec_helpers/rack_test_helper"
5
+ require "spec_helpers/database_cleaner_helper"
6
+ require "spec_helpers/factory_girl_helper"
7
+
8
+ # Boot Padrino
9
+ require_relative "../config/boot"
@@ -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
@@ -0,0 +1,9 @@
1
+ require "factory_girl"
2
+
3
+ RSpec.configure do |config|
4
+
5
+ config.before(:each) do
6
+ FactoryGirl.reload
7
+ end
8
+
9
+ end