Class: SingtelSdp::BaseAdapter

Inherits:
Object
  • Object
show all
Defined in:
app/models/singtel_sdp/base_adapter.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sdp_xml_call) ⇒ BaseAdapter

Returns a new instance of BaseAdapter.



4
5
6
7
8
# File 'app/models/singtel_sdp/base_adapter.rb', line 4

def initialize(sdp_xml_call)
  @sdp_xml_call = sdp_xml_call
  @code = SingtelSdp::ReturnCode.new
  @resource
end

Class Method Details

.get_arguments(node) ⇒ Object



362
363
364
365
366
# File 'app/models/singtel_sdp/base_adapter.rb', line 362

def get_arguments(node)
  items = node.delete(:Item)
  items = [items] unless items.is_a? Array
  Hash[items.collect{ |i| [i[:fieldname].to_sym, i[:value]] }]
end

.get_header(header) ⇒ Object



357
358
359
360
# File 'app/models/singtel_sdp/base_adapter.rb', line 357

def get_header(header)
  header[:createdatetime] = DateTime.parse(header[:createdatetime])
  header
end

.otp_xml_request_body(otp) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'app/models/singtel_sdp/base_adapter.rb', line 118

def self.otp_xml_request_body(otp)
  xml = Builder::XmlMarkup.new(indent: 2)
  xml.instruct!
  xml.SingTelSDPRequest xmlns: 'SingTelSDPRequest.xsd' do
    xml.HeaderInfo '', userid: SingtelSdp.isvuserid, password: SingtelSdp.isvpassword,
      application: SingtelSdp.isvapplication, env: SingtelSdp.isvenv,
      adapterversion: SingtelSdp.isvadapterversion,
      createdatetime:Time.now.strftime('%FT%T%z'),
      requestno: Time.now.strftime('%Y%m%d%H%M%S%L')
    xml.RequestDetail do
      xml.Entity name: 'OTP', action:'SSO' do
        xml.Item '', fieldname: 'OTP', datatype: 'string', value: otp
      end
    end
  end
end

.parse_xml_request(xml) ⇒ Object



337
338
339
340
341
342
343
344
345
# File 'app/models/singtel_sdp/base_adapter.rb', line 337

def parse_xml_request(xml)
  result = {}
  main_node = parser.parse(xml)[:SingTelSDPRequest]
  result[:header_info] = get_header(main_node[:HeaderInfo])
  request_details = main_node[:RequestDetail][:Entity]
  request_details[:arguments] = get_arguments(request_details)
  result[:request_details] = request_details
  result
end

.parse_xml_response(xml) ⇒ Object



347
348
349
350
351
352
353
354
355
# File 'app/models/singtel_sdp/base_adapter.rb', line 347

def parse_xml_response(xml)
  result = {}
  main_node = parser.parse(xml)[:SingTelSDPResponse]
  response = main_node[:Result]
  return unless response[:returncode].to_i == 0
  result[:arguments] = get_arguments(response)
  result[:response] = response
  result
end

.parserObject



330
331
332
333
334
335
# File 'app/models/singtel_sdp/base_adapter.rb', line 330

def parser
  if @_parser.nil?
    @_parser = Nori.new(convert_tags_to: lambda { |tag| tag.gsub('@', '').to_sym })
  end
  @_parser
end

.valid_request?(xml) ⇒ Boolean

Returns:

  • (Boolean)


322
323
324
# File 'app/models/singtel_sdp/base_adapter.rb', line 322

def valid_request?(xml)
  valid_xml?(xml, SingtelSdp::REQUEST_XSD)
end

.valid_response?(xml) ⇒ Boolean

Returns:

  • (Boolean)


326
327
328
# File 'app/models/singtel_sdp/base_adapter.rb', line 326

def valid_response?(xml)
  valid_xml?(xml, SingtelSdp::RESPONSE_XSD)
end

.valid_xml?(xml, xsd_path) ⇒ Boolean

Returns:

  • (Boolean)


316
317
318
319
320
# File 'app/models/singtel_sdp/base_adapter.rb', line 316

def valid_xml?(xml, xsd_path)
  doc = Nokogiri::XML(xml)
  xsd = Nokogiri::XML::Schema(File.read(xsd_path))
  xsd.valid?(doc)
end

.verify_otp(otp) ⇒ Object



135
136
137
138
139
140
141
# File 'app/models/singtel_sdp/base_adapter.rb', line 135

def self.verify_otp(otp)
  url = SingtelSdp.sdp_url
  xml_response = SingtelSdp::SingtelHelper.raw_post_to_sdp(otp_xml_request_body(otp), url)
  response = parse_xml_response(xml_response) if xml_response
  return response[:arguments][:ISVUSERID] if response
  nil
end

Instance Method Details

#actionObject



188
189
190
# File 'app/models/singtel_sdp/base_adapter.rb', line 188

def action
  parsed[:request_details][:action].to_sym
end

#action_method_nameObject



192
193
194
# File 'app/models/singtel_sdp/base_adapter.rb', line 192

def action_method_name
  "#{action}_#{entity}"
end

#argumentsObject

returns all the params



180
181
182
# File 'app/models/singtel_sdp/base_adapter.rb', line 180

def arguments
  parsed[:request_details][:arguments]
end

#create_customerObject



224
225
226
227
228
# File 'app/models/singtel_sdp/base_adapter.rb', line 224

def create_customer
  validate_customer_arguments
  return if @code.has_errors?
  self.on_create_customer
end

#create_productObject



248
249
250
251
252
253
# File 'app/models/singtel_sdp/base_adapter.rb', line 248

def create_product
  validate_product_arguments
  validate_customer_arguments
  return if @code.has_errors?
  self.on_create_product
end

#create_userObject



275
276
277
278
279
280
# File 'app/models/singtel_sdp/base_adapter.rb', line 275

def create_user
  validate_customer_arguments
  validate_user_arguments
  return if @code.has_errors?
  self.on_create_user
end

#current_singtel_customerClass?

For almost all request the isvcustno should be check in your domain thats why this methods returns the current customer

Returns:

  • (Class, nil)

    with the customer that comes in each request.



81
82
83
# File 'app/models/singtel_sdp/base_adapter.rb', line 81

def current_singtel_customer
  find_singtel_customer(arguments[:ISVCUSTNO])
end

#current_singtel_productClass?

For manageing update_product requests the engine needs to check if that subscription exists.

Returns:

  • (Class, nil)

    with the current_singtel_product of the request.



73
74
75
# File 'app/models/singtel_sdp/base_adapter.rb', line 73

def current_singtel_product
  find_singtel_product(arguments[:ISVSUBSID])
end

#current_singtel_userClass?

Singtel_sdp engine needs a way to know if the user that singtel wants to work with exists or no. In this way the engine will be able to validate the input received in the domain of the adapter.

Returns:

  • (Class, nil)

    with the user instance in your domain.



66
67
68
# File 'app/models/singtel_sdp/base_adapter.rb', line 66

def current_singtel_user
  find_singtel_user(arguments[:ISVUSERID])
end

#delete_customerObject



236
237
238
239
240
# File 'app/models/singtel_sdp/base_adapter.rb', line 236

def delete_customer
  validate_customer_arguments
  return if @code.has_errors?
  self.on_delete_customer
end

#delete_productObject



266
267
268
269
270
271
272
273
# File 'app/models/singtel_sdp/base_adapter.rb', line 266

def delete_product
  validate_customer_arguments
  validate_product_arguments
  return if @code.has_errors?
  deleted_extenal_id = on_delete_product
  @code.origin = :target unless deleted_extenal_id
  deleted_extenal_id
end

#delete_userObject



288
289
290
291
292
293
# File 'app/models/singtel_sdp/base_adapter.rb', line 288

def delete_user
  validate_user_arguments
  validate_customer_arguments
  return if @code.has_errors?
  self.on_delete_user
end

#entityObject



184
185
186
# File 'app/models/singtel_sdp/base_adapter.rb', line 184

def entity
  parsed[:request_details][:name].downcase.to_sym
end

#executeObject



196
197
198
199
200
201
# File 'app/models/singtel_sdp/base_adapter.rb', line 196

def execute
  @code.action = action
  @code.entity = action == :select ? :customer_for_select : entity
  @return_value = send(action_method_name)
  @code.origin = :target unless @return_value or has_errors?
end

#find_singtel_customer(isvcustno) ⇒ Class?

As each implementation manage customers in a different way the engin needs to know how to find a singtel customers in your domain.

Returns:

  • (Class, nil)

    with the customer instance in your domain.

Raises:

  • (NotImplementedError)


56
57
58
# File 'app/models/singtel_sdp/base_adapter.rb', line 56

def find_singtel_customer(isvcustno)
  raise NotImplementedError.new('You must implement this method')
end

#find_singtel_product(isvsubsid) ⇒ Class?

As each implementation manage subscriptions in a different way the engine needs to know how to find a singtel subscription in your domain.

Returns:

  • (Class, nil)

    with the product instance in your domain.

Raises:

  • (NotImplementedError)


40
41
42
# File 'app/models/singtel_sdp/base_adapter.rb', line 40

def find_singtel_product(isvsubsid)
  raise NotImplementedError.new('You must implement this method')
end

#find_singtel_user(isvuserid) ⇒ Class?

As each implementation manage users in a different way the engine needs to know how to find a singtel user in your domain.

Returns:

  • (Class, nil)

    with the user instance in your domain.

Raises:

  • (NotImplementedError)


48
49
50
# File 'app/models/singtel_sdp/base_adapter.rb', line 48

def find_singtel_user(isvuserid)
  raise NotImplementedError.new('You must implement this method')
end

#has_errors?Boolean

mainly use for testing purpose

Returns:

  • (Boolean)


220
221
222
# File 'app/models/singtel_sdp/base_adapter.rb', line 220

def has_errors?
  @code.has_errors?
end

#header_infoObject



175
176
177
# File 'app/models/singtel_sdp/base_adapter.rb', line 175

def header_info
  parsed[:header_info]
end

#invalid_settingsObject



99
100
101
102
103
104
# File 'app/models/singtel_sdp/base_adapter.rb', line 99

def invalid_settings
  @invalid_settings ||= [:userid, :password, :application,
    :env, :adapterversion].reject do |key|
    header_info[key] == SingtelSdp.send("isv#{key}")
  end
end

#parsedHash

Contains an the xml request parsed by Nokogiri

Returns:

  • (Hash)

    with the request parsed



170
171
172
# File 'app/models/singtel_sdp/base_adapter.rb', line 170

def parsed
  @parsed ||= self.class.parse_xml_request(@sdp_xml_call)
end

#productsList

In order to validate the product sent by singtel the possible products should be defined.

Returns:

  • (List)

    of all the values that the product can take. eg: [‘PROD1’,‘PROD2’]

Raises:

  • (NotImplementedError)


23
24
25
# File 'app/models/singtel_sdp/base_adapter.rb', line 23

def products
  raise NotImplementedError.new("You must implement products.")
end

#requestnoString

This is for setting the request number in an specific response. That means that a response for a request will have the same requestno.

Returns:

  • (String)

    with the requestno that came in the request.



215
216
217
# File 'app/models/singtel_sdp/base_adapter.rb', line 215

def requestno
  header_info[:requestno]
end

#return_valueObject



203
204
205
# File 'app/models/singtel_sdp/base_adapter.rb', line 203

def return_value
  @return_value
end

#returncodeObject



207
208
209
# File 'app/models/singtel_sdp/base_adapter.rb', line 207

def returncode
  @code.generate
end

#rolesList

In order to validate the role sent by singtel the possible roles should be defined.

Returns:

  • (List)

    of all the values that the role can have. eg: [‘COOL USER’,‘DEFAULT USER’]

Raises:

  • (NotImplementedError)


15
16
17
# File 'app/models/singtel_sdp/base_adapter.rb', line 15

def roles
  raise NotImplementedError.new("You must implement roles.")
end

#select_customerObject



242
243
244
245
246
# File 'app/models/singtel_sdp/base_adapter.rb', line 242

def select_customer
  validate_customer_arguments
  return if @code.has_errors?
  self.on_select_customer
end

#selectfrom_valuesList

In order to validate the SELECTFROM value sent by singtel the possible values should be defined.

eg: [ ‘LICENSE_SUMMARY’ ]

Returns:

  • (List)

    of all the values that the SELECTFROM field can take.

Raises:

  • (NotImplementedError)


32
33
34
# File 'app/models/singtel_sdp/base_adapter.rb', line 32

def selectfrom_values
  raise NotImplementedError.new("You must implement selectfrom_values.")
end

#update_customerObject



230
231
232
233
234
# File 'app/models/singtel_sdp/base_adapter.rb', line 230

def update_customer
  validate_customer_arguments
  return if @code.has_errors?
  self.on_update_customer
end

#update_productObject

In case of an update in a subscription we check the amount of accounts that the previous account represented and replace that ammount in the max_account value. This value contains the max ammount of accounts that an organization backup



259
260
261
262
263
264
# File 'app/models/singtel_sdp/base_adapter.rb', line 259

def update_product
  validate_product_arguments
  validate_customer_arguments
  return if @code.has_errors?
  self.on_update_product
end

#update_userObject



282
283
284
285
286
# File 'app/models/singtel_sdp/base_adapter.rb', line 282

def update_user
  validate_user_arguments
  return if @code.has_errors?
  self.on_update_user
end

#valid_header?Boolean

Used for validating a sdp request header. Checks the attibutes from the header and sets to source of the error that will yield the proper error code.

Returns:

  • (Boolean)

    true is the header is correct



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'app/models/singtel_sdp/base_adapter.rb', line 149

def valid_header?
  unless invalid_settings.empty?
    @code.origin = :source
    @code.entity = :customer
  end

  case
  when !(invalid_settings & [:userid, :password]).empty?
  when invalid_settings.include?(:application)
    @code.custom = :invalid_application
  when invalid_settings.include?(:env)
    @code.custom = :invalid_environment
  when invalid_settings.include?(:adapterversion)
    @code.custom = :invalid_adapterversion
  end

  !@code.has_errors?
end

#valid_sdp_call?Boolean

and its an sdp call

Returns:

  • (Boolean)

    with true value is the xml is correctly formed



108
109
110
111
112
113
114
115
116
# File 'app/models/singtel_sdp/base_adapter.rb', line 108

def valid_sdp_call?
  valid =  !@sdp_xml_call.blank? && self.class.valid_request?(@sdp_xml_call)
  unless valid
    @code.origin = :source
    @code.entity = :other
    @code.custom = :invalid_xml
  end
  valid
end

#validate_customer_argumentsObject



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'app/models/singtel_sdp/base_adapter.rb', line 295

def validate_customer_arguments
  if entity == :customer && action == :select
    @code.origin = :select_method
    if !current_singtel_customer
      @code.custom = :customer_not_found_for_select
    elsif not selectfrom_values.include?(arguments[:SELECTFROM])
      @code.custom = :invalid_selectfrom_value
    end
  else
    if entity == :customer && action == :create
      @code.origin = :source if current_singtel_customer
    elsif current_singtel_customer.nil?
      @code.origin = :source
      @code.custom = :customer_not_found if [:user, :product].include?(entity)
    end
  end
  current_singtel_customer
end