identikey 0.3.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d5a041647bdeb7baf1d5eee22d75c1c19039f7f2a95ed2f72919ce1a62a3c27e
4
+ data.tar.gz: 36b979cf4c32041377b4ab0b881afcca1fd880f8153ac1060447069c47658169
5
+ SHA512:
6
+ metadata.gz: 1bf5928570adb64247b63c0fd9b61cd02711db99c6591fdbedea4d013693dbf8d6cd13edfe06e1c9a77680f20ac95303e4870472e55026a28daff24e2a5f36d6
7
+ data.tar.gz: 7bcea676a24e5ddecbce9895796f5525f4b1ec2f96c27ef993718e7fcc8f1879acad082f88dca88fb154199283d01d87f253760fa1f970b0bca06a4c06d3bdec
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /log/
10
+
11
+ Gemfile.lock
12
+
13
+ .byebug_history
14
+
15
+ # vim swap files
16
+
17
+ .*.sw?
18
+
19
+ # rspec failure tracking
20
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in identikey.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Marcello Barnaba <m.barnaba@ifad.org>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # Identikey
2
+
3
+ This library is a thin and incomplete wrapper of the VASCO Identikey SOAP API.
4
+
5
+ Vasco Identikey has been recently re-branded as OneSpan Authentication Server.
6
+
7
+ ## Requirements
8
+
9
+ The gem requires the Vasco SDK, that is private intellectual property and
10
+ cannot be redistributed here. You have to obtain it from VASCO / OneSpan
11
+ as part of your subscription.
12
+
13
+ The gem interfaces against a running Identikey server, communicating on
14
+ port 8888/TCP the SOAP protocol over HTTPS.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'identikey', github: 'ifad/identikey'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ ## Configuration
29
+
30
+ By default the client expects WSDL files in the current working directory,
31
+ into `./sdk/wsdl` and it connects to an Identikey API endpoint on localhost
32
+ port 8888 using TLSv1.2. Great for development, but definitely not good for
33
+ production.
34
+
35
+ To configure the client, you should at least define where your WSDL files are
36
+ and where the SOAP endpoint is. Given the WSDL file is different for the two
37
+ API sets (Authentication and Administration), you need to configure the two
38
+ classes separately.
39
+
40
+ Use the `.configure` method, that will run the block you give to it in the
41
+ context of the [Savon::Globals](http://savonrb.com/version2/globals.html)
42
+ object as such all available configuration parameters are available as
43
+ instance methods.
44
+
45
+ Example:
46
+
47
+ ```ruby
48
+ Identikey::Authentication.configure do
49
+ wsdl './path/to/your/authentication.wsdl'
50
+ endpoint 'https://your-identikey.example.com:8888'
51
+
52
+ # ... more configuration options as needed ...
53
+ end
54
+
55
+ Identikey::Administration.configure do
56
+ wsdl './path/to/your/administrtaion.wsdl'
57
+ endpoint 'https://your-identikey.example.com:8888'
58
+
59
+ # ... more configuration options as needed ...
60
+ end
61
+ ```
62
+
63
+ By default, all SOAP requests and responses are logged to `log/identikey.log`.
64
+
65
+ If you want to reduce the logging level please use:
66
+
67
+ ```
68
+ Identikey::Authentication.configure do
69
+ log_level :info # or one of [:debug, :warn, :error, :fatal]
70
+ end
71
+ ```
72
+
73
+ Or to disable it altogether (not recommended):
74
+
75
+ ```
76
+ Identikey::Authentication.configure do
77
+ log false
78
+ end
79
+ ```
80
+
81
+ The `configure` block accepts all Savon options, for which documentation
82
+ is available here: http://savonrb.com/version2/globals.html feel free to
83
+ amend it to suit your needs.
84
+
85
+ The only option whose semantics differ from the default is `filters`, as
86
+ it adds handling the faulty parameter passing design in Identikey, where
87
+ the same elements are used to transmit different business informatios.
88
+
89
+ By default, sensitive values attribute are filtered out from the logs.
90
+ Other attributes to filter out can be specified by prefixing them with
91
+ `identikey:`. Example, filter out `CREDFLD_PASSWORD` and `CREDFLD_USERID`:
92
+
93
+ Example, filter out `CREDFLD_PASSWORD` and `CREDFLD_USERID`:
94
+
95
+ ```
96
+ Identikey::Authentication.configure do
97
+ filters [ 'identikey:CREDFLD_PASSWORD', 'identikey:CREDFLD_USERID' ]
98
+ end
99
+ ```
100
+
101
+ Please note that the following attributes are filtered out by default:
102
+
103
+ * CREDFLD_PASSWORD
104
+ * CREDFLD_STATIC_PASSWORD
105
+ * CREDFLD_SESSION_ID
106
+
107
+ Please note that if you set your custom filters, these will override the
108
+ defaults and you should also take care of filtering the above parameters
109
+ in addition to the ones you want to filter out.
110
+
111
+ ## Usage
112
+
113
+ This is still in alpha stage, as such there is not much documentation. Have a
114
+ look at the specs for sample usage.
115
+
116
+ * Verify an end user OTP
117
+
118
+ ```ruby
119
+ Identikey::Authentication.valid_otp?('username', 'otp')
120
+ ```
121
+
122
+ * Start an administration session
123
+
124
+ ```ruby
125
+ s = Identikey::Administration::Session.new(username: 'admin', password: 'foobar')
126
+ s.logon
127
+ ```
128
+
129
+ * Find a digipass
130
+
131
+ ```ruby
132
+ d = s.find_digipass('serial')
133
+ ```
134
+
135
+ * Perform an OTP test
136
+
137
+ ```ruby
138
+ d = d.test_otp('1234567890')
139
+ ```
140
+
141
+ * Assign a digipass to an user
142
+
143
+ ```ruby
144
+ d.assign! 'username'
145
+ ```
146
+
147
+ * Unassign a digipass
148
+
149
+ ```ruby
150
+ d.unassign!
151
+ ```
152
+
153
+ * End an administrative session
154
+
155
+ ```ruby
156
+ s.logoff
157
+ ```
158
+
159
+ ## Development
160
+
161
+ After checking out the repo, run `bin/setup` to install dependencies. Then,
162
+ run `rake` to run the tests. You can also run `bin/console` for an interactive
163
+ prompt that will allow you to experiment.
164
+
165
+ To install this gem onto your local machine, run `bundle exec rake install`.
166
+
167
+ To release a new version, update the version number in `version.rb`, and then
168
+ run `bundle exec rake release`, which will create a git tag for the version,
169
+ push git commits and tags, and push the `.gem` file to
170
+ [rubygems.org](https://rubygems.org).
171
+
172
+ ## Contributing
173
+
174
+ Bug reports and pull requests are welcome on GitHub at
175
+ https://github.com/ifad/identikey.
176
+
177
+ ## License
178
+
179
+ The gem is available as open source under the terms of the [MIT
180
+ License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |spec|
5
+ spec.rspec_opts = '-f doc'
6
+ end
7
+
8
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'identikey'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/identikey.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "identikey/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "identikey"
7
+ spec.version = Identikey::VERSION
8
+ spec.authors = ["Marcello Barnaba"]
9
+ spec.email = ["vjt@openssl.it"]
10
+
11
+ spec.summary = %q{OneSpan Authentication Server (former VASCO Identikey) wrapper for Ruby}
12
+ spec.description = %q{This gem contains a SOAP client to consume Identikey API}
13
+ spec.homepage = "https://github.com/ifad/identikey"
14
+ spec.license = "MIT"
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_dependency "savon", "~> 2.0"
26
+
27
+ spec.add_development_dependency "bundler", "~> 2.0"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rspec", "~> 3.0"
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'hirb'
32
+ spec.add_development_dependency 'byebug'
33
+ spec.add_development_dependency 'simplecov'
34
+ end
@@ -0,0 +1,103 @@
1
+ module Identikey
2
+ class Administration < Base
3
+
4
+ class Digipass
5
+ def self.find(session:, serial_no:)
6
+ new(session).find(serial_no)
7
+ end
8
+
9
+ def initialize(session, digipass = nil)
10
+ @session = session
11
+
12
+ replace(digipass) if digipass
13
+ end
14
+
15
+ def replace(digipass)
16
+ @attributes = {
17
+ serial: digipass['DIGIPASSFLD_SERNO'],
18
+ domain: digipass['DIGIPASSFLD_DOMAIN'],
19
+ ou: digipass['DIGIPASSFLD_ORGANIZATIONAL_UNIT'],
20
+ type: digipass['DIGIPASSFLD_DPTYPE'],
21
+ application: digipass['DIGIPASSFLD_ACTIVE_APPL_NAMES'],
22
+ status: digipass['DIGIPASSFLD_ASSIGN_STATUS'],
23
+ userid: digipass['DIGIPASSFLD_ASSIGNED_USERID'],
24
+ assigned_at: digipass['DIGIPASSFLD_ASSIGNED_DATE'],
25
+ grace_expires_at: digipass['DIGIPASSFLD_GRACE_PERIOD_EXPIRES'],
26
+ created_at: digipass['DIGIPASSFLD_CREATE_TIME'],
27
+ updated_at: digipass['DIGIPASSFLD_MODIFY_TIME'],
28
+ activation_count: digipass['DIGIPASSFLD_ACTIV_COUNT'],
29
+ last_activation_at: digipass['DIGIPASSFLD_LAST_ACTIV_TIME'],
30
+ bind_status: digipass['DIGIPASSFLD_BIND_STATUS'],
31
+ max_activations: digipass['DIGIPASSFLD_MAX_ACTIVATIONS'],
32
+ expired: digipass['DIGIPASSFLD_EXPIRED'],
33
+ grace_expired: digipass['DIGIPASSFLD_GRACE_PERIOD_EXPIRED']
34
+ }.freeze
35
+
36
+ self
37
+ end
38
+
39
+ def assigned?
40
+ self.status == 'Assigned'
41
+ end
42
+
43
+ def find(serial_no)
44
+ stat, digipass, error = @session.execute(
45
+ :digipass_execute_VIEW, serial_no: serial_no)
46
+
47
+ if stat != 'STAT_SUCCESS'
48
+ raise Identikey::Error, "Find digipass failed: #{stat} - #{error}"
49
+ end
50
+
51
+ replace(digipass)
52
+ end
53
+
54
+ def reload
55
+ find(self.serial)
56
+ end
57
+
58
+ def unassign!
59
+ stat, digipass, error = @session.execute(
60
+ :digipass_execute_UNASSIGN, serial_no: self.serial)
61
+
62
+ if stat != 'STAT_SUCCESS'
63
+ raise Identikey::Error, "Assign digipass failed: #{stat} - #{error}"
64
+ end
65
+
66
+ replace(digipass)
67
+ end
68
+
69
+ def assign!(username, domain)
70
+ stat, digipass, error = @session.execute(
71
+ :digipass_execute_ASSIGN, serial_no: self.serial, username: username, domain: domain)
72
+
73
+ if stat != 'STAT_SUCCESS'
74
+ raise Identikey::Error, "Unassign digipass failed: #{stat} - #{error}"
75
+ end
76
+
77
+ replace(digipass)
78
+ end
79
+
80
+ def test_otp(otp)
81
+ stat, appl, error = @session.execute(
82
+ :digipassappl_execute_TEST_OTP, serial_no: self.serial, appl: self.application, otp: otp)
83
+
84
+ # Stat is useless here - it reports whether the call or not has
85
+ # succeeded, not whether the OTP is valid
86
+ if stat != 'STAT_SUCCESS'
87
+ raise Identikey::Error, "Test OTP failed: #{stat} - #{error}"
88
+ end
89
+
90
+ appl['DIGIPASSAPPLFLD_RESULT_CODE'] == '0'
91
+ end
92
+
93
+ def method_missing(name, *args, &block)
94
+ if @attributes.key?(name)
95
+ @attributes.fetch(name)
96
+ else
97
+ super(name, *args, &block)
98
+ end
99
+ end
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,119 @@
1
+ module Identikey
2
+ class Administration < Base
3
+
4
+ class Session
5
+ attr_reader :username, :password, :domain
6
+ attr_reader :session_id, :product, :version
7
+ attr_reader :privileges, :location
8
+
9
+ def initialize(username:, password:, domain: 'master')
10
+ @client = Identikey::Administration.new
11
+
12
+ @username = username
13
+ @password = password
14
+ @domain = domain
15
+ end
16
+
17
+ def endpoint
18
+ @client.endpoint
19
+ end
20
+
21
+ def wsdl
22
+ @client.wsdl
23
+ end
24
+
25
+ def logon
26
+ stat, sess, error = @client.logon(username: @username, password: @password, domain: @domain)
27
+
28
+ if stat != 'STAT_SUCCESS'
29
+ raise Identikey::Error, "logon failed: #{stat} - #{error}"
30
+ end
31
+
32
+ @privileges = parse_privileges sess['CREDFLD_LOGICAL_ADMIN_PRIVILEGES']
33
+
34
+ @session_id = sess['CREDFLD_SESSION_ID'].freeze
35
+ @location = sess['CREDFLD_USER_LOCATION'].freeze
36
+ @last_logon = sess['CREDFLD_LAST_LOGON_TIME'].freeze
37
+
38
+ @product = sess['CREDFLD_PRODUCT_NAME'].freeze
39
+ @version = sess['CREDFLD_PRODUCT_VERSION'].freeze
40
+
41
+ self
42
+ end
43
+
44
+ def logoff
45
+ require_logged_on!
46
+
47
+ stat, _, error = @client.logoff session_id: @session_id
48
+
49
+ unless stat == 'STAT_ADMIN_SESSION_STOPPED' || stat == 'STAT_SUCCESS'
50
+ raise Identikey::Error, "logoff failed: #{stat} - #{error}"
51
+ end
52
+
53
+ @privileges = nil
54
+ @session_id = nil
55
+ @product = nil
56
+ @version = nil
57
+ @last_logon = nil
58
+
59
+ stat == 'STAT_SUCCESS'
60
+ end
61
+
62
+ def alive?
63
+ return false unless logged_on?
64
+
65
+ stat, _ = @client.sessionalive session_id: @session_id
66
+
67
+ stat == 'STAT_SUCCESS'
68
+ end
69
+
70
+ def execute(command, *args)
71
+ kwargs = args.first || {}
72
+ kwargs.update(session_id: @session_id)
73
+ @client.public_send(command, kwargs)
74
+ end
75
+
76
+ def all
77
+ require_logged_on!
78
+
79
+ SessionQuery.all session: self
80
+ end
81
+
82
+ def find_digipass(serial_no)
83
+ require_logged_on!
84
+
85
+ Digipass.find session: self, serial_no: serial_no
86
+ end
87
+
88
+ def find_user(username, domain = nil)
89
+ require_logged_on!
90
+
91
+ User.find session: self, username: username, domain: domain || self.domain
92
+ end
93
+
94
+ def inspect
95
+ "#<#{self.class.name} sid=#@session_id username=#@username domain=#@domain product=#@product>"
96
+ end
97
+
98
+ alias sid session_id
99
+
100
+ def logged_on?
101
+ !@session_id.nil?
102
+ end
103
+
104
+ def require_logged_on!
105
+ unless logged_on?
106
+ raise Identikey::Error, "Session is not logged on at the moment"
107
+ end
108
+ end
109
+
110
+ def parse_privileges(privileges)
111
+ privileges.split(', ').inject({}) do |h, priv|
112
+ privilege, status = priv.split(' ')
113
+ h.update(privilege => status == 'true')
114
+ end.freeze
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,35 @@
1
+ module Identikey
2
+ class Administration < Base
3
+
4
+ class SessionQuery
5
+ def self.all(session:)
6
+ stat, sessions, error = session.execute(:admin_session_query)
7
+
8
+ if stat != 'STAT_SUCCESS'
9
+ raise Identikey::Error, "query failed: #{stat} - #{error}"
10
+ end
11
+
12
+ sessions.map do |sess|
13
+ new(
14
+ idx: sess['ADMINSESSIONFLD_SESSION_IDX'],
15
+ username: sess['ADMINSESSIONFLD_LOGIN_NAME'],
16
+ domain: sess['ADMINSESSIONFLD_DOMAIN'],
17
+ location: sess['ADMINSESSIONFLD_LOCATION'],
18
+ start_time: sess['ADMINSESSIONFLD_START_TIME']
19
+ )
20
+ end
21
+ end
22
+
23
+ attr_reader :idx, :username, :domain, :location, :start_time
24
+
25
+ def initialize(idx:, username:, domain:, location:, start_time:)
26
+ @idx = idx
27
+ @username = username
28
+ @domain = domain
29
+ @location = location
30
+ @start_time = start_time
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,127 @@
1
+ module Identikey
2
+ class Administration < Base
3
+
4
+ class User
5
+ def self.find(session:, username:, domain:)
6
+ new(session).find(username, domain)
7
+ end
8
+
9
+ attr_accessor :username
10
+ attr_accessor :email
11
+ attr_accessor :mobile
12
+ attr_accessor :phone
13
+ attr_accessor :created_at
14
+ attr_accessor :updated_at
15
+ attr_accessor :has_digipass
16
+ attr_accessor :domain
17
+ attr_accessor :ou
18
+ attr_accessor :digipass
19
+ attr_accessor :local_auth
20
+ attr_accessor :backend_auth
21
+ attr_accessor :disabled
22
+ attr_accessor :lock_count
23
+ attr_accessor :locked
24
+ attr_accessor :last_auth_success_at
25
+ attr_accessor :expires_at
26
+ attr_accessor :expired
27
+ attr_accessor :last_auth_attempt_at
28
+
29
+ def initialize(session, user = nil)
30
+ @session = session
31
+
32
+ replace(user) if user
33
+ end
34
+
35
+ def find(username, domain)
36
+ stat, user, error = @session.execute(
37
+ :user_execute_VIEW, username: username, domain: domain)
38
+
39
+ if stat != 'STAT_SUCCESS'
40
+ raise Identikey::Error, "Find user failed: #{stat} - #{error}"
41
+ end
42
+
43
+ replace(user, persisted: true)
44
+ end
45
+
46
+ def persisted?
47
+ @persisted || false
48
+ end
49
+
50
+ def reload
51
+ find(self.username, self.domain)
52
+ end
53
+
54
+ def save!
55
+ method = persisted? ? :user_execute_UPDATE : :user_execute_CREATE
56
+
57
+ stat, user, error = @session.execute(method, attributes: {
58
+ USERFLD_BACKEND_AUTH: self.backend_auth,
59
+ USERFLD_DISABLED: self.disabled,
60
+ USERFLD_DOMAIN: self.domain,
61
+ USERFLD_EMAIL: self.email,
62
+ USERFLD_LOCAL_AUTH: self.local_auth,
63
+ USERFLD_LOCKED: self.locked,
64
+ USERFLD_MOBILE: self.mobile,
65
+ USERFLD_ORGANIZATIONAL_UNIT: self.ou,
66
+ USERFLD_PHONE: self.phone,
67
+ USERFLD_USERID: self.username
68
+ })
69
+
70
+ if stat != 'STAT_SUCCESS'
71
+ raise Identikey::Error, "Save user failed: #{stat} - #{error}"
72
+ end
73
+
74
+ replace(user, persisted: true)
75
+ end
76
+
77
+ def destroy!
78
+ unless self.persisted?
79
+ raise Identikey::Error, "User #{self.username} is not persisted"
80
+ end
81
+
82
+ unless self.username && self.domain
83
+ raise Identikey::Error, "User #{self} is missing username and/or domain"
84
+ end
85
+
86
+ stat, _, error = @session.execute(
87
+ :user_execute_DELETE, username: username, domain: domain)
88
+
89
+ if stat != 'STAT_SUCCESS'
90
+ raise Identikey::Error, "Delete user failed: #{stat} - #{error}"
91
+ end
92
+
93
+ @persisted = false
94
+
95
+ self
96
+ end
97
+
98
+ protected
99
+ def replace(user, persisted: false)
100
+ self.username = user['USERFLD_USERID']
101
+ self.email = user['USERFLD_EMAIL']
102
+ self.mobile = user['USERFLD_MOBILE']
103
+ self.phone = user['USERFLD_PHONE']
104
+ self.created_at = user['USERFLD_CREATE_TIME']
105
+ self.updated_at = user['USERFLD_MODIFY_TIME']
106
+ self.has_digipass = user['USERFLD_HAS_DP'] == 'Assigned'
107
+ self.domain = user['USERFLD_DOMAIN']
108
+ self.ou = user['USERFLD_ORGANIZATIONAL_UNIT']
109
+ self.digipass = user['USERFLD_ASSIGNED_DIGIPASS']&.split(',') || [ ]
110
+ self.local_auth = user['USERFLD_LOCAL_AUTH']
111
+ self.backend_auth = user['USERFLD_BACKEND_AUTH']
112
+ self.disabled = user['USERFLD_DISABLED']
113
+ self.lock_count = user['USERFLD_LOCK_COUNT']
114
+ self.locked = user['USERFLD_LOCKED']
115
+ self.last_auth_success_at = user['USERFLD_LASTAUTH_TIME']
116
+ self.expires_at = user['USERFLD_EXPIRATION_TIME']
117
+ self.expired = user['USERFLD_EXPIRED']
118
+ self.last_auth_attempt_at = user['USERFLD_LASTAUTHREQ_TIME']
119
+
120
+ @persisted = persisted
121
+
122
+ self
123
+ end
124
+ end
125
+
126
+ end
127
+ end