Skip to content

Commit 28dec7e

Browse files
parkrjekyllbot
authored andcommitted
Move owner_metadata to an Owner class and add specs (#159)
Merge pull request 159
1 parent e0c6b5c commit 28dec7e

File tree

9 files changed

+227
-62
lines changed

9 files changed

+227
-62
lines changed

lib/jekyll-github-metadata.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module GitHubMetadata
1717
autoload :Client, "jekyll-github-metadata/client"
1818
autoload :EditLinkTag, "jekyll-github-metadata/edit-link-tag"
1919
autoload :MetadataDrop, "jekyll-github-metadata/metadata_drop"
20+
autoload :Owner, "jekyll-github-metadata/owner"
2021
autoload :Pages, "jekyll-github-metadata/pages"
2122
autoload :Repository, "jekyll-github-metadata/repository"
2223
autoload :RepositoryFinder, "jekyll-github-metadata/repository_finder"
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# frozen_string_literal: true
2+
3+
module Jekyll
4+
module GitHubMetadata
5+
class Owner
6+
extend Forwardable
7+
8+
# Defines an instance method that delegates to a hash's key
9+
#
10+
# hash - a symbol representing the instance method to delegate to. The
11+
# instance method should return a hash or respond to #[]
12+
# key - the key to call within the hash
13+
# method - (optional) the instance method the key should be aliased to.
14+
# If not specified, defaults to the hash key
15+
#
16+
# Returns a symbol representing the instance method
17+
def self.def_hash_delegators(hash, *methods)
18+
content_methods.concat(methods)
19+
methods.each do |method|
20+
define_method(method) do
21+
send(hash)[method.to_s]
22+
end
23+
end
24+
end
25+
26+
def self.content_methods
27+
@content_methods ||= []
28+
end
29+
30+
# List of whitelisted keys.
31+
def_hash_delegators :owner_info,
32+
:avatar_url,
33+
:bio,
34+
:blog,
35+
:collaborators,
36+
:company,
37+
:created_at,
38+
:description,
39+
:email,
40+
:followers,
41+
:following,
42+
:has_organization_projects,
43+
:has_repository_projects,
44+
:hireable,
45+
:html_url,
46+
:id,
47+
:is_verified,
48+
:location,
49+
:login,
50+
:name,
51+
:node_id,
52+
:public_gists,
53+
:public_gists,
54+
:public_repos,
55+
:public_repos,
56+
:type,
57+
:updated_at
58+
59+
attr_reader :owner_login
60+
61+
def initialize(owner_login)
62+
@owner_login = owner_login
63+
end
64+
65+
def to_s
66+
require "json"
67+
JSON.pretty_generate to_h
68+
end
69+
alias_method :to_str, :to_s
70+
71+
def to_h
72+
self.class.content_methods.each_with_object({}) { |method, hash| hash[method] = public_send(method) }
73+
end
74+
75+
private
76+
77+
def owner_info
78+
@owner_info ||= begin
79+
Value.new(
80+
proc do |c|
81+
(c.organization(owner_login) || c.user(owner_login) || {}).to_h
82+
end
83+
).render || {}
84+
end
85+
end
86+
end
87+
end
88+
end

lib/jekyll-github-metadata/repository.rb

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -62,63 +62,8 @@ def repo_pages_info_opts
6262
end
6363
end
6464

65-
# Whitelisted keys for Organizations and Users
66-
WHITELISTED_ORGANIZATION_KEYS = Set.new([
67-
:login,
68-
:id,
69-
:node_id,
70-
:url,
71-
:avatar_url,
72-
:description,
73-
:name,
74-
:company,
75-
:blog,
76-
:location,
77-
:email,
78-
:is_verified,
79-
:has_organization_projects,
80-
:has_repository_projects,
81-
:public_repos,
82-
:public_gists,
83-
:followers,
84-
:following,
85-
:html_url,
86-
:created_at,
87-
:type,
88-
:collaborators,
89-
])
90-
91-
WHITELISTED_USER_KEYS = Set.new([
92-
:login,
93-
:id,
94-
:node_id,
95-
:avatar_url,
96-
:html_url,
97-
:type,
98-
:site_admin,
99-
:name,
100-
:company,
101-
:blog,
102-
:location,
103-
:bio,
104-
:public_repos,
105-
:public_gists,
106-
:followers,
107-
:following,
108-
:hireable,
109-
:created_at,
110-
:updated_at,
111-
])
112-
11365
def owner_metadata
114-
memoize_value :@owner_metadata, Value.new(proc { |c|
115-
org = c.organization(owner)
116-
if org
117-
org.to_h.select { |k, _| WHITELISTED_ORGANIZATION_KEYS.include? k }
118-
else
119-
c.user(owner).to_h.select { |k, _| WHITELISTED_USER_KEYS.include? k }
120-
end
121-
})
66+
@owner_metadata ||= Jekyll::GitHubMetadata::Owner.new(owner)
12267
end
12368

12469
def owner_url

lib/jekyll-github-metadata/sanitizer.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def sanitize(resource)
2121
case resource
2222
when Array
2323
resource.map { |item| sanitize(item) }
24-
when Numeric
24+
when Numeric, Time
2525
resource
2626
when FalseClass
2727
false

spec/owner_spec.rb

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# frozen_string_literal: true
2+
3+
require "spec_helper"
4+
5+
RSpec.describe(Jekyll::GitHubMetadata::Owner) do
6+
subject { described_class.new(login) }
7+
before(:each) do
8+
ENV["JEKYLL_GITHUB_TOKEN"] = "allthespecs"
9+
end
10+
11+
context "is an ORG" do
12+
let(:login) { "jekyll" }
13+
let!(:stub) do
14+
stub_api("/orgs/#{login}", "org")
15+
end
16+
17+
EXPECTED_ATTRIBUTES_ORG = {
18+
:login => "jekyll",
19+
:id => 3_083_652,
20+
:node_id => "MDEyOk9yZ2FuaXphdGlvbjMwODM2NTI=",
21+
:avatar_url => "https://avatars0.githubusercontent.com/u/3083652?v=4",
22+
:description => "Jekyll is a blog-aware, static site generator in Ruby.",
23+
:name => "Jekyll",
24+
:company => nil,
25+
:blog => "https://jekyllrb.com",
26+
:location => nil,
27+
:email => "",
28+
:is_verified => true,
29+
:has_organization_projects => true,
30+
:has_repository_projects => true,
31+
:public_repos => 50,
32+
:public_gists => 0,
33+
:followers => 0,
34+
:following => 0,
35+
:html_url => "https://github.com/jekyll",
36+
:created_at => Time.parse("2012-12-19 19:37:35 UTC"),
37+
:updated_at => Time.parse("2019-01-27 15:27:32 UTC"),
38+
:type => "Organization",
39+
}.freeze
40+
41+
EXPECTED_ATTRIBUTES_ORG.each do |attribute, expected_value|
42+
it "fetches #{attribute}" do
43+
expect(subject.public_send(attribute)).to eq(expected_value)
44+
end
45+
end
46+
47+
it "blocks denied attributes" do
48+
expect(subject).not_to respond_to(:repos_url)
49+
end
50+
end
51+
52+
context "is a USER" do
53+
let(:login) { "jekyllbot" }
54+
let!(:stub) do
55+
stub_api_404("/orgs/#{login}")
56+
stub_api("/users/#{login}", "user")
57+
end
58+
59+
EXPECTED_ATTRIBUTES_USER = {
60+
:login => "jekyllbot",
61+
:id => 6_166_343,
62+
:node_id => "MDQ6VXNlcjYxNjYzNDM=",
63+
:avatar_url => "https://avatars0.githubusercontent.com/u/6166343?v=4",
64+
:type => "User",
65+
:name => "jekyllbot",
66+
:company => nil,
67+
:blog => "https://github.com/parkr/auto-reply",
68+
:location => nil,
69+
:email => nil,
70+
:hireable => nil,
71+
:bio => "I help make working with @jekyll fun and easy.",
72+
:public_repos => 2,
73+
:public_gists => 0,
74+
:followers => 68,
75+
:following => 0,
76+
:created_at => Time.parse("2013-12-12 02:49:00 UTC"),
77+
:updated_at => Time.parse("2017-12-05 21:23:41 UTC"),
78+
}.freeze
79+
80+
EXPECTED_ATTRIBUTES_USER.each do |attribute, expected_value|
81+
it "fetches #{attribute}" do
82+
expect(subject.public_send(attribute)).to eq(expected_value)
83+
end
84+
end
85+
86+
it "blocks denied attributes" do
87+
expect(subject).not_to respond_to(:site_admin)
88+
expect(subject).not_to respond_to(:repos_url)
89+
end
90+
end
91+
end

spec/spec_helpers/integration_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def expected_values
1515
"build_revision" => %r![a-f0-9]{40}!,
1616
"project_title" => "github-metadata",
1717
"project_tagline" => ":octocat: `site.github`",
18-
"owner" => Regexp.new('"login"=>"jekyll", "id"=>3083652'),
18+
"owner" => Regexp.new('"html_url": "https://github.com/jekyll",\s+"id": 3083652'),
1919
"owner_name" => "jekyll",
2020
"owner_url" => "https://github.com/jekyll",
2121
"owner_gravatar_url" => "https://github.com/jekyll.png",

spec/spec_helpers/web_mock_helper.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ def stub_api(path, filename, req_headers = {})
2626
)
2727
end
2828

29+
def stub_api_404(path, req_headers = {})
30+
WebMock.disable_net_connect!
31+
stub_request(:get, url(path))
32+
.with(:headers => request_headers.merge(req_headers))
33+
.to_return(
34+
:status => 404,
35+
:headers => RESPONSE_HEADERS
36+
)
37+
end
38+
2939
def expect_api_call(path)
3040
expect(WebMock).to have_requested(:get, url(path))
3141
.with(:headers => request_headers).once

spec/webmock/api_get_org.json

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,30 @@
1-
{"login":"jekyll","id":3083652,"url":"https://api.github.com/orgs/jekyll","repos_url":"https://api.github.com/orgs/jekyll/repos","events_url":"https://api.github.com/orgs/jekyll/events","hooks_url":"https://api.github.com/orgs/jekyll/hooks","issues_url":"https://api.github.com/orgs/jekyll/issues","members_url":"https://api.github.com/orgs/jekyll/members{/member}","public_members_url":"https://api.github.com/orgs/jekyll/public_members{/member}","avatar_url":"https://avatars.githubusercontent.com/u/3083652?v=3","description":"Jekyll is a blog-aware, static site generator in Ruby.","name":"Jekyll","company":null,"blog":"http://jekyllrb.com","location":"","email":"","public_repos":43,"public_gists":0,"followers":0,"following":0,"html_url":"https://github.com/jekyll","created_at":"2012-12-19T19:37:35Z","updated_at":"2016-01-26T20:22:17Z","type":"Organization","total_private_repos":3,"owned_private_repos":3,"private_gists":0,"disk_usage":110870,"collaborators":0,"billing_email":"tom+jekyll@github.com","plan":{"name":"bronze","space":976562499,"private_repos":10}}
1+
{
2+
"login": "jekyll",
3+
"id": 3083652,
4+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjMwODM2NTI=",
5+
"url": "https://api.github.com/orgs/jekyll",
6+
"repos_url": "https://api.github.com/orgs/jekyll/repos",
7+
"events_url": "https://api.github.com/orgs/jekyll/events",
8+
"hooks_url": "https://api.github.com/orgs/jekyll/hooks",
9+
"issues_url": "https://api.github.com/orgs/jekyll/issues",
10+
"members_url": "https://api.github.com/orgs/jekyll/members{/member}",
11+
"public_members_url": "https://api.github.com/orgs/jekyll/public_members{/member}",
12+
"avatar_url": "https://avatars0.githubusercontent.com/u/3083652?v=4",
13+
"description": "Jekyll is a blog-aware, static site generator in Ruby.",
14+
"name": "Jekyll",
15+
"company": null,
16+
"blog": "https://jekyllrb.com",
17+
"location": null,
18+
"email": "",
19+
"is_verified": true,
20+
"has_organization_projects": true,
21+
"has_repository_projects": true,
22+
"public_repos": 50,
23+
"public_gists": 0,
24+
"followers": 0,
25+
"following": 0,
26+
"html_url": "https://github.com/jekyll",
27+
"created_at": "2012-12-19T19:37:35Z",
28+
"updated_at": "2019-01-27T15:27:32Z",
29+
"type": "Organization"
30+
}

spec/webmock/api_get_user.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"login": "jekyllbot",
33
"id": 6166343,
4-
"avatar_url": "https://avatars.githubusercontent.com/u/6166343?v=3",
4+
"node_id": "MDQ6VXNlcjYxNjYzNDM=",
5+
"avatar_url": "https://avatars0.githubusercontent.com/u/6166343?v=4",
56
"gravatar_id": "",
67
"url": "https://api.github.com/users/jekyllbot",
78
"html_url": "https://github.com/jekyllbot",
@@ -25,8 +26,8 @@
2526
"bio": "I help make working with @jekyll fun and easy.",
2627
"public_repos": 2,
2728
"public_gists": 0,
28-
"followers": 31,
29+
"followers": 68,
2930
"following": 0,
3031
"created_at": "2013-12-12T02:49:00Z",
31-
"updated_at": "2016-09-23T18:14:57Z"
32+
"updated_at": "2017-12-05T21:23:41Z"
3233
}

0 commit comments

Comments
 (0)