ae_easy-login 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.
@@ -0,0 +1,110 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.9.20
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ pathId = "";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+
41
+
42
+ <span class="title">Top Level Namespace</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><h1>Top Level Namespace
63
+
64
+
65
+
66
+ </h1>
67
+ <div class="box_info">
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+ </div>
80
+
81
+ <h2>Defined Under Namespace</h2>
82
+ <p class="children">
83
+
84
+
85
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="AeEasy.html" title="AeEasy (module)">AeEasy</a></span>
86
+
87
+
88
+
89
+
90
+ </p>
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ </div>
101
+
102
+ <div id="footer">
103
+ Generated on Fri Sep 27 07:10:16 2019 by
104
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
+ 0.9.20 (ruby-2.5.3).
106
+ </div>
107
+
108
+ </div>
109
+ </body>
110
+ </html>
@@ -0,0 +1,10 @@
1
+ require 'digest'
2
+ require 'ae_easy/core'
3
+ require 'ae_easy/login/version'
4
+ require 'ae_easy/login/flow'
5
+ require 'ae_easy/login/plugin'
6
+
7
+ module AeEasy
8
+ module Login
9
+ end
10
+ end
@@ -0,0 +1,295 @@
1
+ module AeEasy
2
+ module Login
3
+ # Login flow executor designed to recover from an expired or invalid
4
+ # session.
5
+ class Flow
6
+ include AeEasy::Core::Plugin::Executor
7
+
8
+ # App configuration to store login flow configuration.
9
+ # @return [AeEasy::Core::Config]
10
+ attr_accessor :app_config
11
+
12
+ # Output collection used to store held pages to be fixed and fetched.
13
+ # @return [String]
14
+ attr_accessor :collection
15
+
16
+ # Batch size used on query outputs.
17
+ # @return [Integer]
18
+ attr_accessor :per_page
19
+
20
+ # Key to be used to store login flow configuration data at #app_config.
21
+ # @return [String]
22
+ attr_accessor :config_key
23
+
24
+ # Page's "vars" key to store the login cookie used to fetch.
25
+ # @return [String]
26
+ attr_accessor :vars_key
27
+
28
+ # Block with custom user defined fixing logic to be executed on help page
29
+ # fix.
30
+ # @return [Proc,Lambda,nil]
31
+ attr_accessor :custom_fix
32
+
33
+ # Force held pages to keep response_keys on save.
34
+ # @return [Boolean] `true` when enabled, else `false`.
35
+ attr_accessor :keep_response_keys
36
+
37
+ # Hook to initialize login flow configuration.
38
+ #
39
+ # @param [Hash] opts ({}) Configuration options.
40
+ # @option opts [AeEasy::Core::Config] :app_config (nil) App configuration to
41
+ # use.
42
+ # @option opts [Integer] :per_page (100) Batch size used on query outputs.
43
+ # @option opts [String] :collection ('login_flow_held_pages') Output
44
+ # collection used to store held pages to be fixed and fetched.
45
+ # @option opts [String] :config_key ('login_flow') Key to be used to
46
+ # store login flow configuration data at #app_config.
47
+ # @option opts [String] :vars_key ('login_flow_cookie') Page's "vars" key
48
+ # to store the login cookie used to fetch.
49
+ # @option opts [String] :reponse_keys (nil) Response keys to remove from
50
+ # a held page before enqueue it again.
51
+ # @option opts [Block] :custom_fix (nil) Custom block to be executed on
52
+ # fixing a held page.
53
+ #
54
+ # @raise [ArgumentError] When `opts[:app_config]` is not provided or
55
+ # `nil`.
56
+ #
57
+ # @note `opts[:response_keys]` will default to a predefined list whenever
58
+ # `nil`.
59
+ def initialize_hook_login_flow opts = {}
60
+ self.per_page = opts[:per_page] || 100
61
+ self.collection = opts[:collection] || 'login_flow_held_pages'
62
+ self.config_key = opts[:config_key] || 'login_flow'
63
+ self.vars_key = opts[:vars_key] || 'login_flow_cookie'
64
+ self.response_keys = opts[:reponse_keys] || nil
65
+ self.app_config = opts[:app_config] || nil
66
+ self.custom_fix = opts[:custom_fix] || nil
67
+ self.keep_response_keys = opts[:keep_response_keys] || false
68
+
69
+ if self.app_config.nil?
70
+ raise ArgumentError.new('":app_config" option is required!')
71
+ end
72
+ end
73
+
74
+ # Response keys to remove from a held page before enqueue it again.
75
+ #
76
+ # @return [Array<String>]
77
+ def response_keys
78
+ @response_keys ||= [
79
+ 'content_size',
80
+ 'content_type',
81
+ 'created_at',
82
+ 'effective_url',
83
+ 'failed_at',
84
+ 'failed_cid',
85
+ 'failed_content_size',
86
+ 'failed_content_type',
87
+ 'failed_effective_url',
88
+ 'failed_response_checksum',
89
+ 'failed_response_cookie',
90
+ 'failed_response_headers',
91
+ 'failed_response_proto',
92
+ 'failed_response_status_code',
93
+ 'failed_response_status',
94
+ 'fetched_at',
95
+ 'fetched_from',
96
+ 'fetching_at',
97
+ 'fetching_try_count',
98
+ 'forced_fetch',
99
+ 'fresh',
100
+ 'gid',
101
+ 'hostname',
102
+ 'job_id',
103
+ 'job_status',
104
+ 'parsed_at',
105
+ 'parsing_at',
106
+ 'parsing_fail_count',
107
+ 'parsing_failed_at',
108
+ 'parsing_status',
109
+ 'parsing_try_count',
110
+ 'parsing_updated_at',
111
+ 'response_checksum',
112
+ 'response_cookie',
113
+ 'response_headers',
114
+ 'response_proto',
115
+ 'response_status_code',
116
+ 'response_status',
117
+ 'status',
118
+ 'to_fetch',
119
+ 'total_failures',
120
+ 'total_requests',
121
+ 'total_successes'
122
+ ]
123
+ end
124
+
125
+ # Set response key list to remove from a page before enqueue it again.
126
+ #
127
+ # @param [Array<String>] value Response key list.
128
+ def response_keys= value
129
+ @response_keys = value
130
+ end
131
+
132
+ # Invalidates login flow config, so it is reloaded on next config usage.
133
+ def reload_config
134
+ @config = nil
135
+ end
136
+
137
+ # Gets the existing login flow config or load it from app config when
138
+ # invalid.
139
+ #
140
+ # @return [Hash]
141
+ def config
142
+ @config ||= nil
143
+ return @config unless @config.nil?
144
+ @config = app_config.find_config config_key
145
+ @config.freeze
146
+ @config
147
+ end
148
+
149
+ # Indicates whenever login flow has been seeded. Useful when using files
150
+ # to held pages.
151
+ #
152
+ # @return [Boolean] `true` if seeded, else `false`.
153
+ def seeded?
154
+ config['seeded'] || false
155
+ end
156
+
157
+ # Updates app configuration.
158
+ #
159
+ # @param [Hash] data ({}) Data to be saved on app configuration.
160
+ def update_config data = {}
161
+ reload_config
162
+ new_config = {}.merge(config)
163
+ new_config.merge!(data)
164
+ save new_config
165
+ reload_config
166
+ end
167
+
168
+ # Set seeded flag as `true`.
169
+ def seeded!
170
+ update_config 'seeded' => true
171
+ end
172
+
173
+ # Indicates whenever latest session has been set as expired.
174
+ #
175
+ # @return [Boolean] `true` when expired, else `false`.
176
+ def expired?
177
+ config['expired'] || false
178
+ end
179
+
180
+ # Set expire flag as `true`.
181
+ def expire!
182
+ update_config 'expired' => true
183
+ end
184
+
185
+ # Check whenever a key name is categorized as a response key.
186
+ #
187
+ # @param [String] key Key name to check.
188
+ #
189
+ # @return [Boolean] `true` when key name is a response key, else `false`.
190
+ def response_key? key
191
+ self.response_keys.include? key.to_s.strip
192
+ end
193
+
194
+ # Remove all response keys from a held page hash.
195
+ #
196
+ # @param [Hash] held_page Held page to clean.
197
+ def clean_page_response! held_page
198
+ keys = held_page.keys + []
199
+ keys.each do |key|
200
+ held_page.delete key if response_key? key
201
+ end
202
+ end
203
+
204
+ # Updates an old cookie with current cookie saved on app configuration.
205
+ #
206
+ # @param [String,Array,Hash] old_cookie Old cookie to update.
207
+ def merge_cookie old_cookie
208
+ return config['cookie'] if old_cookie.nil?
209
+ AeEasy::Core::Helper::Cookie.update old_cookie, config['cookie']
210
+ end
211
+
212
+ # Add login flow reserved vars into a page.
213
+ #
214
+ # @param [Hash] new_page Page to add login flow reserved vars.
215
+ def add_vars! new_page
216
+ key = new_page.has_key?(:vars) ? :vars : 'vars'
217
+ new_page[key] = {} if new_page[key].nil?
218
+ new_page[key][vars_key] = config['cookie']
219
+ end
220
+
221
+ # Execute #custom_fix block into a held page.
222
+ #
223
+ # @param [Hash] held_page Held page to fix.
224
+ def custom_fix! held_page
225
+ self.custom_fix.call held_page unless self.custom_fix.nil?
226
+ end
227
+
228
+ # Fixes a held page session.
229
+ #
230
+ # @param [Hash] held_page Held page to fix.
231
+ def fix_page! held_page
232
+ clean_page_response! held_page
233
+ held_page['cookie'] = merge_cookie held_page['cookie']
234
+ held_page['headers'] = {} unless held_page.has_key? 'headers'
235
+ if held_page['headers'].has_key? 'Cookie'
236
+ held_page['headers']['Cookie'] = merge_cookie held_page['headers']['Cookie']
237
+ end
238
+ add_vars! held_page
239
+ custom_fix! held_page
240
+ end
241
+
242
+ # Fixes current page session by enqueue it using latest working session or
243
+ # held it for fix and enqueue login page by executing block.
244
+ def fix_session &enqueue_login
245
+ # Expire cookie when same as current page
246
+ old_cookie_hash = AeEasy::Core::Helper::Cookie.parse_from_request page['vars'][vars_key]
247
+ newest_cookie_hash = AeEasy::Core::Helper::Cookie.parse_from_request config['cookie']
248
+ same_cookie = AeEasy::Core::Helper::Cookie.include? old_cookie_hash, newest_cookie_hash
249
+ expire! if same_cookie && !config['expired']
250
+
251
+ # Hold self page
252
+ if config['expired'].nil? || config['expired']
253
+ held_page = page.merge({})
254
+ clean_page_response!(held_page) unless keep_response_keys
255
+ save(
256
+ '_collection' => collection,
257
+ '_id' => page['gid'],
258
+ 'page' => held_page,
259
+ 'fetched' => '0'
260
+ )
261
+ enqueue_login.call unless enqueue_login.nil?
262
+ return
263
+ end
264
+
265
+ # Refetch self with new session
266
+ new_page = {}.merge page
267
+ fix_page! new_page
268
+ enqueue new_page
269
+ end
270
+
271
+ # Restore all held pages stored as outputs.
272
+ def restore_held_pages
273
+ current_page = 1
274
+ held_pages = find_outputs collection, {'fetched' => '0'}, current_page, per_page
275
+ while !held_pages&.first.nil? do
276
+ held_pages.each do |output|
277
+ # Parse and seed pages
278
+ held_page = output['page'].is_a?(String) ? JSON.parse(output['page']) : output['page']
279
+ fix_page! held_page
280
+ pages << held_page
281
+
282
+ output['fetched'] = '1'
283
+ outputs << output
284
+ end
285
+
286
+ # Fetch next page
287
+ current_page += 1
288
+ enqueue pages
289
+ save outputs
290
+ held_pages = find_outputs collection, {'fetched' => '0'}, current_page, per_page
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,8 @@
1
+ require 'ae_easy/login/plugin/enabled_behavior'
2
+
3
+ module AeEasy
4
+ module Login
5
+ module Plugin
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,47 @@
1
+ module AeEasy
2
+ module Login
3
+ module Plugin
4
+ # Abstract module that provides a template with minimal common logic to
5
+ # implement a login flow enabled plugin.
6
+ # @abstract
7
+ module EnabledBehavior
8
+ include AeEasy::Core::Plugin::InitializeHook
9
+
10
+ # Login flow tool.
11
+ attr_reader :login_flow
12
+
13
+ # Hook to initialize login_flow configuration.
14
+ #
15
+ # @param [Hash] opts ({}) Configuration options (see
16
+ # AeEasy::Login::Flow#initialize_hook_login_flow).
17
+ def initialize_hook_login_plugin_enabled_behavior opts = {}
18
+ @login_flow = AeEasy::Login::Flow.new opts
19
+ end
20
+
21
+ # Generates a salt value based on the current page's login flow vars.
22
+ #
23
+ # @return [String]
24
+ def salt
25
+ old_cookie = page['vars'][login_flow.vars_key]
26
+ old_cookie = '' if old_cookie.nil?
27
+ Digest::SHA1.hexdigest old_cookie
28
+ end
29
+
30
+ # Validates that the current page's session hasn't expired.
31
+ #
32
+ # @return [Boolean] `true` when session is valid, else `false`.
33
+ def valid_session?
34
+ raise NotImplementedError.new('Must implement "session_valid?" function.')
35
+ end
36
+
37
+ # Fixes current page's session.
38
+ #
39
+ # @return [Boolean] `true` when session is valid and no need to fix,
40
+ # else `false`.
41
+ def fix_session
42
+ raise NotImplementedError.new('Must implement "fix_session" function.')
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end