public
Description: A mirror of the mephisto code-base
Homepage: http://mephistoblog.com/
Clone URL: git://github.com/halorgium/mephisto.git
Search Repo:
Removed the Akismet and Defensio plugins.

Replaced by the Viking plugin.
francois (author)
Mon Mar 10 20:49:20 -0700 2008
commit  86c8abf9e9f207e6dcf84df6544968eafbf2b566
tree    09c8861590595c77f6f0e2bacb107450184c5ed1
parent  1734f2205fe0ba4967c9492b8cec96cd69bbe3c3
...
1
2
3
4
5
6
...
 
 
 
 
 
 
0
@@ -1,7 +1 @@
0
-Author:: David Czarnecki
0
-Copyright:: Copyright (c) 2005 - David Czarnecki
0
-License:: BSD
0
-
0
-Extracted to a Rails plugin by François Beausoleil <francois@teksol.info>,
0
-while refactoring Mephisto to have multiple spam detection engine backends.
...
1
...
 
0
@@ -1,2 +1 @@
0
-require "akismet"
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,120 +1 @@
0
-require 'net/http'
0
-require 'uri'
0
-
0
-# Akismet
0
-#
0
-# Author:: David Czarnecki
0
-# Copyright:: Copyright (c) 2005 - David Czarnecki
0
-# License:: BSD
0
-#
0
-# rewritten to be more rails-like
0
-class Akismet
0
-
0
- cattr_accessor :valid_responses, :normal_responses
0
- attr_accessor :proxy_port, :proxy_host
0
- attr_reader :last_response
0
-
0
- @@valid_responses = Set.new(['false', ''])
0
- @@normal_responses = @@valid_responses.dup << 'true'
0
- STANDARD_HEADERS = {
0
- 'User-Agent' => 'Mephisto/' << Mephisto::Version::STRING,
0
- 'Content-Type' => 'application/x-www-form-urlencoded'
0
- }
0
-
0
- # Create a new instance of the Akismet class
0
- #
0
- # api_key
0
- # Your Akismet API key
0
- # blog
0
- # The blog associated with your api key
0
- def initialize(api_key, blog)
0
- @api_key = api_key
0
- @blog = blog
0
- @verified_key = false
0
- @proxy_port = nil
0
- @proxy_host = nil
0
- end
0
-
0
- # Returns <tt>true</tt> if the API key has been verified, <tt>false</tt> otherwise
0
- def verified?
0
- (@verified_key ||= verify_api_key) != :false
0
- end
0
-
0
- # This is basically the core of everything. This call takes a number of arguments and characteristics about the submitted content and then returns a thumbs up or thumbs down. Almost everything is optional, but performance can drop dramatically if you exclude certain elements.
0
- #
0
- # user_ip (required)
0
- # IP address of the comment submitter.
0
- # user_agent (required)
0
- # User agent information.
0
- # referrer (note spelling)
0
- # The content of the HTTP_REFERER header should be sent here.
0
- # permalink
0
- # The permanent location of the entry the comment was submitted to.
0
- # comment_type
0
- # May be blank, comment, trackback, pingback, or a made up value like "registration".
0
- # comment_author
0
- # Submitted name with the comment
0
- # comment_author_email
0
- # Submitted email address
0
- # comment_author_url
0
- # Commenter URL.
0
- # comment_content
0
- # The content that was submitted.
0
- # Other server enviroment variables
0
- # In PHP there is an array of enviroment variables called $_SERVER which contains information about the web server itself as well as a key/value for every HTTP header sent with the request. This data is highly useful to Akismet as how the submited content interacts with the server can be very telling, so please include as much information as possible.
0
- def comment_check(options = {})
0
- !@@valid_responses.include?(call_akismet('comment-check', options))
0
- end
0
-
0
- # This call is for submitting comments that weren't marked as spam but should have been. It takes identical arguments as comment check.
0
- # The call parameters are the same as for the #commentCheck method.
0
- def submit_spam(options = {})
0
- call_akismet('submit-spam', options)
0
- end
0
-
0
- # This call is intended for the marking of false positives, things that were incorrectly marked as spam. It takes identical arguments as comment check and submit spam.
0
- # The call parameters are the same as for the #commentCheck method.
0
- def submit_ham(options = {})
0
- call_akismet('submit-ham', options)
0
- end
0
-
0
- protected
0
- # Internal call to Akismet. Prepares the data for posting to the Akismet service.
0
- #
0
- # akismet_function
0
- # The Akismet function that should be called
0
- # user_ip (required)
0
- # IP address of the comment submitter.
0
- # user_agent (required)
0
- # User agent information.
0
- # referrer (note spelling)
0
- # The content of the HTTP_REFERER header should be sent here.
0
- # permalink
0
- # The permanent location of the entry the comment was submitted to.
0
- # comment_type
0
- # May be blank, comment, trackback, pingback, or a made up value like "registration".
0
- # comment_author
0
- # Submitted name with the comment
0
- # comment_author_email
0
- # Submitted email address
0
- # comment_author_url
0
- # Commenter URL.
0
- # comment_content
0
- # The content that was submitted.
0
- # Other server enviroment variables
0
- # In PHP there is an array of enviroment variables called $_SERVER which contains information about the web server itself as well as a key/value for every HTTP header sent with the request. This data is highly useful to Akismet as how the submited content interacts with the server can be very telling, so please include as much information as possible.
0
- def call_akismet(akismet_function, options = {})
0
- http = Net::HTTP.new("#{@api_key}.rest.akismet.com", 80, @proxy_host, @proxy_port)
0
- data = URI.escape(options.update(:blog => @blog).inject([]) { |data, opt| data << '%s=%s' % opt } * '&')
0
- resp, @last_response = http.post("/1.1/#{akismet_function}", data, STANDARD_HEADERS)
0
- @last_response
0
- end
0
-
0
- # Call to check and verify your API key. You may then call the #hasVerifiedKey method to see if your key has been validated.
0
- def verify_api_key
0
- http = Net::HTTP.new('rest.akismet.com', 80, @proxy_host, @proxy_port)
0
- resp, data = http.post('/1.1/verify-key', "key=#{@api_key}&blog=#{@blog}", STANDARD_HEADERS)
0
- @verified_key = (data == "valid") ? true : :false
0
- end
0
-end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,38 +1 @@
0
-== Defensio
0
-
0
-* Complete doc of Defensio API: Defensio::Client
0
-* Plugin doc: Defensio::ActsAs::ClassMethods
0
-
0
-=== Installation
0
-
0
-1. Install the plugin
0
- script/plugin install http://code.macournoyer.com/svn/plugins/defensio/
0
-2. Get an API key at http://defensio.com and dump it in config/defensio.yml
0
-3. Add new column to your spammable model
0
- script/generate defensio_migration comment
0
-
0
-You're ready to go!
0
-
0
-=== Usage
0
-
0
-In your "article" class, add:
0
-
0
- acts_as_defensio_article
0
-
0
-In your "comment" class, add:
0
-
0
- acts_as_defensio_comment :fields => { :content => :comment }
0
-
0
-The :fields option allows you to configure fields that are sent
0
-to Defensio to classify a comment.
0
-
0
-Look at Defensio::Client for a list of all those fields.
0
-
0
-In the controller, before creating a comment set the request environment variables:
0
- @comment.env = request.env
0
-
0
-Then when the comment is created the +spam+, +spaminess+ and +signature+
0
-columns will magically be set for your own pleasure.
0
-
0
-Check out other examples in http://code.macournoyer.com/svn/plugins/defensio/example
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,30 +1 @@
0
-require 'rake'
0
-require 'rake/testtask'
0
-require 'rake/rdoctask'
0
-require 'rake/contrib/rubyforgepublisher'
0
-
0
-desc 'Default: run unit tests.'
0
-task :default => :test
0
-
0
-desc 'Test the defensio plugin.'
0
-Rake::TestTask.new(:test) do |t|
0
- t.libs << 'lib'
0
- t.pattern = 'test/**/*_test.rb'
0
- t.verbose = true
0
-end
0
-
0
-desc 'Generate documentation for the defensio plugin.'
0
-Rake::RDocTask.new(:rdoc) do |rdoc|
0
- rdoc.rdoc_dir = 'rdoc'
0
- rdoc.title = 'Defensio'
0
- rdoc.options << '--line-numbers' << '--inline-source'
0
- rdoc.rdoc_files.include('README')
0
- rdoc.rdoc_files.include('lib/**/*.rb')
0
-end
0
-
0
-task :pub_doc => :rdoc do
0
- Rake::SshDirPublisher.new("macournoyer@macournoyer.com",
0
- "code.macournoyer.com/defensio",
0
- "rdoc").upload
0
-end
...
1
2
3
4
5
6
...
 
 
 
 
 
 
0
@@ -1,7 +1 @@
0
-class Article < ActiveRecord::Base
0
- # Columns: author, author_email, title, content, permalink
0
- has_many :comments
0
-
0
- acts_as_defensio_article
0
-end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,17 +1 @@
0
-class Comment < ActiveRecord::Base
0
- # Columns: author, content, title, author_email, author_url, permalink, article_id
0
- attr_accessor :current_user
0
-
0
- belongs_to :article
0
-
0
- acts_as_defensio_comment
0
-
0
- def user_logged_in
0
- current_user.logged_in?
0
- end
0
-
0
- def trusted_user
0
- current_user.admin?
0
- end
0
-end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,38 +1 @@
0
-class CommentsController < ApplicationController
0
- def index
0
- @ham = @article.comments.find_all_by_spam(false)
0
- @spam = @article.comments.find_all_by_spam(true, :order => 'spaminess desc')
0
- end
0
-
0
- def create
0
- @comment = @article.comments.build(params[:comment])
0
- @comment.env = request.env
0
- @comment.current_user = self.current_user
0
-
0
- if @comment.save
0
- if @comment.spam
0
- flash[:notice] = 'Your comment has been marked for review'
0
- else
0
- flash[:notice] = 'Comment created'
0
- end
0
- redirect_to article_url(@article)
0
- else
0
- render :action => 'new'
0
- end
0
- end
0
-
0
- def report_as_spam
0
- @comment = @article.comments.find(params[:id])
0
- @comment.report_as_spam
0
- end
0
-
0
- def report_as_ham
0
- @comment = @article.comments.find(params[:id])
0
- @comment.report_as_ham
0
- end
0
-
0
- def stats
0
- @stats = Comment.defensio_stats
0
- end
0
-end
...
1
2
3
4
5
6
7
8
9
10
11
...
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,12 +1 @@
0
-development:
0
- api_key: 1234abc
0
- owner_url: http://code.macournoyer.com/svn/plugins/defensio
0
-
0
-test:
0
- api_key: 1234abc
0
- owner_url: http://code.macournoyer.com/svn/plugins/defensio
0
-
0
-production:
0
- api_key: 6789xyz
0
- owner_url: http://code.macournoyer.com/svn/plugins/defensio
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,16 +1 @@
0
-class DefensioMigrationGenerator < Rails::Generator::NamedBase
0
- def manifest
0
- record do |m|
0
- m.migration_template 'migration.rb', 'db/migrate', :assigns => {
0
- :table_name => @name.tableize, :class_name => @name.classify.pluralize
0
- }, :migration_file_name => "add_defensio_columns_to_#{@name.tableize}"
0
- end
0
- end
0
-
0
- protected
0
- # Override with your own usage banner.
0
- def banner
0
- "Usage: #{$0} defensio_migration model"
0
- end
0
-end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,17 +1 @@
0
-class AddDefensioColumnsTo<%= class_name %> < ActiveRecord::Migration
0
- def self.up
0
- add_column :<%= table_name %>, :spam, :boolean, :default => false
0
- add_column :<%= table_name %>, :spaminess, :float
0
- add_column :<%= table_name %>, :signature, :string
0
- # Uncomment this if you wanna customize when an article is announced to Defensio server
0
- # add_column :article, :announced, :boolean, :default => false
0
- end
0
-
0
- def self.down
0
- remove_column :<%= table_name %>, :spam
0
- remove_column :<%= table_name %>, :spaminess
0
- remove_column :<%= table_name %>, :signature
0
- # add_column :article, :announced
0
- end
0
-end
...
1
...
 
0
@@ -1,2 +1 @@
0
-require 'defensio'
...
1
2
3
...
 
 
 
0
@@ -1,4 +1 @@
0
-require 'fileutils'
0
-FileUtils.cp "#{File.dirname(__FILE__)}/example/defensio.yml", "#{RAILS_ROOT}/config/defensio.yml"
0
-puts File.read("#{File.dirname(__FILE__)}/README")
...
1
2
...
 
 
0
@@ -1,3 +1 @@
0
-require 'defensio/client'
0
-require 'defensio/acts_as'
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,241 +1 @@
0
-module Defensio
0
- mattr_accessor :config_file
0
- self.config_file = RAILS_ROOT + '/config/defensio.yml'
0
-
0
- module ActsAs
0
- module ClassMethods
0
- # Add Defensio magic for managing a comment or something that
0
- # can be marked as Spam or Ham.
0
- # By default those following fields are maped to the column of the
0
- # same name, if the column exists:
0
- # <tt>
0
- # author, content, title, author_email, author_url,
0
- # user_logged_in, trusted_user, article.permalink
0
- # </tt>
0
- # See +acts_as_defensio+ for more details.
0
- def acts_as_defensio_comment(options={})
0
- acts_as_defensio :comment, options
0
- end
0
-
0
- # Add Defensio magic for managing an article or something that
0
- # can be commented (spamed) about.
0
- # By default those following fields are maped to the column of the
0
- # same name, if the column exists:
0
- # <tt>
0
- # author, author_email, title, content, permalink
0
- # </tt>
0
- # By default the article will be published after creation. You can
0
- # override this behaviour with the :announce_when option. Specified
0
- # a method returning if the article needs to be announced to the
0
- # Defensio server. If you're using the :announce_when option, you'll
0
- # also need to create an announced column as this will be set to
0
- # +true+ when the article is published.
0
- # See +acts_as_defensio+ for more details.
0
- def acts_as_defensio_article(options={})
0
- acts_as_defensio :article, options
0
- end
0
-
0
- # Add Defensio magic to an ActiveRecord class.
0
- #
0
- # Options are the same as +Defensio::Client#new+ plus the <tt>:fields</tt>
0
- # option that allows to customize the fields that will be sent to
0
- # Defensio to help the classification of a comment.
0
- # For example if the content of a comment is stored in the comment
0
- # column set the <tt>:fields</tt> option to <tt>{ :content => :comment }</tt>.
0
- # Try to map as much column as possible as this helps Defensio to
0
- # classify one comment effectively.
0
- #
0
- # You can also set the type of comment with the :comment_type option.
0
- #
0
- # Usage:
0
- # <tt>
0
- # acts_as_defensio_comment :owner_url => 'http://code.macournoyer.com/svn/plugins/defensio',
0
- # :fields => { :content => :comment }
0
- # </tt>
0
- #
0
- # You must specify the <tt>:api_key</tt> and <tt>:owner_url</tt> option.
0
- # Other options are optional.
0
- # All options can be specified in a YAML config file by default in
0
- # RAILS_ROOT/config/defensio.yml.
0
- def acts_as_defensio(type, options={})
0
- include InstanceMethods
0
-
0
- case type
0
- when :article
0
- if options.has_key? :announce_when
0
- after_save :announce_article
0
- else
0
- after_create :announce_article!
0
- end
0
- when :comment
0
- after_create :audit_comment
0
- end
0
-
0
- @defensio_type = type
0
- self.defensio_options = options
0
- @defensio = Defensio::Client.new(@defensio_options)
0
-
0
- unless defensio_options.has_key?(:validate_key) && !defensio_options[:validate_key]
0
- raise Defensio::InvalidAPIKey unless @defensio.validate_key.success?
0
- end
0
- end
0
-
0
- def defensio
0
- @defensio
0
- end
0
-
0
- def defensio_options=(options)
0
- @defensio_options = {}
0
- @defensio_options.merge! File.open(Defensio.config_file) { |file| YAML.load(file) }[ENV['RAILS_ENV']] if File.exists?(Defensio.config_file)
0
- @defensio_options.merge! options
0
- @defensio_options.symbolize_keys!
0
- end
0
-
0
- def defensio_options
0
- @defensio_options
0
- end
0
-
0
- def defensio_type
0
- @defensio_type
0
- end
0
-
0
- def defensio_fields(field)
0
- (@defensio_options[:fields] || {})[field] || field
0
- end
0
-
0
- def comment_type
0
- @defensio_options[:comment_type] || 'comment'
0
- end
0
-
0
- def defensio_stats
0
- @defensio.get_stats
0
- end
0
- end
0
-
0
- module InstanceMethods
0
- def self.included(base)
0
- base.class_eval do
0
- alias_method :report_as_spam, :report_as_false_negative
0
- alias_method :report_as_ham, :report_as_false_positive
0
- end
0
- end
0
-
0
- def audit_comment
0
- raise Defensio::Error,
0
- "You have to pass the current request environement:\n\t@comment.env = request.env" unless @env
0
-
0
- article_field = self.class.defensio_fields(:article)
0
- raise Defensio::Error,
0
- "You must specify an assiociated object which acts_as_defensio_article" unless respond_to? article_field
0
- article = send article_field
0
-
0
- fields = { :user_ip => @env['REMOTE_ADDR'],
0
- :referrer => @env['HTTP_REFERER'],
0
- :article_date => convert_to_defensio_date(article.created_at),
0
- :comment_type => self.class.comment_type }
0
-
0
- fields.merge! extract_optional_fields_value(self, :author, :content, :title, :author_email, :author_url, :prefix => 'comment_')
0
- fields.merge! extract_optional_fields_value(self, :user_logged_in, :trusted_user)
0
- fields.merge! extract_optional_fields_value(article, :permalink)
0
-
0
- response = nil
0
- log_and_ignore_error do
0
- response = self.class.defensio.audit_comment fields
0
- end
0
-
0
- if response
0
- raise Defensio::Error, response.message unless response.success?
0
- self.signature = response.signature
0
- self.spam = response.spam
0
- self.spaminess = response.spaminess
0
- save(false)
0
- end
0
- end
0
-
0
- def announce_article
0
- announce_when = self.class.defensio_options[:announce_when]
0
- announced_field = self.class.defensio_fields(:announced)
0
-
0
- raise Defensio::Error, "announced field not found" unless respond_to? announced_field
0
-
0
- return unless send(announce_when) && !send(announced_field)
0
-
0
- announce_article!
0
-
0
- self.announced = true
0
- save(false)
0
- end
0
-
0
- def announce_article!
0
- fields = {}
0
-
0
- fields.merge! extract_optional_fields_value(self, :author, :author_email, :title, :content, :prefix => 'article_')
0
- fields.merge! extract_optional_fields_value(self, :permalink)
0
-
0
- response = nil
0
- log_and_ignore_error do
0
- response = self.class.defensio.announce_article fields
0
- end
0
-
0
- if response
0
- raise Defensio::Error, response.message unless response.success?
0
- end
0
- end
0
-
0
- def env=(env)
0
- @env = env
0
- end
0
-
0
- def report_as_false_negative
0
- log_and_ignore_error do
0
- self.class.defensio.report_false_negatives :signatures => self.signature
0
- end
0
- self.spam = true
0
- self.spaminess = 1.0
0
- save(false)
0
- end
0
-
0
- def report_as_false_positive
0
- log_and_ignore_error do
0
- self.class.defensio.report_false_positives :signatures => self.signature
0
- end
0
- self.spam = false
0
- self.spaminess = 0.0
0
- save(false)
0
- end
0
-
0
- private
0
- def convert_to_defensio_date(date)
0
- [date.strftime('%Y'), date.month, date.day] * '/'
0
- end
0
-
0
- def extract_optional_fields_value(object, *fields)
0
- options = fields.last.is_a?(Hash) ? fields.pop : {}
0
- prefix = options.delete(:prefix)
0
-
0
- fields.inject({}) do |hash, field|
0
- field_name = object.class.defensio_fields(field)
0
- hash[:"#{prefix}#{field}"] = object.send(field_name) if object.respond_to? field_name
0
- hash
0
- end
0
- end
0
-
0
- def log_and_ignore_error
0
- tries = 0
0
- begin
0
- tries += 1
0
- yield
0
- rescue Exception => e
0
- if tries < 3
0
- retry
0
- else
0
- RAILS_DEFAULT_LOGGER.error "[DEFENSIO] Could not contact server : #{e}"
0
- end
0
- end
0
- end
0
- end
0
- end
0
-end
0
-
0
-ActiveRecord::Base.extend Defensio::ActsAs::ClassMethods
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,229 +1 @@
0
-require 'net/http'
0
-require 'yaml'
0
-
0
-module Defensio
0
- class Error < RuntimeError; end
0
- class InvalidAPIKey < Error; end
0
-
0
- class Response
0
- attr_reader :raw
0
-
0
- def initialize(response_body)
0
- @raw = response_body
0
- @parameters = YAML.load(response_body)['defensio-result'] || {}
0
- end
0
-
0
- def [](parameter)
0
- @parameters[parameter.to_s.tr('_', '-')]
0
- end
0
-
0
- # Indicates whether the action could be processed
0
- def success?
0
- self[:status] == 'success'
0
- end
0
-
0
- def self.response_attr_reader(*attrs)
0
- attrs.each do |attr|
0
- define_method attr do
0
- self[attr]
0