identikey 0.3.0

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