logical_model 0.4.10 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +17 -2
- data/VERSION +1 -1
- data/client.rb +10 -4
- data/lib/logical_model.rb +23 -481
- data/lib/logical_model/api_key.rb +41 -0
- data/lib/logical_model/attributes.rb +57 -0
- data/lib/logical_model/has_many_keys.rb +53 -47
- data/lib/logical_model/rest_actions.rb +410 -0
- data/lib/logical_model/safe_log.rb +61 -0
- data/lib/logical_model/url_helper.rb +78 -0
- data/logical_model.gemspec +7 -4
- data/spec/client_spec.rb +129 -39
- metadata +8 -5
- data/lib/safe_log.rb +0 -11
- data/lib/ssl_support.rb +0 -39
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class LogicalModel
|
4
|
+
module SafeLog
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.send(:include, InstanceMethods)
|
8
|
+
base.send(:extend, ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
def log_ok(response)
|
13
|
+
self.class.log_ok(response)
|
14
|
+
end
|
15
|
+
|
16
|
+
def log_failed(response)
|
17
|
+
self.class.log_failed(response)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
attr_accessor :log_path
|
24
|
+
|
25
|
+
def log_path
|
26
|
+
@log_path ||= "log/logical_model.log"
|
27
|
+
end
|
28
|
+
|
29
|
+
def log_ok(response)
|
30
|
+
self.logger.info("LogicalModel Log: #{response.code} #{mask_api_key(response.effective_url)} in #{response.time}s")
|
31
|
+
self.logger.debug("LogicalModel Log RESPONSE: #{response.body}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def log_failed(response)
|
35
|
+
begin
|
36
|
+
error_message = ActiveSupport::JSON.decode(response.body)["message"]
|
37
|
+
rescue => e
|
38
|
+
error_message = "error"
|
39
|
+
end
|
40
|
+
msg = "LogicalModel Log: #{response.code} #{mask_api_key(response.effective_url)} in #{response.time}s FAILED: #{error_message}"
|
41
|
+
self.logger.warn(msg)
|
42
|
+
self.logger.debug("LogicalModel Log RESPONSE: #{response.body}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def logger
|
46
|
+
Logger.new(self.log_path || "log/logical_model.log")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Filters api_key
|
50
|
+
# @return [String]
|
51
|
+
def mask_api_key(str)
|
52
|
+
if use_api_key && str
|
53
|
+
str = str.gsub(api_key,'[SECRET]')
|
54
|
+
end
|
55
|
+
str
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class LogicalModel
|
2
|
+
module UrlHelper
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:extend, ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
# adds following setters
|
9
|
+
# - force_ssl
|
10
|
+
# - set_resource_host
|
11
|
+
# - set_resource_path
|
12
|
+
#
|
13
|
+
# add reader
|
14
|
+
# - resource_uri
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
attr_accessor :host,
|
18
|
+
:resource_path,
|
19
|
+
:use_ssl
|
20
|
+
|
21
|
+
# Will return path to resource
|
22
|
+
# @param id [String] (nil)
|
23
|
+
def resource_uri(id=nil)
|
24
|
+
sufix = (id.nil?)? "" : "/#{id}"
|
25
|
+
"#{url_protocol_prefix}#{host}#{resource_path}#{sufix}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# If called in class, will make al request through SSL.
|
29
|
+
# @example
|
30
|
+
# class Client < LogicalModel
|
31
|
+
# force_ssl
|
32
|
+
# ...
|
33
|
+
# end
|
34
|
+
def force_ssl
|
35
|
+
@use_ssl = true
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param new_host [String] resource host. Should NOT include protocol (http)
|
39
|
+
# @param new_path [String] resource path in host
|
40
|
+
def set_resource_url(new_host,new_path)
|
41
|
+
@host = new_host
|
42
|
+
@resource_path = new_path
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_resource_host(new_host)
|
46
|
+
@host = new_host
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_resource_path(new_path)
|
50
|
+
@resource_path = new_path
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Default use_ssl to ssl_recommend?
|
55
|
+
# @return [Boolean]
|
56
|
+
def use_ssl?
|
57
|
+
@use_ssl ||= ssl_recommended?
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [String]
|
61
|
+
def url_protocol_prefix
|
62
|
+
(use_ssl?)? "https://" : "http://"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns true if ssl is recommended according to environment.
|
66
|
+
#
|
67
|
+
# - production, staging -> true
|
68
|
+
# - other -> false
|
69
|
+
#
|
70
|
+
# @return [Boolean]
|
71
|
+
def ssl_recommended?
|
72
|
+
ssl_recommended_environments = %W(production staging)
|
73
|
+
ssl_recommended_environments.include?(defined?(Rails)? Rails.env : ENV['RACK_ENV'] )
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
data/logical_model.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "logical_model"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Dwayne Macgowan"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-05-01"
|
13
13
|
s.description = "LogicalModel allows to use a resource as a model. It is based on web presentation http://www.slideshare.net/ihower/serviceoriented-design-and-implement-with-rails3"
|
14
14
|
s.email = "dwaynemac@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -32,9 +32,12 @@ Gem::Specification.new do |s|
|
|
32
32
|
"db/development.sqlite3",
|
33
33
|
"db/migrate/001_create_users.rb",
|
34
34
|
"lib/logical_model.rb",
|
35
|
+
"lib/logical_model/api_key.rb",
|
36
|
+
"lib/logical_model/attributes.rb",
|
35
37
|
"lib/logical_model/has_many_keys.rb",
|
36
|
-
"lib/
|
37
|
-
"lib/
|
38
|
+
"lib/logical_model/rest_actions.rb",
|
39
|
+
"lib/logical_model/safe_log.rb",
|
40
|
+
"lib/logical_model/url_helper.rb",
|
38
41
|
"lib/typhoeus_fix/array_decoder.rb",
|
39
42
|
"logical_model.gemspec",
|
40
43
|
"models/user.rb",
|
data/spec/client_spec.rb
CHANGED
@@ -5,6 +5,135 @@ include TyphoeusMocks
|
|
5
5
|
|
6
6
|
describe "LogicalModel User client" do
|
7
7
|
|
8
|
+
subject{User}
|
9
|
+
|
10
|
+
describe "Attributes" do
|
11
|
+
subject{User.new}
|
12
|
+
%W(id name email password bio).each do |attribute|
|
13
|
+
it { should respond_to attribute }
|
14
|
+
it { should respond_to "#{attribute}="}
|
15
|
+
end
|
16
|
+
describe "attribute definer" do
|
17
|
+
it "should add attribute" do
|
18
|
+
User.new.attributes.should_not include :this_is_a_new_attribute
|
19
|
+
User.new.attributes.should_not include :another_new_attribute
|
20
|
+
class User < LogicalModel
|
21
|
+
attribute :this_is_a_new_attribute
|
22
|
+
attribute :another_new_attribute
|
23
|
+
end
|
24
|
+
User.new.attributes.should include :this_is_a_new_attribute
|
25
|
+
User.new.attributes.should include :another_new_attribute
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "RESTActions" do
|
31
|
+
%W(find async_find paginate async_paginate delete delete_multiple).each do |class_action|
|
32
|
+
it { should respond_to class_action }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "has_many_keys" do
|
37
|
+
it { should respond_to 'has_many_keys=' }
|
38
|
+
it { should respond_to 'has_many_keys'}
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "url_helper" do
|
42
|
+
it { should respond_to 'use_ssl=' }
|
43
|
+
it { should respond_to 'use_ssl?' }
|
44
|
+
it { should respond_to 'url_protocol_prefix' }
|
45
|
+
it { should respond_to 'ssl_recommended?' }
|
46
|
+
describe "force_ssl" do
|
47
|
+
it { should respond_to 'force_ssl' }
|
48
|
+
it "sets use_ssl to true" do
|
49
|
+
User.use_ssl?.should be_false
|
50
|
+
class User; force_ssl; end;
|
51
|
+
User.use_ssl?.should be_true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
describe "set_resource_host" do
|
55
|
+
it { should respond_to 'set_resource_host' }
|
56
|
+
it "sets resource_path" do
|
57
|
+
User.resource_path.should == "/api/v1/users"
|
58
|
+
class User; set_resource_path("new_path"); end;
|
59
|
+
User.resource_path.should == "new_path"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
describe "set_resource_path" do
|
63
|
+
it { should respond_to 'set_resource_path'}
|
64
|
+
it "sets resource_host" do
|
65
|
+
User.host.should == "localhost:3000"
|
66
|
+
class User; set_resource_host("new_host"); end;
|
67
|
+
User.host.should == "new_host"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "safe_log" do
|
73
|
+
it { should respond_to 'log_ok' }
|
74
|
+
it { should respond_to 'log_failed' }
|
75
|
+
it { should respond_to 'logger' }
|
76
|
+
it { should respond_to 'mask_api_key' }
|
77
|
+
describe ".log_path" do
|
78
|
+
it { should respond_to 'log_path' }
|
79
|
+
its(:log_path){ should == "logs/development.log"}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "api_key" do
|
84
|
+
describe "set_api_key" do
|
85
|
+
it { should respond_to 'set_api_key'}
|
86
|
+
it "sets api_key" do
|
87
|
+
class User < LogicalModel
|
88
|
+
set_api_key(:key_name, 'secret_api_key')
|
89
|
+
end
|
90
|
+
User.use_api_key.should be_true
|
91
|
+
User.api_key.should == 'secret_api_key'
|
92
|
+
User.api_key_name.should == :key_name
|
93
|
+
end
|
94
|
+
end
|
95
|
+
describe "use_api_key" do
|
96
|
+
it { should respond_to 'use_api_key' }
|
97
|
+
context "when true" do
|
98
|
+
before(:each) do
|
99
|
+
class User < LogicalModel; self.use_api_key=true; self.api_key_name='keyname'; self.api_key="secret_api_key"; end
|
100
|
+
end
|
101
|
+
it "should send api key in requests" do
|
102
|
+
Typhoeus::Request.should_receive(:new).with(User.resource_uri(1),{:params=>{'keyname'=>'secret_api_key'}})
|
103
|
+
begin
|
104
|
+
User.find(1)
|
105
|
+
rescue
|
106
|
+
end
|
107
|
+
end
|
108
|
+
it "should mask api key in logs" do
|
109
|
+
response = mock(
|
110
|
+
code: 200,
|
111
|
+
body: {}.to_json,
|
112
|
+
effective_url: "server?keyname=secret_api_key",
|
113
|
+
time: 1234
|
114
|
+
)
|
115
|
+
Logger.any_instance.should_receive(:info).with(/\[SECRET\]/)
|
116
|
+
User.log_ok(response)
|
117
|
+
Logger.any_instance.should_receive(:warn).with(/\[SECRET\]/)
|
118
|
+
User.log_failed(response)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
context "when false" do
|
122
|
+
before(:each) do
|
123
|
+
class User < LogicalModel; self.use_api_key=false; self.api_key_name='keyname'; self.api_key="secret_api_key"; end
|
124
|
+
end
|
125
|
+
it "should not send api key in requests" do
|
126
|
+
Typhoeus::Request.should_not_receive(:new).with(User.resource_uri(1),{:params=>{'keyname'=>'secret_api_key'}})
|
127
|
+
begin
|
128
|
+
User.find(1)
|
129
|
+
rescue
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
it { should respond_to 'merge_key'}
|
135
|
+
end
|
136
|
+
|
8
137
|
describe "#create" do
|
9
138
|
context "with valid attributes" do
|
10
139
|
context "if response is code 201" do
|
@@ -131,45 +260,6 @@ describe "LogicalModel User client" do
|
|
131
260
|
end
|
132
261
|
end
|
133
262
|
|
134
|
-
describe "use_api_key" do
|
135
|
-
context "when true" do
|
136
|
-
before(:each) do
|
137
|
-
class User < LogicalModel; self.use_api_key=true; self.api_key_name='keyname'; self.api_key="secret_api_key"; end
|
138
|
-
end
|
139
|
-
it "should send api key in requests" do
|
140
|
-
Typhoeus::Request.should_receive(:new).with(User.resource_uri(1),{:params=>{'keyname'=>'secret_api_key'}})
|
141
|
-
begin
|
142
|
-
User.find(1)
|
143
|
-
rescue
|
144
|
-
end
|
145
|
-
end
|
146
|
-
it "should mask api key in logs" do
|
147
|
-
response = mock(
|
148
|
-
code: 200,
|
149
|
-
body: {}.to_json,
|
150
|
-
effective_url: "server?keyname=secret_api_key",
|
151
|
-
time: 1234
|
152
|
-
)
|
153
|
-
Logger.any_instance.should_receive(:info).with(/\[SECRET\]/)
|
154
|
-
User.log_ok(response)
|
155
|
-
Logger.any_instance.should_receive(:warn).with(/\[SECRET\]/)
|
156
|
-
User.log_failed(response)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
context "when false" do
|
160
|
-
before(:each) do
|
161
|
-
class User < LogicalModel; self.use_api_key=false; self.api_key_name='keyname'; self.api_key="secret_api_key"; end
|
162
|
-
end
|
163
|
-
it "should not send api key in requests" do
|
164
|
-
Typhoeus::Request.should_not_receive(:new).with(User.resource_uri(1),{:params=>{'keyname'=>'secret_api_key'}})
|
165
|
-
begin
|
166
|
-
User.find(1)
|
167
|
-
rescue
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
263
|
describe "#https" do
|
174
264
|
context "when use_ssl is tue" do
|
175
265
|
before(:each) do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logical_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -323,9 +323,12 @@ files:
|
|
323
323
|
- db/development.sqlite3
|
324
324
|
- db/migrate/001_create_users.rb
|
325
325
|
- lib/logical_model.rb
|
326
|
+
- lib/logical_model/api_key.rb
|
327
|
+
- lib/logical_model/attributes.rb
|
326
328
|
- lib/logical_model/has_many_keys.rb
|
327
|
-
- lib/
|
328
|
-
- lib/
|
329
|
+
- lib/logical_model/rest_actions.rb
|
330
|
+
- lib/logical_model/safe_log.rb
|
331
|
+
- lib/logical_model/url_helper.rb
|
329
332
|
- lib/typhoeus_fix/array_decoder.rb
|
330
333
|
- logical_model.gemspec
|
331
334
|
- models/user.rb
|
@@ -348,7 +351,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
348
351
|
version: '0'
|
349
352
|
segments:
|
350
353
|
- 0
|
351
|
-
hash:
|
354
|
+
hash: 863618749
|
352
355
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
353
356
|
none: false
|
354
357
|
requirements:
|
data/lib/safe_log.rb
DELETED
data/lib/ssl_support.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module SslSupport
|
2
|
-
|
3
|
-
def self.included(base)
|
4
|
-
base.class.send(:attr_accessor, :use_ssl)
|
5
|
-
base.send(:include, InstanceMethods)
|
6
|
-
base.send(:extend, ClassMethods)
|
7
|
-
end
|
8
|
-
|
9
|
-
module InstanceMethods
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
module ClassMethods
|
14
|
-
##
|
15
|
-
# Default use_ssl to ssl_recommend?
|
16
|
-
# @return [Boolean]
|
17
|
-
def use_ssl?
|
18
|
-
@use_ssl ||= ssl_recommended?
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [String]
|
22
|
-
def url_protocol_prefix
|
23
|
-
(use_ssl?)? "https://" : "http://"
|
24
|
-
end
|
25
|
-
|
26
|
-
# Returns true if ssl is recommended according to environment.
|
27
|
-
#
|
28
|
-
# - production, staging -> true
|
29
|
-
# - other -> false
|
30
|
-
#
|
31
|
-
# @return [Boolean]
|
32
|
-
def ssl_recommended?
|
33
|
-
ssl_recommended_environments = %W(production staging)
|
34
|
-
ssl_recommended_environments.include?(defined?(Rails)? Rails.env : ENV['RACK_ENV'] )
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
end
|