identikey 0.4.3 → 0.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7250ec019f47150ff6dd6c34436cda2615daad7cc2ab27a9ff24b92a8d412985
4
- data.tar.gz: dc079e945e696d1480f80e90ab1ecf339a8b441c243cca201332c199c22ed570
3
+ metadata.gz: 17806b4e8996eac32014f37f34d9e698b4668e5fd196e1102e2a30c0eb349757
4
+ data.tar.gz: 26e36da28a662d259e538ef2936d8b03a883c0e38e450a5350e548a336336ed7
5
5
  SHA512:
6
- metadata.gz: 348dc3966a4bf3e9d31afefc738a0f698572035f2fed833de9f5260d115bd2b528eb546a69599cf67982ed23561691554055b1d998255f69454c681b26f48956
7
- data.tar.gz: 8afac75cce4902ce9e3939505c7f1a6707555b7ba1e9906cec0645d136a820fb8f6108c906c76982753499adec8fcd1a9c7a771e1e3861be6c15b7f25f7ec8fa
6
+ metadata.gz: cf8893d1ae7931194b59c54d0f3a6addd824869c116859ae534f36bb5a6619cebdb1f0e87bb6d8c74c4a67988470053abb2985b6d58e2011d59a0b16eeaf1eeb
7
+ data.tar.gz: 0c4e3661f8b518f55382490c9af060580d1982f2762904afeef435e9c544e0309e6ced8230bbea0e4b3e23451a544828bd10dc486858d8fc3ca03b792e191437
@@ -6,6 +6,36 @@ module Identikey
6
6
  new(session).find(serial_no)
7
7
  end
8
8
 
9
+ def self.search(session:, query:, options: {})
10
+ query_keys = {
11
+ 'applications' => 'DIGIPASSFLD_ACTIVE_APPL_NAMES',
12
+ 'app_types' => 'DIGIPASSFLD_ACTIVE_APPL_TYPES',
13
+ 'status' => 'DIGIPASSFLD_ASSIGN_STATUS',
14
+ 'user_org_unit' => 'DIGIPASSFLD_ASSIGNED_USER_ORG_UNIT',
15
+ 'username' => 'DIGIPASSFLD_ASSIGNED_USERID',
16
+ 'device_id' => 'DIGIPASSFLD_DEVICE_ID',
17
+ 'direct' => 'DIGIPASSFLD_DIRECT_ASSIGN_ONLY',
18
+ 'domain' => 'DIGIPASSFLD_DOMAIN',
19
+ 'type' => 'DIGIPASSFLD_DPTYPE',
20
+ 'expired' => 'DIGIPASSFLD_EXPIRED',
21
+ 'grace_expired' => 'DIGIPASSFLD_GRACE_PERIOD_EXPIRED',
22
+ 'license_serial' => 'DIGIPASSFLD_LICENSE_SERNO',
23
+ 'org_unit' => 'DIGIPASSFLD_ORGANIZATIONAL_UNIT',
24
+ 'serial' => 'DIGIPASSFLD_SERNO'
25
+ }
26
+
27
+ stat, digipasses, error = session.execute(:digipass_query,
28
+ attributes: Base.search_attributes_from(query, attribute_map: query_keys),
29
+ query_options: Base.search_options_from(options))
30
+
31
+ case stat
32
+ when 'STAT_SUCCESS' then (digipasses||[]).map {|user| new(session, user) }
33
+ when 'STAT_NOT_FOUND' then []
34
+ else
35
+ raise Identikey::Error, "Search digipass failed: #{stat} - #{error}"
36
+ end
37
+ end
38
+
9
39
  def initialize(session, digipass = nil)
10
40
  @session = session
11
41
 
@@ -85,12 +85,28 @@ module Identikey
85
85
  Digipass.find session: self, serial_no: serial_no
86
86
  end
87
87
 
88
+ def search_digipasses(query)
89
+ require_logged_on!
90
+
91
+ options = query.delete(:options) || {}
92
+
93
+ Digipass.search session: self, query: query, options: options
94
+ end
95
+
88
96
  def find_user(username, domain = nil)
89
97
  require_logged_on!
90
98
 
91
99
  User.find session: self, username: username, domain: domain || self.domain
92
100
  end
93
101
 
102
+ def search_users(query)
103
+ require_logged_on!
104
+
105
+ options = query.delete(:options) || {}
106
+
107
+ User.search session: self, query: query, options: options
108
+ end
109
+
94
110
  def inspect
95
111
  "#<#{self.class.name} sid=#@session_id username=#@username domain=#@domain product=#@product>"
96
112
  end
@@ -6,6 +6,37 @@ module Identikey
6
6
  new(session).find(username, domain)
7
7
  end
8
8
 
9
+ def self.search(session:, query:, options: {})
10
+ if query.key?(:has_digipass) && [true, false].include?(query[:has_digipass])
11
+ query[:has_digipass] = query[:has_digipass] ? 'Assigned' : 'Unassigned'
12
+ end
13
+
14
+ query_keys = {
15
+ 'has_digipass' => 'USERFLD_HAS_DP',
16
+ 'description' => 'USERFLD_DESCRIPTION',
17
+ 'disabled' => 'USERFLD_DISABLED',
18
+ 'domain' => 'USERFLD_DOMAIN',
19
+ 'email' => 'USERFLD_EMAIL',
20
+ 'expired' => 'USERFLD_EXPIRED',
21
+ 'locked' => 'USERFLD_LOCKED',
22
+ 'mobile' => 'USERFLD_MOBILE',
23
+ 'org_unit' => 'USERFLD_ORGANIZATIONAL_UNIT',
24
+ 'phone' => 'USERFLD_PHONE',
25
+ 'username' => 'USERFLD_USERID',
26
+ }
27
+
28
+ stat, users, error = session.execute(:user_query,
29
+ attributes: Base.search_attributes_from(query, attribute_map: query_keys),
30
+ query_options: Base.search_options_from(options))
31
+
32
+ case stat
33
+ when 'STAT_SUCCESS' then (users||[]).map {|user| new(session, user) }
34
+ when 'STAT_NOT_FOUND' then []
35
+ else
36
+ raise Identikey::Error, "Search user failed: #{stat} - #{error}"
37
+ end
38
+ end
39
+
9
40
  attr_accessor :username
10
41
  attr_accessor :email
11
42
  attr_accessor :mobile
@@ -25,6 +56,7 @@ module Identikey
25
56
  attr_accessor :expires_at
26
57
  attr_accessor :expired
27
58
  attr_accessor :last_auth_attempt_at
59
+ attr_accessor :description
28
60
 
29
61
  def initialize(session, user = nil)
30
62
  @session = session
@@ -116,6 +148,7 @@ module Identikey
116
148
  self.expires_at = user['USERFLD_EXPIRATION_TIME']
117
149
  self.expired = user['USERFLD_EXPIRED']
118
150
  self.last_auth_attempt_at = user['USERFLD_LASTAUTHREQ_TIME']
151
+ self.description = user['USERFLD_DESCRIPTION']
119
152
 
120
153
  @persisted = persisted
121
154
 
@@ -15,8 +15,8 @@ module Identikey
15
15
  client wsdl: './sdk/wsdl/administration.wsdl'
16
16
 
17
17
  operations :logon, :logoff, :sessionalive,
18
- :admin_session_query, :user_execute,
19
- :digipass_execute, :digipassappl_execute
18
+ :admin_session_query, :user_execute, :user_query,
19
+ :digipass_execute, :digipass_query, :digipassappl_execute
20
20
 
21
21
  def logon(username:, password:, domain:)
22
22
  resp = super(message: {
@@ -150,6 +150,20 @@ module Identikey
150
150
  )
151
151
  end
152
152
 
153
+
154
+ def user_query(session_id:, attributes:, query_options:)
155
+ resp = super(message: {
156
+ sessionID: session_id,
157
+ attributeSet: {
158
+ attributes: typed_attributes_query_list_from(attributes)
159
+ },
160
+ queryOptions: query_options
161
+ })
162
+
163
+ parse_response resp, :user_query_response
164
+ end
165
+
166
+
153
167
  def digipass_execute(session_id:, cmd:, attributes: [])
154
168
  resp = super(message: {
155
169
  sessionID: session_id,
@@ -195,6 +209,20 @@ module Identikey
195
209
  )
196
210
  end
197
211
 
212
+
213
+ def digipass_query(session_id:, attributes:, query_options:)
214
+ resp = super(message: {
215
+ sessionID: session_id,
216
+ attributeSet: {
217
+ attributes: typed_attributes_query_list_from(attributes)
218
+ },
219
+ queryOptions: query_options
220
+ })
221
+
222
+ parse_response resp, :digipass_query_response
223
+ end
224
+
225
+
198
226
  def digipassappl_execute(session_id:, cmd:, attributes:)
199
227
  resp = super(message: {
200
228
  sessionID: session_id,
@@ -220,12 +220,35 @@ module Identikey
220
220
  end
221
221
  end
222
222
 
223
+ def typed_attributes_list_from(hash)
224
+ self.class.typed_attributes_list_from(hash)
225
+ end
226
+
227
+ # Calls typed_attribute_query_list_from() by removing the
228
+ # nil values from the given hash.
229
+ #
230
+ # The nil values are ignored when calling API endpoints that
231
+ # are not query ones, as such there is no point in adding an
232
+ # attributeOption null:true on those.
233
+ #
234
+ def self.typed_attributes_list_from(hash)
235
+ typed_attributes_query_list_from(hash.reject {|k,v| v.nil?})
236
+ end
237
+
238
+ def typed_attributes_query_list_from(hash)
239
+ self.class.typed_attributes_query_list_from(hash)
240
+ end
241
+
223
242
  # Converts and hash keyed by attribute name into an array of hashes
224
243
  # whose keys are the attribute name as attributeID and the value as
225
244
  # a Gyoku-compatible hash with the xsd:type annotation. The type is
226
245
  # inferred from the Ruby value type and the contents are serialized
227
246
  # as a string formatted as per the XSD DTD definition.
228
247
  #
248
+ # Further, this supports "virtual" attributes with a "NOT_" prefix.
249
+ # If the NOT_ prefix is set to the attribute name then the negative
250
+ # attributeOption is set.
251
+ #
229
252
  # <rant>
230
253
  # This code should not exist, because defining argument types is what
231
254
  # WSDL is for. However, in the braindead web services implementation
@@ -235,8 +258,15 @@ module Identikey
235
258
  # than an aid.
236
259
  # </rant>
237
260
  #
238
- def typed_attributes_list_from(hash)
239
- hash.map do |name, value|
261
+ def self.typed_attributes_query_list_from(hash)
262
+ hash.map do |full_name, value|
263
+
264
+ parse = /^(not_)?(.*)/i.match(full_name.to_s)
265
+ name = parse[2]
266
+
267
+ options = []
268
+ options.push(negative: true) if !parse[1].nil?
269
+
240
270
  type, value = case value
241
271
 
242
272
  when Unsigned
@@ -255,17 +285,61 @@ module Identikey
255
285
  [ 'xsd:string', value.to_s ]
256
286
 
257
287
  when NilClass
258
- next
288
+ options.push(null: true)
289
+ [ 'xsd:string', '' ]
259
290
 
260
291
  else
261
- raise Identikey::UsageError, "#{name} type #{value.class} is unsupported"
292
+ raise Identikey::UsageError, "#{full_name} type #{value.class} is unsupported"
262
293
  end
263
294
 
264
- { attributeID: name.to_s,
295
+ { attributeID: name,
296
+ attributeOptions: options,
265
297
  value: { '@xsi:type': type, content!: value } }
266
298
  end.compact
267
299
  end
268
300
 
301
+ # Translates the given attributes map into an hash suitable to be passed
302
+ # to typed_attributes_query_list_from(). This is used only to DRY the
303
+ # invocations across the _query methods.
304
+ #
305
+ def self.search_attributes_from(query, attribute_map:)
306
+ query.inject({}) do |ret, (key, value)|
307
+
308
+ parse = /^(not_)?(.*)/.match(key.to_s)
309
+ negate = !parse[1].nil?
310
+ name = parse[2]
311
+
312
+ attribute = attribute_map.fetch(name, nil)
313
+
314
+ if attribute.nil?
315
+ raise Identikey::UsageError, "Invalid search key: #{key}"
316
+ end
317
+
318
+ attribute = "NOT_#{attribute}" if negate
319
+
320
+ ret.update(attribute => value)
321
+ end
322
+ end
323
+
324
+ # Translate our search interface options into Identikey's _query methods
325
+ # interface options.
326
+ #
327
+ def self.search_options_from(options)
328
+ options.inject({}) do |ret, (option, value)|
329
+ attribute = {
330
+ 'distinct' => 'distinct',
331
+ 'limit' => 'rowcount',
332
+ 'offset' => 'rowoffset',
333
+ }.fetch(option.to_s, nil)
334
+
335
+ if attribute.nil?
336
+ raise Identikey::UsageError, "Invalid search option: #{option}"
337
+ end
338
+
339
+ ret.update(attribute => value)
340
+ end
341
+ end
342
+
269
343
  # protected
270
344
 
271
345
  end
@@ -1,3 +1,3 @@
1
1
  module Identikey
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: identikey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcello Barnaba
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-24 00:00:00.000000000 Z
11
+ date: 2019-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: savon