social_snippet-registry_core 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.
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