ae_easy-login 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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