singtel_sdp 1.2.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 +7 -0
- data/LICENSE +20 -0
- data/README.md +134 -0
- data/Rakefile +27 -0
- data/app/assets/stylesheets/application.css +0 -0
- data/app/controllers/singtel_sdp/base_adapter_controller.rb +64 -0
- data/app/models/singtel_sdp/base_adapter.rb +400 -0
- data/app/models/singtel_sdp/return_code.rb +113 -0
- data/app/views/singtel_sdp/base_adapter/create_customer_response.xml.builder +9 -0
- data/app/views/singtel_sdp/base_adapter/create_product_response.xml.builder +9 -0
- data/app/views/singtel_sdp/base_adapter/create_user_response.xml.builder +9 -0
- data/app/views/singtel_sdp/base_adapter/delete_customer_response.xml.builder +6 -0
- data/app/views/singtel_sdp/base_adapter/delete_product_response.xml.builder +6 -0
- data/app/views/singtel_sdp/base_adapter/delete_user_response.xml.builder +6 -0
- data/app/views/singtel_sdp/base_adapter/error_response.xml.builder +7 -0
- data/app/views/singtel_sdp/base_adapter/invalid_session.html.haml +1 -0
- data/app/views/singtel_sdp/base_adapter/select_customer_response.xml.builder +11 -0
- data/app/views/singtel_sdp/base_adapter/update_customer_response.xml.builder +6 -0
- data/app/views/singtel_sdp/base_adapter/update_product_response.xml.builder +9 -0
- data/app/views/singtel_sdp/base_adapter/update_user_response.xml.builder +6 -0
- data/config/routes.rb +2 -0
- data/lib/generators/singtel_sdp_generator.rb +10 -0
- data/lib/generators/singtel_sdp_views_generator.rb +10 -0
- data/lib/resources/xsds/SingTelSDPRequest.xsd +41 -0
- data/lib/resources/xsds/SingTelSDPResponse.xsd +27 -0
- data/lib/singtel_sdp.rb +8 -0
- data/lib/singtel_sdp/engine.rb +51 -0
- data/lib/singtel_sdp/rails/routes.rb +11 -0
- data/lib/singtel_sdp/singtel_helper.rb +37 -0
- data/lib/singtel_sdp/version.rb +3 -0
- data/lib/tasks/singtel_sdp_tasks.rake +4 -0
- metadata +204 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 43a8326ed8b265c7ead7f7ea5c386a800a27d747
|
4
|
+
data.tar.gz: 7595fcfdcc6a294e7323ed5ea300bfc17d66d52d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d3a6c5701955cdc968146710befd6774948c815b7e057c4edeb4147cb43762ceb14a4e81a970dac23f5a1d23da8d9045f091df68f3bcdc0cb29cc65b90559a1c
|
7
|
+
data.tar.gz: 8ed91a7879fdaf249983c2d17ce8cce74a70616477fb9297b1eaae5ca44f92b54d3e46a0426b9743014e7b646e4cbc75de9a30147e43b82f9eb1d5ce9da9494d
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012-2014 Dropmysite Pte Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# SingtelSdp
|
2
|
+
|
3
|
+
The core of this gem its on `SingtelSdp::BaseAdapter` and `SingtelSdp::BaseAdapterController`.
|
4
|
+
|
5
|
+
Implementing these 2 classes will let you decide what to do with each request received from the sdp.
|
6
|
+
|
7
|
+
SingtelSdp let you forget about the xml connections, result codes and messages. It gives you the chance to focus on the implementation of the actions for each request.
|
8
|
+
|
9
|
+
This gem solves most of the hard problems with the integration with singtel.
|
10
|
+
|
11
|
+
## Installing
|
12
|
+
|
13
|
+
## Get the gem
|
14
|
+
|
15
|
+
Add this to your `Gemfile`.
|
16
|
+
|
17
|
+
```
|
18
|
+
gem 'singtel_sdp', '~>1.0.0', git: 'git://github.com/dropmyemail/singtel_sdp.git'
|
19
|
+
```
|
20
|
+
|
21
|
+
## Create the adapter
|
22
|
+
|
23
|
+
Use the provided generator to create the model, controller and initializer file for SingtelSdp.
|
24
|
+
|
25
|
+
```
|
26
|
+
rails g singtel_sdp
|
27
|
+
```
|
28
|
+
|
29
|
+
### Customize the models
|
30
|
+
|
31
|
+
`SingtelSdp::BaseAdapter` is an abstract class, You need to implement the abstract methods.
|
32
|
+
|
33
|
+
``` ruby
|
34
|
+
# app/models/singtel_Adapter.rb
|
35
|
+
#
|
36
|
+
class SingtelAdapter < SingtelSdp::BaseAdapter
|
37
|
+
def roles
|
38
|
+
# here you should return a list of the possible roles. eg ['ADMIN','DEFAULT']
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_singtel_customer(isvcustno)
|
42
|
+
# Find and return a singtel customer here, can be an instances of any class that represents an active customer.
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_singtel_product(isvsubsid)
|
46
|
+
# Find and return a singtel product subscription here, can be an instances of any class that represents an active subscription to a product in your domain.
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_singtel_user(isvuserid)
|
50
|
+
# Find and return your singtel user here, can be an instances of any class that represents your active user.
|
51
|
+
end
|
52
|
+
|
53
|
+
def on_create_customer
|
54
|
+
#create your singtel customer here. in arguments variable you ll find a hash with the params received in the request. eg: arguments[:ISVCUSTNO], return the ivcustno as a string if everything went fine, if not nil.
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_update_customer
|
58
|
+
#update your singtel customer here. in arguments variable you ll find a hash with the params received in the request. eg: arguments[:ISVCUSTNO], return the ivcustno as a string if everything went fine, if not nil.
|
59
|
+
end
|
60
|
+
|
61
|
+
def on_delete_customer
|
62
|
+
#delete your singtel customer here. in arguments variable you ll find a hash with the params received in the request. eg: arguments[:ISVCUSTNO], return the ivcustno as a string if everything went fine, if not nil.
|
63
|
+
end
|
64
|
+
|
65
|
+
def on_create_product
|
66
|
+
# Create your singtel product here. In arguments variable you ll find a hash with the params received in the request. eg arguments[:ISVSUBSID], return the isvsubsid as a string if everything went fine, if not nil.
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_update_product
|
70
|
+
# Update your singtel product here. In arguments variable you ll find a hash with the params received in the request. eg: arguments[:NEWISVSUBSID], return the newisvsubsid as a string if everything went fine, if not nil.
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_delete_product
|
74
|
+
# Update your singtel product here. In arguments variable you ll find a hash with the params received in the request. eg: arguments[:NEWISVSUBSID], return the newisvsubsid as a string if everything went fine, if not nil.
|
75
|
+
end
|
76
|
+
|
77
|
+
def on_create_user
|
78
|
+
end
|
79
|
+
|
80
|
+
def on_update_user
|
81
|
+
end
|
82
|
+
|
83
|
+
def on_delete_user
|
84
|
+
end
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
### Customize the controller
|
89
|
+
|
90
|
+
The `SintelSdp::BaseAdapterController` should be overriden. You have to override `SingtelSdp::SingtelBaseAdapterController#sign\_in\_singtel\_user #sign\_in\_singtel\_user`.
|
91
|
+
|
92
|
+
Optionally you can override `SingtelSdp::SingtelBaseAdapterController#on\_singtel\_login\_success #on\_singtel\_login\_success` and `SingtelSdp::SingtelBaseAdapterController#on\_singtel\_login\_failure #on\_singtel\_login\_failure`
|
93
|
+
|
94
|
+
``` ruby
|
95
|
+
# app/controller/singtel_controller.rb
|
96
|
+
class SingtelController < SingtelSdp::BaseAdapterController
|
97
|
+
def sign_in_singtel_user(isvuserid)
|
98
|
+
# this is an implementation :P
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
### Mounting the routes
|
104
|
+
|
105
|
+
We provide a shortcut so you can add the `SingtelSdp::BaseAdapterController BaseAdapterController` to your `routes.rb`.
|
106
|
+
|
107
|
+
Here's a snippet showing two different ways of mounting the routes:
|
108
|
+
|
109
|
+
``` ruby
|
110
|
+
# your routes.rb
|
111
|
+
YourApp::Application.routes.draw do
|
112
|
+
|
113
|
+
# Will mount the default SingtelSdp:BaseAdapterController in the
|
114
|
+
# /singtel path.
|
115
|
+
add_singtel_sdp_routes
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
### Customize the invalid session template
|
120
|
+
|
121
|
+
SingtelSdp will redirect to invalid session template if an sso login fails:
|
122
|
+
|
123
|
+
* problems with the otp.
|
124
|
+
* problems with the conextion.
|
125
|
+
|
126
|
+
You can copy the the built in template into your app's directory structure and customize them:
|
127
|
+
|
128
|
+
```
|
129
|
+
$ rails g singtel_sdp_views
|
130
|
+
```
|
131
|
+
|
132
|
+
# LICENSE
|
133
|
+
|
134
|
+
MIT-LICENSE. Check LICENSE for more details
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'SingtelSdp'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
File without changes
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class SingtelSdp::BaseAdapterController < ApplicationController
|
2
|
+
skip_before_filter :verify_authenticity_token
|
3
|
+
before_filter :parse_request, only: :adapter
|
4
|
+
before_filter :validate_request, only: :adapter
|
5
|
+
before_filter :validate_header, only: :adapter
|
6
|
+
|
7
|
+
#singtel/adapter
|
8
|
+
def adapter
|
9
|
+
@singtel_request.execute
|
10
|
+
@requestno = @singtel_request.requestno
|
11
|
+
@return_value = @singtel_request.return_value
|
12
|
+
@returncode = @singtel_request.returncode
|
13
|
+
logger.info @returncode
|
14
|
+
render(if @returncode == 0
|
15
|
+
"#{@singtel_request.action_method_name}_response"
|
16
|
+
else
|
17
|
+
:error_response
|
18
|
+
end)
|
19
|
+
end
|
20
|
+
|
21
|
+
#singtel/sso
|
22
|
+
def sso
|
23
|
+
isvuserid = SingtelAdapter.verify_otp(params['otp'])
|
24
|
+
isvuserid = SingtelAdapter.verify_otp(params['otp']) if isvuserid.nil?
|
25
|
+
if isvuserid && sign_in_singtel_user(isvuserid)
|
26
|
+
self.on_singtel_login_success
|
27
|
+
else
|
28
|
+
self.on_singtel_login_failure
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_singtel_login_success
|
33
|
+
redirect_to root_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_singtel_login_failure
|
37
|
+
redirect_to invalid_session_path
|
38
|
+
end
|
39
|
+
|
40
|
+
# Singtel_sdp engine call this method when an user is aproved by singtel.
|
41
|
+
# Here you need to loggin the User with the isvuserid received as a param to your site.
|
42
|
+
def sign_in_singtel_user(isvuserid)
|
43
|
+
raise NotImplementedError.new("You must implement sign in.")
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def parse_request
|
48
|
+
@singtel_request = SingtelAdapter.new(request.raw_post)
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate_request
|
52
|
+
unless @singtel_request.valid_sdp_call?
|
53
|
+
@returncode = @singtel_request.returncode
|
54
|
+
render :error_response
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_header
|
59
|
+
unless @singtel_request.valid_header?
|
60
|
+
@returncode = @singtel_request.returncode
|
61
|
+
render :error_response
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,400 @@
|
|
1
|
+
require 'builder'
|
2
|
+
|
3
|
+
class SingtelSdp::BaseAdapter
|
4
|
+
def initialize(sdp_xml_call)
|
5
|
+
@sdp_xml_call = sdp_xml_call
|
6
|
+
@code = SingtelSdp::ReturnCode.new
|
7
|
+
@resource
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
# In order to validate the role sent by singtel the possible roles should be
|
12
|
+
# defined.
|
13
|
+
#
|
14
|
+
# @return [List] of all the values that the role can have. eg: ['COOL USER','DEFAULT USER']
|
15
|
+
def roles
|
16
|
+
raise NotImplementedError.new("You must implement roles.")
|
17
|
+
end
|
18
|
+
|
19
|
+
# In order to validate the product sent by singtel the possible products should be
|
20
|
+
# defined.
|
21
|
+
#
|
22
|
+
# @return [List] of all the values that the product can take. eg: ['PROD1','PROD2']
|
23
|
+
def products
|
24
|
+
raise NotImplementedError.new("You must implement products.")
|
25
|
+
end
|
26
|
+
|
27
|
+
# In order to validate the SELECTFROM value sent by singtel the possible values should be
|
28
|
+
# defined.
|
29
|
+
#
|
30
|
+
# @return [List] of all the values that the SELECTFROM field can take.
|
31
|
+
# eg: [ 'LICENSE_SUMMARY' ]
|
32
|
+
def selectfrom_values
|
33
|
+
raise NotImplementedError.new("You must implement selectfrom_values.")
|
34
|
+
end
|
35
|
+
|
36
|
+
# As each implementation manage subscriptions in a different way the engine needs to know
|
37
|
+
# how to find a singtel subscription in your domain.
|
38
|
+
#
|
39
|
+
# @return [Class, nil] with the product instance in your domain.
|
40
|
+
def find_singtel_product(isvsubsid)
|
41
|
+
raise NotImplementedError.new('You must implement this method')
|
42
|
+
end
|
43
|
+
|
44
|
+
# As each implementation manage users in a different way the engine needs to know
|
45
|
+
# how to find a singtel user in your domain.
|
46
|
+
#
|
47
|
+
# @return [Class, nil] with the user instance in your domain.
|
48
|
+
def find_singtel_user(isvuserid)
|
49
|
+
raise NotImplementedError.new('You must implement this method')
|
50
|
+
end
|
51
|
+
|
52
|
+
# As each implementation manage customers in a different way the engin needs to know
|
53
|
+
# how to find a singtel customers in your domain.
|
54
|
+
#
|
55
|
+
# @return [Class, nil] with the customer instance in your domain.
|
56
|
+
def find_singtel_customer(isvcustno)
|
57
|
+
raise NotImplementedError.new('You must implement this method')
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Singtel_sdp engine needs a way to know if the user that singtel wants to work with
|
62
|
+
# exists or no. In this way the engine will be able to validate the input received in
|
63
|
+
# the domain of the adapter.
|
64
|
+
#
|
65
|
+
# @return [Class, nil] with the user instance in your domain.
|
66
|
+
def current_singtel_user
|
67
|
+
find_singtel_user(arguments[:ISVUSERID])
|
68
|
+
end
|
69
|
+
|
70
|
+
# For manageing update_product requests the engine needs to check if that subscription exists.
|
71
|
+
#
|
72
|
+
# @return [Class, nil] with the current_singtel_product of the request.
|
73
|
+
def current_singtel_product
|
74
|
+
find_singtel_product(arguments[:ISVSUBSID])
|
75
|
+
end
|
76
|
+
|
77
|
+
# For almost all request the isvcustno should be check in your domain thats why this methods
|
78
|
+
# returns the current customer
|
79
|
+
#
|
80
|
+
# @return [Class, nil] with the customer that comes in each request.
|
81
|
+
def current_singtel_customer
|
82
|
+
find_singtel_customer(arguments[:ISVCUSTNO])
|
83
|
+
end
|
84
|
+
|
85
|
+
[ :on_create_customer, :on_update_customer, :on_delete_customer, :on_select_customer,
|
86
|
+
:on_create_product, :on_update_product, :on_delete_product,
|
87
|
+
:on_create_user, :on_update_user, :on_delete_user ].each do |name|
|
88
|
+
# When singtel send an action for updating deleting or creating an entity you should
|
89
|
+
# represent that action in your domain. that means for example updating deleting or creating
|
90
|
+
# one of your users.
|
91
|
+
#
|
92
|
+
# @return [String, nil] the external id of the object that was updated,deleted or created.
|
93
|
+
# nil on failure
|
94
|
+
define_method name do
|
95
|
+
raise NotImplementedError.new("You must implement #{name}.")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def invalid_settings
|
100
|
+
@invalid_settings ||= [:userid, :password, :application,
|
101
|
+
:env, :adapterversion].reject do |key|
|
102
|
+
header_info[key] == SingtelSdp.send("isv#{key}")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [Boolean] with true value is the xml is correctly formed
|
107
|
+
# and its an sdp call
|
108
|
+
def valid_sdp_call?
|
109
|
+
valid = !@sdp_xml_call.blank? && self.class.valid_request?(@sdp_xml_call)
|
110
|
+
unless valid
|
111
|
+
@code.origin = :source
|
112
|
+
@code.entity = :other
|
113
|
+
@code.custom = :invalid_xml
|
114
|
+
end
|
115
|
+
valid
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.otp_xml_request_body(otp)
|
119
|
+
xml = Builder::XmlMarkup.new(indent: 2)
|
120
|
+
xml.instruct!
|
121
|
+
xml.SingTelSDPRequest xmlns: 'SingTelSDPRequest.xsd' do
|
122
|
+
xml.HeaderInfo '', userid: SingtelSdp.isvuserid, password: SingtelSdp.isvpassword,
|
123
|
+
application: SingtelSdp.isvapplication, env: SingtelSdp.isvenv,
|
124
|
+
adapterversion: SingtelSdp.isvadapterversion,
|
125
|
+
createdatetime:Time.now.strftime('%FT%T%z'),
|
126
|
+
requestno: Time.now.strftime('%Y%m%d%H%M%S%L')
|
127
|
+
xml.RequestDetail do
|
128
|
+
xml.Entity name: 'OTP', action:'SSO' do
|
129
|
+
xml.Item '', fieldname: 'OTP', datatype: 'string', value: otp
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.verify_otp(otp)
|
136
|
+
url = SingtelSdp.sdp_url
|
137
|
+
xml_response = SingtelSdp::SingtelHelper.raw_post_to_sdp(otp_xml_request_body(otp), url)
|
138
|
+
response = parse_xml_response(xml_response) if xml_response
|
139
|
+
return response[:arguments][:ISVUSERID] if response
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
# Used for validating a sdp request header.
|
145
|
+
# Checks the attibutes from the header and sets to source of the error
|
146
|
+
# that will yield the proper error code.
|
147
|
+
#
|
148
|
+
# @return [Boolean] true is the header is correct
|
149
|
+
def valid_header?
|
150
|
+
unless invalid_settings.empty?
|
151
|
+
@code.origin = :source
|
152
|
+
@code.entity = :customer
|
153
|
+
end
|
154
|
+
|
155
|
+
case
|
156
|
+
when !(invalid_settings & [:userid, :password]).empty?
|
157
|
+
when invalid_settings.include?(:application)
|
158
|
+
@code.custom = :invalid_application
|
159
|
+
when invalid_settings.include?(:env)
|
160
|
+
@code.custom = :invalid_environment
|
161
|
+
when invalid_settings.include?(:adapterversion)
|
162
|
+
@code.custom = :invalid_adapterversion
|
163
|
+
end
|
164
|
+
|
165
|
+
!@code.has_errors?
|
166
|
+
end
|
167
|
+
|
168
|
+
# Contains an the xml request parsed by Nokogiri
|
169
|
+
# @return [Hash] with the request parsed
|
170
|
+
def parsed
|
171
|
+
@parsed ||= self.class.parse_xml_request(@sdp_xml_call)
|
172
|
+
end
|
173
|
+
|
174
|
+
# @returns [Hash] with the accessor to the header node from the parsed request
|
175
|
+
def header_info
|
176
|
+
parsed[:header_info]
|
177
|
+
end
|
178
|
+
|
179
|
+
# returns all the params
|
180
|
+
def arguments
|
181
|
+
parsed[:request_details][:arguments]
|
182
|
+
end
|
183
|
+
|
184
|
+
def entity
|
185
|
+
parsed[:request_details][:name].downcase.to_sym
|
186
|
+
end
|
187
|
+
|
188
|
+
def action
|
189
|
+
parsed[:request_details][:action].to_sym
|
190
|
+
end
|
191
|
+
|
192
|
+
def action_method_name
|
193
|
+
"#{action}_#{entity}"
|
194
|
+
end
|
195
|
+
|
196
|
+
def execute
|
197
|
+
@code.action = action
|
198
|
+
@code.entity = action == :select ? :customer_for_select : entity
|
199
|
+
@return_value = send(action_method_name)
|
200
|
+
@code.origin = :target unless @return_value or has_errors?
|
201
|
+
end
|
202
|
+
|
203
|
+
def return_value
|
204
|
+
@return_value
|
205
|
+
end
|
206
|
+
|
207
|
+
def returncode
|
208
|
+
@code.generate
|
209
|
+
end
|
210
|
+
|
211
|
+
# This is for setting the request number in an specific response. That means that a
|
212
|
+
# response for a request will have the same requestno.
|
213
|
+
#
|
214
|
+
# @return [String] with the requestno that came in the request.
|
215
|
+
def requestno
|
216
|
+
header_info[:requestno]
|
217
|
+
end
|
218
|
+
|
219
|
+
# mainly use for testing purpose
|
220
|
+
def has_errors?
|
221
|
+
@code.has_errors?
|
222
|
+
end
|
223
|
+
|
224
|
+
def create_customer
|
225
|
+
validate_customer_arguments
|
226
|
+
return if @code.has_errors?
|
227
|
+
self.on_create_customer
|
228
|
+
end
|
229
|
+
|
230
|
+
def update_customer
|
231
|
+
validate_customer_arguments
|
232
|
+
return if @code.has_errors?
|
233
|
+
self.on_update_customer
|
234
|
+
end
|
235
|
+
|
236
|
+
def delete_customer
|
237
|
+
validate_customer_arguments
|
238
|
+
return if @code.has_errors?
|
239
|
+
self.on_delete_customer
|
240
|
+
end
|
241
|
+
|
242
|
+
def select_customer
|
243
|
+
validate_customer_arguments
|
244
|
+
return if @code.has_errors?
|
245
|
+
self.on_select_customer
|
246
|
+
end
|
247
|
+
|
248
|
+
def create_product
|
249
|
+
validate_product_arguments
|
250
|
+
validate_customer_arguments
|
251
|
+
return if @code.has_errors?
|
252
|
+
self.on_create_product
|
253
|
+
end
|
254
|
+
|
255
|
+
# In case of an update in a subscription we check the amount of accounts that
|
256
|
+
# the previous account represented and replace that ammount in the max_account
|
257
|
+
# value. This value contains the max ammount of accounts that an organization
|
258
|
+
# backup
|
259
|
+
def update_product
|
260
|
+
validate_product_arguments
|
261
|
+
validate_customer_arguments
|
262
|
+
return if @code.has_errors?
|
263
|
+
self.on_update_product
|
264
|
+
end
|
265
|
+
|
266
|
+
def delete_product
|
267
|
+
validate_customer_arguments
|
268
|
+
validate_product_arguments
|
269
|
+
return if @code.has_errors?
|
270
|
+
deleted_extenal_id = on_delete_product
|
271
|
+
@code.origin = :target unless deleted_extenal_id
|
272
|
+
deleted_extenal_id
|
273
|
+
end
|
274
|
+
|
275
|
+
def create_user
|
276
|
+
validate_customer_arguments
|
277
|
+
validate_user_arguments
|
278
|
+
return if @code.has_errors?
|
279
|
+
self.on_create_user
|
280
|
+
end
|
281
|
+
|
282
|
+
def update_user
|
283
|
+
validate_user_arguments
|
284
|
+
return if @code.has_errors?
|
285
|
+
self.on_update_user
|
286
|
+
end
|
287
|
+
|
288
|
+
def delete_user
|
289
|
+
validate_user_arguments
|
290
|
+
validate_customer_arguments
|
291
|
+
return if @code.has_errors?
|
292
|
+
self.on_delete_user
|
293
|
+
end
|
294
|
+
|
295
|
+
def validate_customer_arguments
|
296
|
+
if entity == :customer && action == :select
|
297
|
+
@code.origin = :select_method
|
298
|
+
if !current_singtel_customer
|
299
|
+
@code.custom = :customer_not_found_for_select
|
300
|
+
elsif not selectfrom_values.include?(arguments[:SELECTFROM])
|
301
|
+
@code.custom = :invalid_selectfrom_value
|
302
|
+
end
|
303
|
+
else
|
304
|
+
if entity == :customer && action == :create
|
305
|
+
@code.origin = :source if current_singtel_customer
|
306
|
+
elsif current_singtel_customer.nil?
|
307
|
+
@code.origin = :source
|
308
|
+
@code.custom = :customer_not_found if [:user, :product].include?(entity)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
current_singtel_customer
|
312
|
+
end
|
313
|
+
|
314
|
+
|
315
|
+
class << self
|
316
|
+
def valid_xml?(xml, xsd_path)
|
317
|
+
doc = Nokogiri::XML(xml)
|
318
|
+
xsd = Nokogiri::XML::Schema(File.read(xsd_path))
|
319
|
+
xsd.valid?(doc)
|
320
|
+
end
|
321
|
+
|
322
|
+
def valid_request?(xml)
|
323
|
+
valid_xml?(xml, SingtelSdp::REQUEST_XSD)
|
324
|
+
end
|
325
|
+
|
326
|
+
def valid_response?(xml)
|
327
|
+
valid_xml?(xml, SingtelSdp::RESPONSE_XSD)
|
328
|
+
end
|
329
|
+
|
330
|
+
def parser
|
331
|
+
if @_parser.nil?
|
332
|
+
@_parser = Nori.new(convert_tags_to: lambda { |tag| tag.gsub('@', '').to_sym })
|
333
|
+
end
|
334
|
+
@_parser
|
335
|
+
end
|
336
|
+
|
337
|
+
def parse_xml_request(xml)
|
338
|
+
result = {}
|
339
|
+
main_node = parser.parse(xml)[:SingTelSDPRequest]
|
340
|
+
result[:header_info] = get_header(main_node[:HeaderInfo])
|
341
|
+
request_details = main_node[:RequestDetail][:Entity]
|
342
|
+
request_details[:arguments] = get_arguments(request_details)
|
343
|
+
result[:request_details] = request_details
|
344
|
+
result
|
345
|
+
end
|
346
|
+
|
347
|
+
def parse_xml_response(xml)
|
348
|
+
result = {}
|
349
|
+
main_node = parser.parse(xml)[:SingTelSDPResponse]
|
350
|
+
response = main_node[:Result]
|
351
|
+
return unless response[:returncode].to_i == 0
|
352
|
+
result[:arguments] = get_arguments(response)
|
353
|
+
result[:response] = response
|
354
|
+
result
|
355
|
+
end
|
356
|
+
|
357
|
+
def get_header(header)
|
358
|
+
header[:createdatetime] = DateTime.parse(header[:createdatetime])
|
359
|
+
header
|
360
|
+
end
|
361
|
+
|
362
|
+
def get_arguments(node)
|
363
|
+
items = node.delete(:Item)
|
364
|
+
items = [items] unless items.is_a? Array
|
365
|
+
Hash[items.collect{ |i| [i[:fieldname].to_sym, i[:value]] }]
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
private
|
371
|
+
|
372
|
+
def validate_user_arguments
|
373
|
+
user = current_singtel_user
|
374
|
+
if !roles.include?(arguments[:ISVUSERROLE]) && action != :delete
|
375
|
+
@code.origin = :source
|
376
|
+
@code.custom = :invalid_user_role
|
377
|
+
elsif entity == :user && action == :create
|
378
|
+
@code.origin = :source if user
|
379
|
+
elsif user.nil?
|
380
|
+
@code.origin = :source
|
381
|
+
end
|
382
|
+
|
383
|
+
user
|
384
|
+
end
|
385
|
+
|
386
|
+
def validate_product_arguments
|
387
|
+
if !products.include?(arguments[:NEWISVPRODID]) && action == :update or
|
388
|
+
!products.include?(arguments[:ISVPRODID]) && action == :create
|
389
|
+
@code.origin = :source
|
390
|
+
@code.custom = :invalid_product_name
|
391
|
+
elsif arguments[:NEWISVSUBSID] && find_singtel_product(arguments[:NEWISVSUBSID])
|
392
|
+
@code.custom = :duplicated_subscription
|
393
|
+
@code.origin = :source
|
394
|
+
elsif current_singtel_product.nil? && action != :create
|
395
|
+
@code.origin = :source
|
396
|
+
end
|
397
|
+
current_singtel_product
|
398
|
+
end
|
399
|
+
|
400
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
class SingtelSdp::ReturnCode
|
2
|
+
ORIGINS = { no_error: 0, target: 1, source: 2, customer_data: 3, select_method: 6 }
|
3
|
+
ACTIONS = { general: 0, create: 2, update: 4, delete: 6, select: 0 }
|
4
|
+
ENTITIES = { general: 0, other: 1, customer: 2, product: 4, user: 6, customer_for_select: 0 }
|
5
|
+
CUSTOM_DIGIT = { general: 0, invalid_application: 1,
|
6
|
+
invalid_product_name: 1, invalid_user_role: 1,
|
7
|
+
invalid_environment: 3, invalid_adapterversion: 4,
|
8
|
+
duplicated_subscription: 4, invalid_xml: 5,
|
9
|
+
customer_not_found: 5,
|
10
|
+
customer_not_found_for_select: 1, invalid_selectfrom_value: 2 }
|
11
|
+
|
12
|
+
RETURN_MESSAGES = {
|
13
|
+
0 => 'Success',
|
14
|
+
-1 => 'In Progress',
|
15
|
+
1000 => 'General Error',
|
16
|
+
1220 => 'Failed to Create Customer',
|
17
|
+
1240 => 'Failed to Create Product',
|
18
|
+
1260 => 'Failed to Create User',
|
19
|
+
1420 => 'Failed to Update Customer',
|
20
|
+
1440 => 'Failed to Update Product',
|
21
|
+
1460 => 'Failed to Update User',
|
22
|
+
1620 => 'Failed to Delete Customer',
|
23
|
+
1640 => 'Failed to Delete Product',
|
24
|
+
1660 => 'Failed to Delete User',
|
25
|
+
2000 => 'Invalid OTP',
|
26
|
+
2010 => 'Invalid Source Server',
|
27
|
+
2015 => 'Invalid Request XML',
|
28
|
+
2016 => 'Invalid Response XML',
|
29
|
+
2020 => 'Invalid UserID and Password',
|
30
|
+
2021 => 'Invalid application name',
|
31
|
+
2023 => 'Invalid environment',
|
32
|
+
2024 => 'Invalid adapter version',
|
33
|
+
2025 => 'Invalid CreateDatetime',
|
34
|
+
2026 => 'Duplicated requestno',
|
35
|
+
2040 => 'Invalid Entity type',
|
36
|
+
2041 => 'Invalid Action type',
|
37
|
+
2220 => 'Duplicated Customer',
|
38
|
+
2240 => 'Duplicated Subscription',
|
39
|
+
2241 => 'Invalid Product Name',
|
40
|
+
2242 => 'Invalid Trial Indicator',
|
41
|
+
2243 => 'Invalid Quantity',
|
42
|
+
2245 => 'Customer not found',
|
43
|
+
2260 => 'Duplicated User',
|
44
|
+
2261 => 'Invalid User Role',
|
45
|
+
2265 => 'Customer not found',
|
46
|
+
2266 => 'Subscription not found',
|
47
|
+
2420 => 'Customer Not found',
|
48
|
+
2440 => 'Subscription Not found',
|
49
|
+
2441 => 'Invalid Product Name',
|
50
|
+
2442 => 'Invalid Trial Indicator',
|
51
|
+
2443 => 'Invalid Quantity',
|
52
|
+
2444 => 'Duplicated Subscription',
|
53
|
+
2460 => 'User Not Found',
|
54
|
+
2461 => 'Invalid User Role',
|
55
|
+
2620 => 'Customer not found',
|
56
|
+
2640 => 'Subscription not found',
|
57
|
+
2645 => 'Customer not found',
|
58
|
+
2660 => 'User not found',
|
59
|
+
2665 => 'Customer not found',
|
60
|
+
2666 => 'Subscription not found',
|
61
|
+
3260 => 'Email cannot be null',
|
62
|
+
3261 => 'Invalid Email account',
|
63
|
+
3262 => 'Existing Email account detected',
|
64
|
+
3263 => 'Exceeded allowed number of total users license',
|
65
|
+
3264 => 'Exceeded allowed number of admin users license',
|
66
|
+
3460 => 'Invalid Email account',
|
67
|
+
3462 => 'Existing Email account',
|
68
|
+
6001 => 'Customer not found',
|
69
|
+
6002 => 'Invalid SELECTFROM value',
|
70
|
+
}
|
71
|
+
|
72
|
+
def initialize
|
73
|
+
# These are the four digits that will compose
|
74
|
+
# the final returncode
|
75
|
+
self.origin = :no_error
|
76
|
+
self.action = :general
|
77
|
+
self.entity = :general
|
78
|
+
self.custom = :general
|
79
|
+
end
|
80
|
+
|
81
|
+
def origin=(key)
|
82
|
+
@origin = ORIGINS[key]
|
83
|
+
end
|
84
|
+
|
85
|
+
def action=(key)
|
86
|
+
@action = ACTIONS[key]
|
87
|
+
end
|
88
|
+
|
89
|
+
def entity=(key)
|
90
|
+
@entity = ENTITIES[key]
|
91
|
+
end
|
92
|
+
|
93
|
+
def custom=(key)
|
94
|
+
@custom = CUSTOM_DIGIT[key]
|
95
|
+
end
|
96
|
+
|
97
|
+
def generate
|
98
|
+
return 0 unless has_errors?
|
99
|
+
"#{@origin}#{@action}#{@entity}#{@custom}".to_i
|
100
|
+
end
|
101
|
+
|
102
|
+
def message
|
103
|
+
RETURN_MESSAGES[generate]
|
104
|
+
end
|
105
|
+
|
106
|
+
def has_errors?
|
107
|
+
if @origin == ORIGINS[:select_method]
|
108
|
+
@custom != 0
|
109
|
+
else
|
110
|
+
@origin != 0
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.SingTelSDPResponse xmlns: 'SingTelSDPResponse.xsd' do
|
3
|
+
xml.Result returncode: @returncode,
|
4
|
+
returnmessage: SingtelSdp::ReturnCode::RETURN_MESSAGES[@returncode],
|
5
|
+
requestno: @requestno, moreinfo: @moreinfo do
|
6
|
+
xml.Item '', fieldname: 'ISVCUSTNO', datatype: 'string',
|
7
|
+
value: @return_value
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.SingTelSDPResponse xmlns: 'SingTelSDPResponse.xsd' do
|
3
|
+
xml.Result returncode: @returncode,
|
4
|
+
returnmessage: SingtelSdp::ReturnCode::RETURN_MESSAGES[@returncode],
|
5
|
+
requestno: @requestno, moreinfo: @moreinfo do
|
6
|
+
xml.Item '', fieldname: 'ISVSUBSID', datatype: 'string',
|
7
|
+
value: @return_value
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.SingTelSDPResponse xmlns: 'SingTelSDPResponse.xsd' do
|
3
|
+
xml.Result returncode: @returncode,
|
4
|
+
returnmessage: SingtelSdp::ReturnCode::RETURN_MESSAGES[@returncode],
|
5
|
+
requestno: @requestno, moreinfo: @moreinfo do
|
6
|
+
xml.Item '', fieldname: 'ISVUSERID', datatype: 'string',
|
7
|
+
value: @return_value
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ivalid session :(
|
@@ -0,0 +1,11 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.SingTelSDPResponse xmlns: 'SingTelSDPResponse.xsd' do
|
3
|
+
xml.Result returncode: @returncode,
|
4
|
+
returnmessage: SingtelSdp::ReturnCode::RETURN_MESSAGES[@returncode],
|
5
|
+
requestno: @requestno, moreinfo: @moreinfo do
|
6
|
+
xml.Data fieldid: 'USAGELICENSE_LIST' do
|
7
|
+
xml.Licenses total: @return_value[:total], assigned: @return_value[:assigned],
|
8
|
+
spare: @return_value[:spare]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.SingTelSDPResponse xmlns: 'SingTelSDPResponse.xsd' do
|
3
|
+
xml.Result returncode: @returncode,
|
4
|
+
returnmessage: SingtelSdp::ReturnCode::RETURN_MESSAGES[@returncode],
|
5
|
+
requestno: @requestno, moreinfo: @moreinfo do
|
6
|
+
xml.Item '', fieldname: 'ISVSUBSID', datatype: 'string',
|
7
|
+
value: @return_value
|
8
|
+
end
|
9
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class SingtelSdpGenerator < Rails::Generators::Base
|
4
|
+
self.source_root([File.expand_path("../../../app/views", __FILE__)])
|
5
|
+
|
6
|
+
desc 'creates the controller and initializer file for SingtelSdp.'
|
7
|
+
def create_all
|
8
|
+
directory 'singtel_sdp', 'app/views'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class SingtelSdpGenerator < Rails::Generators::Base
|
4
|
+
self.source_root([File.expand_path("../../../app/views", __FILE__)])
|
5
|
+
|
6
|
+
desc 'creates the controller and initializer file for SingtelSdp.'
|
7
|
+
def create_singtel_sdp_views
|
8
|
+
directory 'singtel_sdp', 'app/views'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<xs:schema id="SingTelSDPRequest" targetNamespace="SingTelSDPRequest.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
3
|
+
<xs:element name="SingTelSDPRequest">
|
4
|
+
<xs:complexType>
|
5
|
+
<xs:sequence>
|
6
|
+
<xs:element name="HeaderInfo" minOccurs="1" maxOccurs="1">
|
7
|
+
<xs:complexType>
|
8
|
+
<xs:attribute name="userid" type="xs:string" use="required" />
|
9
|
+
<xs:attribute name="password" type="xs:string" use="required" />
|
10
|
+
<xs:attribute name="application" type="xs:string" use="required" />
|
11
|
+
<xs:attribute name="env" type="xs:string" use="required" />
|
12
|
+
<xs:attribute name="adapterversion" type="xs:string" use="required" />
|
13
|
+
<xs:attribute name="createdatetime" type="xs:string" use="required" />
|
14
|
+
<xs:attribute name="requestno" type="xs:string" use="required" />
|
15
|
+
</xs:complexType>
|
16
|
+
</xs:element>
|
17
|
+
<xs:element name="RequestDetail" minOccurs="1" maxOccurs="1">
|
18
|
+
<xs:complexType>
|
19
|
+
<xs:sequence>
|
20
|
+
<xs:element name="Entity" minOccurs="1" maxOccurs="unbounded">
|
21
|
+
<xs:complexType>
|
22
|
+
<xs:sequence>
|
23
|
+
<xs:element name="Item" minOccurs="1" maxOccurs="unbounded">
|
24
|
+
<xs:complexType>
|
25
|
+
<xs:attribute name="fieldname" type="xs:string" use="required" />
|
26
|
+
<xs:attribute name="datatype" type="xs:string" use="required" />
|
27
|
+
<xs:attribute name="value" type="xs:string" use="required" />
|
28
|
+
</xs:complexType>
|
29
|
+
</xs:element>
|
30
|
+
</xs:sequence>
|
31
|
+
<xs:attribute name="name" type="xs:string" use="required" />
|
32
|
+
<xs:attribute name="action" type="xs:string" use="required" />
|
33
|
+
</xs:complexType>
|
34
|
+
</xs:element>
|
35
|
+
</xs:sequence>
|
36
|
+
</xs:complexType>
|
37
|
+
</xs:element>
|
38
|
+
</xs:sequence>
|
39
|
+
</xs:complexType>
|
40
|
+
</xs:element>
|
41
|
+
</xs:schema>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<xs:schema id="SingTelSDPResponse" targetNamespace="SingTelSDPResponse.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
3
|
+
elementFormDefault="qualified">
|
4
|
+
<xs:element name="SingTelSDPResponse">
|
5
|
+
<xs:complexType>
|
6
|
+
<xs:sequence>
|
7
|
+
<xs:element name="Result" minOccurs="1" maxOccurs="1">
|
8
|
+
<xs:complexType>
|
9
|
+
<xs:sequence>
|
10
|
+
<xs:element name="Item" minOccurs="0" maxOccurs="unbounded">
|
11
|
+
<xs:complexType>
|
12
|
+
<xs:attribute name="fieldname" type="xs:string" use="required" />
|
13
|
+
<xs:attribute name="datatype" type="xs:string" use="required" />
|
14
|
+
<xs:attribute name="value" type="xs:string" use="required" />
|
15
|
+
</xs:complexType>
|
16
|
+
</xs:element>
|
17
|
+
</xs:sequence>
|
18
|
+
<xs:attribute name="returncode" type="xs:string" use="required" />
|
19
|
+
<xs:attribute name="returnmessage" type="xs:string" use="required" />
|
20
|
+
<xs:attribute name="moreinfo" type="xs:string" use="required" />
|
21
|
+
<xs:attribute name="requestno" type="xs:string" use="required" />
|
22
|
+
</xs:complexType>
|
23
|
+
</xs:element>
|
24
|
+
</xs:sequence>
|
25
|
+
</xs:complexType>
|
26
|
+
</xs:element>
|
27
|
+
</xs:schema>
|
data/lib/singtel_sdp.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
require "singtel_sdp/engine"
|
2
|
+
require "singtel_sdp/singtel_helper"
|
3
|
+
require "singtel_sdp/rails/routes"
|
4
|
+
|
5
|
+
module SingtelSdp
|
6
|
+
REQUEST_XSD = "#{File.dirname(__FILE__)}/../lib/resources/xsds/SingTelSDPRequest.xsd"
|
7
|
+
RESPONSE_XSD = "#{File.dirname(__FILE__)}/../lib/resources/xsds/SingTelSDPResponse.xsd"
|
8
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'nori'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'hashie'
|
4
|
+
|
5
|
+
module SingtelSdp
|
6
|
+
# This is the url of sdp
|
7
|
+
# !@property mattr_accessor
|
8
|
+
# @returns [String] example: https://marketplace-uat.singtel.com/SSOBalance/
|
9
|
+
mattr_accessor :sdp_url
|
10
|
+
|
11
|
+
# This is the user id that singtel uses to identify in your application
|
12
|
+
# !@property mattr_accessor
|
13
|
+
# @returns [String] example: dropmyemail_singtel_user
|
14
|
+
mattr_accessor :isvuserid
|
15
|
+
|
16
|
+
# This is the password that singtel uses to identify in your application
|
17
|
+
# !@property mattr_accessor
|
18
|
+
# @returns [String] example: 123456
|
19
|
+
mattr_accessor :isvpassword
|
20
|
+
|
21
|
+
# This is the name you gave to singtel for your application.
|
22
|
+
# !@property mattr_accessor
|
23
|
+
# @returns [String] example: dropmyemail.com
|
24
|
+
mattr_accessor :isvapplication
|
25
|
+
|
26
|
+
# This is the current environment of the request.
|
27
|
+
# !@property mattr_accessor
|
28
|
+
# @returns [String] example: UAT
|
29
|
+
mattr_accessor :isvenv
|
30
|
+
|
31
|
+
# This is the version of your adapter.
|
32
|
+
# !@property mattr_accessor
|
33
|
+
# @returns [String] example: 0.1
|
34
|
+
mattr_accessor :isvadapterversion
|
35
|
+
|
36
|
+
def self.setup
|
37
|
+
config = Hashie::Mash.new
|
38
|
+
yield config
|
39
|
+
self.sdp_url = config.sdpurl
|
40
|
+
self.isvuserid = config.isvuserid
|
41
|
+
self.isvpassword = config.isvpassword
|
42
|
+
self.isvapplication = config.isvapplication
|
43
|
+
self.isvenv = config.isvenv
|
44
|
+
self.isvadapterversion = config.isvadapterversion
|
45
|
+
end
|
46
|
+
|
47
|
+
class Engine < ::Rails::Engine
|
48
|
+
initializer 'singtel_sdp starts nori configs' do |app|
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class ActionDispatch::Routing::Mapper
|
2
|
+
def add_singtel_sdp_routes(controller='singtel_sdp/singtel')
|
3
|
+
lambda do
|
4
|
+
scope '/singtel', module: :singtel do
|
5
|
+
match 'adapter', via: :all
|
6
|
+
match 'sso', via: :all
|
7
|
+
get 'invalid_session'
|
8
|
+
end
|
9
|
+
end.call
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
module SingtelSdp
|
3
|
+
class SingtelHelper
|
4
|
+
# This returns the absolute path of the engine whethere you are in the engine or in the host
|
5
|
+
# app.
|
6
|
+
def self.root
|
7
|
+
"#{File.dirname(__FILE__)}/../.."
|
8
|
+
end
|
9
|
+
|
10
|
+
# Validates a user provided OTP against Singtel SSO remote API.
|
11
|
+
# Response is an XML containing either an error or the valid user id.
|
12
|
+
# Returns nil if any network errors occur.
|
13
|
+
#
|
14
|
+
# @param xml [String] SSO request containing OTP
|
15
|
+
# @return [String,nil] XML response for the login attempt, nil on failure.
|
16
|
+
def self.raw_post_to_sdp(xml, url, ssl = true)
|
17
|
+
uri = URI.parse(url)
|
18
|
+
begin
|
19
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
20
|
+
http.use_ssl = ssl
|
21
|
+
request = Net::HTTP::Post.new(uri.path)
|
22
|
+
request.body = xml
|
23
|
+
request['Content-Type'] = 'text/xml'
|
24
|
+
response = http.request(request)
|
25
|
+
response.body
|
26
|
+
rescue => e
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# retrives the content of some xml request and response examples
|
32
|
+
def self.xml_for(filename)
|
33
|
+
File.read("#{root}/spec/fixtures/singtel/samples/#{filename}.xml")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: singtel_sdp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alan Moran
|
8
|
+
- Tomas Rojas
|
9
|
+
- Bruno Nubis
|
10
|
+
- Wong Liang Zan
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2014-10-30 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rails
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '4.1'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.1'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: nokogiri
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: nori
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
type: :runtime
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: haml
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: hashie
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: sqlite3
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: rspec-rails
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
type: :development
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
- !ruby/object:Gem::Dependency
|
115
|
+
name: factory_girl_rails
|
116
|
+
requirement: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
- !ruby/object:Gem::Dependency
|
129
|
+
name: capybara
|
130
|
+
requirement: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
type: :development
|
136
|
+
prerelease: false
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
description: |2
|
143
|
+
Rails 4 engine that provides Singtel's SDP integration points to your rails app.
|
144
|
+
Processes and translates requestes for the standard CRUD actions for Customers, Products, Users and OAuth SSO.
|
145
|
+
email:
|
146
|
+
- zan@dropmysite.com
|
147
|
+
executables: []
|
148
|
+
extensions: []
|
149
|
+
extra_rdoc_files: []
|
150
|
+
files:
|
151
|
+
- app/assets/stylesheets/application.css
|
152
|
+
- app/controllers/singtel_sdp/base_adapter_controller.rb
|
153
|
+
- app/models/singtel_sdp/base_adapter.rb
|
154
|
+
- app/models/singtel_sdp/return_code.rb
|
155
|
+
- app/views/singtel_sdp/base_adapter/create_customer_response.xml.builder
|
156
|
+
- app/views/singtel_sdp/base_adapter/create_product_response.xml.builder
|
157
|
+
- app/views/singtel_sdp/base_adapter/create_user_response.xml.builder
|
158
|
+
- app/views/singtel_sdp/base_adapter/delete_customer_response.xml.builder
|
159
|
+
- app/views/singtel_sdp/base_adapter/delete_product_response.xml.builder
|
160
|
+
- app/views/singtel_sdp/base_adapter/delete_user_response.xml.builder
|
161
|
+
- app/views/singtel_sdp/base_adapter/error_response.xml.builder
|
162
|
+
- app/views/singtel_sdp/base_adapter/invalid_session.html.haml
|
163
|
+
- app/views/singtel_sdp/base_adapter/select_customer_response.xml.builder
|
164
|
+
- app/views/singtel_sdp/base_adapter/update_customer_response.xml.builder
|
165
|
+
- app/views/singtel_sdp/base_adapter/update_product_response.xml.builder
|
166
|
+
- app/views/singtel_sdp/base_adapter/update_user_response.xml.builder
|
167
|
+
- config/routes.rb
|
168
|
+
- lib/generators/singtel_sdp_generator.rb
|
169
|
+
- lib/generators/singtel_sdp_views_generator.rb
|
170
|
+
- lib/resources/xsds/SingTelSDPRequest.xsd
|
171
|
+
- lib/resources/xsds/SingTelSDPResponse.xsd
|
172
|
+
- lib/singtel_sdp/engine.rb
|
173
|
+
- lib/singtel_sdp/rails/routes.rb
|
174
|
+
- lib/singtel_sdp/singtel_helper.rb
|
175
|
+
- lib/singtel_sdp/version.rb
|
176
|
+
- lib/singtel_sdp.rb
|
177
|
+
- lib/tasks/singtel_sdp_tasks.rake
|
178
|
+
- LICENSE
|
179
|
+
- Rakefile
|
180
|
+
- README.md
|
181
|
+
homepage: https://github.com/dropmyemail/singtel_sdp
|
182
|
+
licenses: []
|
183
|
+
metadata: {}
|
184
|
+
post_install_message:
|
185
|
+
rdoc_options: []
|
186
|
+
require_paths:
|
187
|
+
- lib
|
188
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - '>='
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
requirements: []
|
199
|
+
rubyforge_project:
|
200
|
+
rubygems_version: 2.0.14
|
201
|
+
signing_key:
|
202
|
+
specification_version: 4
|
203
|
+
summary: Provides Singtel's SDP integration points to your rails app
|
204
|
+
test_files: []
|