restful-userprofiles 0.0.4

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
+ SHA1:
3
+ metadata.gz: 2f30bbf64754a1548562bef94a07f7ace2f54256
4
+ data.tar.gz: 4e16651bad36f01220f99b810cdb61ac69c8b40c
5
+ SHA512:
6
+ metadata.gz: 88efbbe093e93e4222261b8357ee7fb847642403233b1d89db02ad4696bebb9b2076c892c11500c2e11d5f93169e8d23283f300a15529c335529d2a715310fa7
7
+ data.tar.gz: 0c9b5717fa704c7730b78c69ab46d2835f154a94c72fae370dc7c89e5bb5b271b701b0c19a54f0861194e256a392d7908ee2751c33b6655b4ebbab9b5da94e35
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # ######################################################################## #
5
+ #
6
+ # Main module/entry file for the UserProfiles Microservice
7
+ #
8
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
9
+ #
10
+ # ######################################################################## #
11
+
12
+
13
+ # ##########################################################################
14
+ # requires
15
+
16
+ require 'razor_risk/cassini/diagnostics/zeroth_include'
17
+
18
+ require 'razor_risk/cassini/applications/microservices/restful/user_profiles'
19
+ require 'razor_risk/cassini/main'
20
+
21
+ # TODO: This needs to be added to cassini/main
22
+ require 'razor_risk/cassini/common/version'
23
+
24
+
25
+ # ##########################################################################
26
+ # includes
27
+
28
+ include ::RazorRisk::Cassini::Applications::Microservices::RESTful
29
+
30
+
31
+ # ##########################################################################
32
+ # constants
33
+
34
+ PROGRAM_VERSION = UserProfiles::VERSION
35
+
36
+
37
+ # ##########################################################################
38
+ # main section
39
+
40
+ TheApp = UserProfiles::UserProfilesApp
41
+
42
+
43
+ # ############################## end of file ############################# #
44
+
45
+
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # ######################################################################## #
5
+ #
6
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
7
+ #
8
+ # ######################################################################## #
9
+
10
+
11
+ # ##########################################################################
12
+ # requires
13
+
14
+ require 'razor_risk/cassini/applications/rest_framework/route_verb_dispatcher'
15
+ require 'razor_risk/cassini/applications/route_verb_adaptors/user_profiles'
16
+ require 'razor_risk/cassini/applications/secured_microservice'
17
+
18
+ require 'razor_risk/cassini/mixin/razor_response_validator'
19
+
20
+ require 'pantheios'
21
+
22
+
23
+ # ##########################################################################
24
+ # modules
25
+
26
+ module RazorRisk
27
+ module Cassini
28
+ module Applications
29
+ module Microservices
30
+ module RESTful
31
+ module UserProfiles
32
+
33
+
34
+ # ##########################################################################
35
+ # includes
36
+
37
+
38
+ # ##########################################################################
39
+ # application
40
+
41
+ # Sinatra Application for the UserProfiles Microservice.
42
+ class UserProfilesApp < SecuredMicroservice
43
+
44
+ # ##########################################################
45
+ # includes
46
+
47
+ include Cassini::Applications::RouteVerbAdaptors::UserProfiles
48
+ include Cassini::Applications::RESTFramework::RouteVerbDispatch
49
+ include Cassini::Mixin::RazorResponseValidator
50
+
51
+ include ::Pantheios
52
+
53
+
54
+ # ##########################################################
55
+ # Constants
56
+
57
+ FULL_DESIGNATION = 'UserProfiles'
58
+ SHORT_DESIGNATION = 'user_profiles'
59
+ SERVICE_TYPE = :microservice
60
+ PROGRAM_FEATURES = {
61
+ has_web_server: true,
62
+ has_host_and_port: true,
63
+ has_razor_connectivity: true,
64
+ authentication: true,
65
+ copyright_year: 2019,
66
+ }
67
+ SUPPORTED_ROUTES = [
68
+ ]
69
+ HTTP_ACCEPTS = %w{
70
+ text/html
71
+ application/json
72
+ application/xml
73
+ text/xml
74
+ text/csv
75
+ text/plain
76
+ text/tab-separated-values
77
+ text/tsv
78
+ }
79
+
80
+
81
+ # ##########################################################
82
+ # methods
83
+
84
+ def self.on_init_service options
85
+
86
+ trace ParamNames[ :options ], options
87
+
88
+ raise ArgumentError.new(
89
+ 'missing keyword: razor_requester'
90
+ ) unless options.has_key? :razor_requester
91
+
92
+ request_options = options[:request_options]
93
+
94
+ set :razor_requester, options[:razor_requester]
95
+ set :request_options, request_options
96
+ end
97
+
98
+
99
+ # ##########################################################
100
+ # routes
101
+
102
+ put '/:id/custom-details/:name/?' do
103
+
104
+ trace ParamNames[ :request, :params ], request, params
105
+
106
+ dispatch CustomDetailPut
107
+ end
108
+
109
+ get '/:id/custom-details/:name/?' do
110
+
111
+ trace ParamNames[ :request, :params ], request, params
112
+
113
+ dispatch CustomDetailGet
114
+ end
115
+
116
+ get '/:id/?' do
117
+
118
+ trace ParamNames[ :request, :params ], request, params
119
+
120
+ dispatch ItemGet
121
+ end
122
+
123
+ get '/' do
124
+
125
+ trace ParamNames[ :request, :params ], request, params
126
+
127
+ dispatch CollectionGet
128
+ end
129
+
130
+
131
+ # ##########################################################
132
+ # catch-all hook
133
+
134
+ define_catch_all_handlers
135
+
136
+ end # class App
137
+
138
+
139
+ # ##########################################################################
140
+ # modules
141
+
142
+ end # module UserProfiles
143
+ end # module RESTful
144
+ end # module Microservices
145
+ end # module Applications
146
+ end # module Cassini
147
+ end # module RazorRisk
148
+
149
+ # ############################## end of file ############################# #
150
+
151
+
@@ -0,0 +1,47 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ #
5
+ # Version for RazorRisk.Cassini.Microservices.RESTful.UserProfiles library
6
+ #
7
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
8
+ #
9
+ # ######################################################################## #
10
+
11
+ module RazorRisk
12
+ module Cassini
13
+ module Applications
14
+ module Microservices
15
+ module RESTful
16
+
17
+ module UserProfiles
18
+
19
+ # Current version of the RazorRisk.Cassini.Microservices.RESTful.UserProfiles library
20
+ VERSION = '0.0.4'
21
+
22
+ private
23
+ VERSION_PARTS_ = VERSION.split(/[.]/).collect { |n| n.to_i }
24
+ public
25
+ # Major version of the RazorRisk.Cassini.Microservices.RESTful.UserProfiles library
26
+ VERSION_MAJOR = VERSION_PARTS_[0]
27
+ # Minor version of the RazorRisk.Cassini.Microservices.RESTful.UserProfiles library
28
+ VERSION_MINOR = VERSION_PARTS_[1]
29
+ # Patch version of the RazorRisk.Cassini.Microservices.RESTful.UserProfiles library
30
+ VERSION_PATCH = VERSION_PARTS_[2]
31
+ # Commit version of the RazorRisk.Cassini.Microservices.RESTful.UserProfiles library
32
+ VERSION_COMMIT = VERSION_PARTS_[3] || 0
33
+
34
+
35
+ # The description of the framework
36
+ DESCRIPTION = "Razor Risk's Cassini Web-framework's UserProfiles RESTful microservice"
37
+ end # module UserProfiles
38
+
39
+ end # module RESTful
40
+ end # module Microservices
41
+ end # module Applications
42
+ end # module Cassini
43
+ end # module RazorRisk
44
+
45
+ # ############################## end of file ############################# #
46
+
47
+
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ # ##########################################################################
4
+ #
5
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
6
+ #
7
+ # ##########################################################################
8
+
9
+
10
+ # ##########################################################
11
+ # requires
12
+
13
+ require 'razor_risk/cassini/applications/microservices/restful/user_profiles/app'
14
+ require 'razor_risk/cassini/applications/microservices/restful/user_profiles/version'
15
+
16
+
17
+ # ############################## end of file ############################# #
18
+
19
+
@@ -0,0 +1,137 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ #
5
+ # Adaptor for UserProfiles microservice's collection GET verb
6
+ #
7
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
8
+ #
9
+ # ######################################################################## #
10
+
11
+
12
+ # ##########################################################################
13
+ # requires
14
+
15
+ require 'razor_risk/cassini/applications/rest_framework/verb_handler'
16
+ require 'razor_risk/cassini/mixin/razor_response_validator'
17
+ require 'razor_risk/cassini/util/conversion_util'
18
+
19
+ require 'razor_risk/razor/connectivity/razor_3/entity_connectors/user_profiles_connector'
20
+ require 'razor_risk/core/diagnostics/logger'
21
+
22
+ # ##########################################################################
23
+ # module
24
+
25
+ module RazorRisk
26
+ module Cassini
27
+ module Applications
28
+ module RouteVerbAdaptors
29
+ module UserProfiles
30
+
31
+
32
+ # ##########################################################################
33
+ # classes
34
+
35
+ class CollectionGet < RESTFramework::VerbHandler
36
+
37
+ # ##########################################################
38
+ # includes
39
+
40
+ include Cassini::Mixin::RazorResponseValidator
41
+ include Cassini::Util::ConversionUtil
42
+
43
+ include Razor::Connectivity::Razor3::EntityConnectors
44
+ include ::RazorRisk::Core::Diagnostics::Logger
45
+
46
+ # ##########################################################
47
+ # Constants
48
+
49
+ public
50
+ HTTP_VERB = :get
51
+ HTTP_ACCEPTS = [
52
+ 'application/xml',
53
+ 'application/json',
54
+ 'text/xml',
55
+ ]
56
+ QUERY_PARAMETERS = []
57
+ ROUTE_VARIABLES = []
58
+
59
+
60
+ # ##########################################################
61
+ # methods
62
+
63
+ def initialize *args, **options
64
+
65
+ @connector_class = options[:connector_class] || UserProfilesConnector
66
+ super
67
+ end
68
+
69
+ def handle env, params, request, response
70
+
71
+ trace(
72
+ ParamNames[ :env, :params, :request, :response ],
73
+ env, params, request, response
74
+ )
75
+
76
+ ec = @connector_class.new(
77
+ settings.razor_requester,
78
+ credentials: get_required_credentials,
79
+ )
80
+
81
+ qr = ec.get_user_profiles indicate_result_by: :qualified_result
82
+ log :debug1, "qr(#{qr.class})='#{qr}'"
83
+
84
+ validate_qualified_razor_response qr
85
+
86
+ unless qr.succeeded?
87
+ if qr.result.nil?
88
+ error(
89
+ HTTP_STATUS_NAMES::NOT_FOUND,
90
+ 'User Profiles could not be found'
91
+ )
92
+ else
93
+ log :warning, 'Failed to retrieve User Profiles for an unkown reason'
94
+ error(
95
+ HTTP_STATUS_NAMES::INTERNAL_SERVER_ERROR,
96
+ 'Oops! Something went wrong'
97
+ )
98
+ end
99
+ end
100
+
101
+ status HTTP_STATUS_NAMES::OK
102
+
103
+ if request.accept?('application/xml')
104
+ log :debug1, 'application/xml'
105
+ content_type 'application/xml'
106
+ qr.result.to_s
107
+ elsif request.accept?('text/xml')
108
+ log :debug1, 'text/xml'
109
+ content_type 'text/xml'
110
+ qr.result.to_s
111
+ elsif request.accept?('application/json')
112
+ log :debug1, 'application/json'
113
+ content_type 'application/json'
114
+ convert_XML_to_JSON qr.result, { scheme: :gdata }
115
+ else
116
+ log :violation, "unexpected failure to match given 'Accept' header '#{request.accept}'"
117
+ error(
118
+ HTTP_STATUS_NAMES::INTERNAL_SERVER_ERROR,
119
+ 'Oops! Something went wrong'
120
+ )
121
+ end
122
+ end
123
+ end # class CollectionGet
124
+
125
+
126
+ # ##########################################################################
127
+ # module
128
+
129
+ end # module UserProfiles
130
+ end # module RouteVerbAdaptors
131
+ end # module Applications
132
+ end # module Cassini
133
+ end # module RazorRisk
134
+
135
+ # ############################## end of file ############################# #
136
+
137
+
@@ -0,0 +1,183 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ #
5
+ # Adaptor for UserProfiles microservice's item GET verb
6
+ #
7
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
8
+ #
9
+ # ######################################################################## #
10
+
11
+
12
+ # ##########################################################################
13
+ # requires
14
+
15
+ require 'razor_risk/cassini/applications/rest_framework/verb_handler'
16
+ require 'razor_risk/cassini/mixin/razor_response_validator'
17
+ require 'razor_risk/cassini/util/conversion_util'
18
+
19
+ require 'razor_risk/razor/connectivity/razor_3/entity_connectors/user_profiles_connector'
20
+ require 'razor_risk/core/diagnostics/logger'
21
+
22
+ require 'base64'
23
+ require 'json'
24
+
25
+
26
+ # ##########################################################################
27
+ # module
28
+
29
+ module RazorRisk
30
+ module Cassini
31
+ module Applications
32
+ module RouteVerbAdaptors
33
+ module UserProfiles
34
+
35
+
36
+ # ##########################################################################
37
+ # classes
38
+
39
+ class CustomDetailGet < RESTFramework::VerbHandler
40
+
41
+ # ##########################################################
42
+ # includes
43
+
44
+ include Cassini::Mixin::RazorResponseValidator
45
+ include Cassini::Util::ConversionUtil
46
+
47
+ include Razor::Connectivity::Razor3::EntityConnectors
48
+ include ::RazorRisk::Core::Diagnostics::Logger
49
+
50
+ # ##########################################################
51
+ # Constants
52
+
53
+ public
54
+ HTTP_VERB = :get
55
+ HTTP_ACCEPTS = [
56
+ 'text/plain',
57
+ ]
58
+ QUERY_PARAMETERS = []
59
+ ROUTE_VARIABLES = [
60
+ 'id',
61
+ 'name',
62
+ ]
63
+
64
+
65
+ # ##########################################################
66
+ # methods
67
+
68
+ def initialize *args, **options
69
+
70
+ @connector_class = options[:connector_class] || UserProfilesConnector
71
+ super
72
+ end
73
+
74
+ def handle env, params, request, response
75
+
76
+ trace(
77
+ ParamNames[ :env, :params, :request, :response ],
78
+ env, params, request, response
79
+ )
80
+
81
+ user_id = check_option(
82
+ params,
83
+ 'id',
84
+ strip_str_whitespace: true,
85
+ reject_empty: true,
86
+ nothrow: true,
87
+ ) || error(
88
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
89
+ 'Invalid User ID'
90
+ )
91
+
92
+ detail_name = check_option(
93
+ params,
94
+ 'name',
95
+ strip_str_whitespace: true,
96
+ reject_empty: true,
97
+ nothrow: true,
98
+ ) || error(
99
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
100
+ 'Invalid Detail Name'
101
+ )
102
+
103
+ # FIXME: Validate that all characters in the User ID and Detail Name are
104
+ # alphanumerics, spaces, or underscores.
105
+ #
106
+ # This check is temporary and does not grantee SQL safety. This
107
+ # must be addressed as a larger issue around sanitization of user
108
+ # inputs to Razor.
109
+ settings.razor_requester.stopgap_sql_string_validator_fix_me user_id do
110
+ error(
111
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
112
+ 'User ID contained invalid characters, may only be alphanumerics, spaces, or underscores.'
113
+ )
114
+ end
115
+ settings.razor_requester.stopgap_sql_string_validator_fix_me detail_name do
116
+ error(
117
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
118
+ 'Detail Name contained invalid characters, may only be alphanumerics, spaces, or underscores.'
119
+ )
120
+ end
121
+
122
+ ec = @connector_class.new(
123
+ settings.razor_requester,
124
+ credentials: get_required_credentials,
125
+ )
126
+
127
+ # Send update
128
+ qr = ec.get_custom_detail(
129
+ user_id,
130
+ detail_name,
131
+ indicate_result_by: :qualified_result,
132
+ )
133
+ log :debug1, "qr(#{qr.class})='#{qr}'"
134
+
135
+ validate_qualified_razor_response qr
136
+
137
+ if !qr.succeeded? and qr.result.nil?
138
+ error(
139
+ HTTP_STATUS_NAMES::NOT_FOUND,
140
+ "Detail #{detail_name} for profile #{user_id} could not be found"
141
+ )
142
+ end
143
+
144
+ detail = decode_ qr.result.text
145
+
146
+ status HTTP_STATUS_NAMES::OK
147
+
148
+ if request.accept?('text/plain')
149
+ log :debug1, 'text/plain'
150
+ content_type 'text/plain'
151
+ detail
152
+ else
153
+ log :violation, "unexpected failure to match given 'Accept' header '#{request.accept}'"
154
+ error(
155
+ HTTP_STATUS_NAMES::INTERNAL_SERVER_ERROR,
156
+ 'Oops! Something went wrong'
157
+ )
158
+ end
159
+ end
160
+
161
+ private
162
+ # Checks if the string is base 64 encoded and returns the decoded string.
163
+ def decode_ value
164
+ decoded = Base64.decode64(value)
165
+ reencoded = Base64.encode64(decoded)
166
+
167
+ reencoded.chomp == value.chomp ? decoded : value
168
+ end
169
+ end # class CustomDetailPut
170
+
171
+
172
+ # ##########################################################################
173
+ # module
174
+
175
+ end # module UserProfiles
176
+ end # module RouteVerbAdaptors
177
+ end # module Applications
178
+ end # module Cassini
179
+ end # module RazorRisk
180
+
181
+ # ############################## end of file ############################# #
182
+
183
+
@@ -0,0 +1,210 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ #
5
+ # Adaptor for UserProfiles microservice's custom details put verb
6
+ #
7
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
8
+ #
9
+ # ######################################################################## #
10
+
11
+
12
+ # ##########################################################################
13
+ # requires
14
+
15
+ require 'razor_risk/cassini/applications/rest_framework/verb_handler'
16
+ require 'razor_risk/cassini/mixin/razor_response_validator'
17
+ require 'razor_risk/cassini/util/conversion_util'
18
+
19
+ require 'razor_risk/razor/connectivity/razor_3/entity_connectors/user_profiles_connector'
20
+ require 'razor_risk/core/diagnostics/logger'
21
+
22
+ require 'base64'
23
+
24
+
25
+ # ##########################################################################
26
+ # module
27
+
28
+ module RazorRisk
29
+ module Cassini
30
+ module Applications
31
+ module RouteVerbAdaptors
32
+ module UserProfiles
33
+
34
+
35
+ # ##########################################################################
36
+ # classes
37
+
38
+ class CustomDetailPut < RESTFramework::VerbHandler
39
+
40
+ # ##########################################################
41
+ # includes
42
+
43
+ include Cassini::Mixin::RazorResponseValidator
44
+ include Cassini::Util::ConversionUtil
45
+
46
+ include Razor::Connectivity::Razor3::EntityConnectors
47
+ include ::RazorRisk::Core::Diagnostics::Logger
48
+
49
+ # ##########################################################
50
+ # Constants
51
+
52
+ public
53
+ HTTP_VERB = :put
54
+ HTTP_ACCEPTS = [
55
+ 'application/xml',
56
+ 'application/json',
57
+ 'text/xml',
58
+ ]
59
+ QUERY_PARAMETERS = []
60
+ ROUTE_VARIABLES = [
61
+ 'id',
62
+ 'name',
63
+ ]
64
+
65
+
66
+ # ##########################################################
67
+ # methods
68
+
69
+ def initialize *args, **options
70
+
71
+ @connector_class = options[:connector_class] || UserProfilesConnector
72
+ super
73
+ end
74
+
75
+ def handle env, params, request, response
76
+
77
+ trace(
78
+ ParamNames[ :env, :params, :request, :response ],
79
+ env, params, request, response
80
+ )
81
+
82
+ user_id = check_option(
83
+ params,
84
+ 'id',
85
+ strip_str_whitespace: true,
86
+ reject_empty: true,
87
+ nothrow: true,
88
+ ) || error(
89
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
90
+ 'Invalid User ID'
91
+ )
92
+
93
+ detail_name = check_option(
94
+ params,
95
+ 'name',
96
+ strip_str_whitespace: true,
97
+ reject_empty: true,
98
+ nothrow: true,
99
+ ) || error(
100
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
101
+ 'Invalid Detail Name'
102
+ )
103
+
104
+ # FIXME: Validate that all characters in the User ID and Detail Name are
105
+ # alphanumerics, spaces, or underscores.
106
+ #
107
+ # This check is temporary and does not grantee SQL safety. This
108
+ # must be addressed as a larger issue around sanitization of user
109
+ # inputs to Razor.
110
+ settings.razor_requester.stopgap_sql_string_validator_fix_me user_id do
111
+ error(
112
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
113
+ 'User ID contained invalid characters, may only be alphanumerics, spaces, or underscores.'
114
+ )
115
+ end
116
+ settings.razor_requester.stopgap_sql_string_validator_fix_me detail_name do
117
+ error(
118
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
119
+ 'Detail Name contained invalid characters, may only be alphanumerics, spaces, or underscores.'
120
+ )
121
+ end
122
+
123
+ # Get the body content
124
+ request.body.rewind
125
+ body_text = request.body.read
126
+ detail_value = Base64.encode64(body_text)
127
+
128
+ ec = @connector_class.new(
129
+ settings.razor_requester,
130
+ credentials: get_required_credentials,
131
+ )
132
+
133
+ # Get existing profile
134
+ qr = ec.get_user_profile(
135
+ user_id,
136
+ indicate_result_by: :qualified_result,
137
+ )
138
+ log :debug1, "qr(#{qr.class})='#{qr}'"
139
+
140
+ validate_qualified_razor_response qr
141
+
142
+ unless qr.succeeded?
143
+ if qr.result.nil?
144
+ error(
145
+ HTTP_STATUS_NAMES::NOT_FOUND,
146
+ 'User Profile could not be found'
147
+ )
148
+ else
149
+ log :warning, "Failed to retrieve User Profile for '#{user_id}' for an unkown reason."
150
+ error(
151
+ HTTP_STATUS_NAMES::INTERNAL_SERVER_ERROR,
152
+ 'Oops! Something went wrong'
153
+ )
154
+ end
155
+ end
156
+
157
+ # Updated profile XML with detail
158
+ profile = qr.result
159
+ details = profile.at_xpath('customDetails')
160
+ unless details
161
+ ::Nokogiri::XML::Builder.with(profile) { |xml| xml.customDetails }
162
+ details = profile.at_xpath('customDetails')
163
+ end
164
+
165
+ detail = details.at_xpath("customDetail[@name='#{detail_name}']")
166
+ unless detail
167
+ ::Nokogiri::XML::Builder.with(details) do |xml|
168
+ xml.customDetail name: detail_name
169
+ end
170
+ detail = details.at_xpath("customDetail[@name='#{detail_name}']")
171
+ end
172
+ detail.content = detail_value
173
+
174
+ # Send update
175
+ qr = ec.update_user_profile(
176
+ user_id,
177
+ profile,
178
+ indicate_result_by: :qualified_result,
179
+ )
180
+ log :debug1, "qr(#{qr.class})='#{qr}'"
181
+
182
+ validate_qualified_razor_response qr
183
+
184
+ unless qr.succeeded?
185
+ log :warning, "Failed to update User Profile for '#{user_id}' for an unknown reason"
186
+ error(
187
+ HTTP_STATUS_NAMES::INTERNAL_SERVER_ERROR,
188
+ 'Oops! Something went wrong!'
189
+ )
190
+ end
191
+
192
+ status 202
193
+
194
+ nil
195
+ end
196
+ end # class CustomDetailPut
197
+
198
+
199
+ # ##########################################################################
200
+ # module
201
+
202
+ end # module UserProfiles
203
+ end # module RouteVerbAdaptors
204
+ end # module Applications
205
+ end # module Cassini
206
+ end # module RazorRisk
207
+
208
+ # ############################## end of file ############################# #
209
+
210
+
@@ -0,0 +1,159 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ #
5
+ # Adaptor for UserProfiles microservice's item GET verb
6
+ #
7
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
8
+ #
9
+ # ######################################################################## #
10
+
11
+
12
+ # ##########################################################################
13
+ # requires
14
+
15
+ require 'razor_risk/cassini/applications/rest_framework/verb_handler'
16
+ require 'razor_risk/cassini/mixin/razor_response_validator'
17
+ require 'razor_risk/cassini/util/conversion_util'
18
+
19
+ require 'razor_risk/razor/connectivity/razor_3/entity_connectors/user_profiles_connector'
20
+ require 'razor_risk/core/diagnostics/logger'
21
+
22
+ # ##########################################################################
23
+ # module
24
+
25
+ module RazorRisk
26
+ module Cassini
27
+ module Applications
28
+ module RouteVerbAdaptors
29
+ module UserProfiles
30
+
31
+
32
+ # ##########################################################################
33
+ # classes
34
+
35
+ class ItemGet < RESTFramework::VerbHandler
36
+
37
+ # ##########################################################
38
+ # includes
39
+
40
+ include Cassini::Mixin::RazorResponseValidator
41
+ include Cassini::Util::ConversionUtil
42
+
43
+ include Razor::Connectivity::Razor3::EntityConnectors
44
+ include ::RazorRisk::Core::Diagnostics::Logger
45
+
46
+ # ##########################################################
47
+ # Constants
48
+
49
+ public
50
+ HTTP_VERB = :get
51
+ HTTP_ACCEPTS = [
52
+ 'application/xml',
53
+ 'application/json',
54
+ 'text/xml',
55
+ ]
56
+ QUERY_PARAMETERS = []
57
+ ROUTE_VARIABLES = [ 'id' ]
58
+
59
+
60
+ # ##########################################################
61
+ # methods
62
+
63
+ def initialize *args, **options
64
+
65
+ @connector_class = options[:connector_class] || UserProfilesConnector
66
+ super
67
+ end
68
+
69
+ def handle env, params, request, response
70
+
71
+ trace(
72
+ ParamNames[ :env, :params, :request, :response ],
73
+ env, params, request, response
74
+ )
75
+
76
+ user_id = check_option(
77
+ params,
78
+ 'id',
79
+ strip_str_whitespace: true,
80
+ reject_empty: true,
81
+ nothrow: true,
82
+ ) || error(HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY, "Invalid User ID")
83
+
84
+ # FIXME: Validate that all characters in the User ID are alphanumerics,
85
+ # spaces, or underscores.
86
+ #
87
+ # This check is temporary and does not grantee SQL safety. This
88
+ # must be addressed as a larger issue around sanitization of user
89
+ # inputs to Razor.
90
+ settings.razor_requester.stopgap_sql_string_validator_fix_me user_id do
91
+ error(
92
+ HTTP_STATUS_NAMES::UNPROCESSABLE_ENTITY,
93
+ 'User ID contained invalid characters, may only be alphanumerics, spaces, or underscores.'
94
+ )
95
+ end
96
+
97
+ ec = @connector_class.new(
98
+ settings.razor_requester,
99
+ credentials: get_required_credentials,
100
+ )
101
+
102
+ qr = ec.get_user_profile(
103
+ user_id,
104
+ indicate_result_by: :qualified_result,
105
+ )
106
+ log :debug1, "qr(#{qr.class})='#{qr}'"
107
+
108
+ validate_qualified_razor_response qr
109
+
110
+ unless qr.succeeded?
111
+ if qr.result.nil?
112
+ error HTTP_STATUS_NAMES::NOT_FOUND, 'User Profile could not be found'
113
+ else
114
+ reasons = qr.failure_qualifier.reasons.join("\n")
115
+ log :warning, "Failed to retrieve User Profile for '#{user_id}'; #{reasons}"
116
+ error(
117
+ HTTP_STATUS_NAMES::INTERNAL_SERVER_ERROR,
118
+ 'Oops! Something went wrong'
119
+ )
120
+ end
121
+ end
122
+
123
+ status HTTP_STATUS_NAMES::OK
124
+
125
+ if request.accept?('application/xml')
126
+ log :debug1, 'application/xml'
127
+ content_type 'application/xml'
128
+ qr.result.to_s
129
+ elsif request.accept?('text/xml')
130
+ log :debug1, 'text/xml'
131
+ content_type 'text/xml'
132
+ qr.result.to_s
133
+ elsif request.accept?('application/json')
134
+ log :debug1, 'application/json'
135
+ content_type 'application/json'
136
+ convert_XML_to_JSON qr.result, { scheme: :gdata }
137
+ else
138
+ log :violation, "unexpected failure to match given 'Accept' header '#{request.accept}'"
139
+ error(
140
+ HTTP_STATUS_NAMES::INTERNAL_SERVER_ERROR,
141
+ 'Oops! Something went wrong'
142
+ )
143
+ end
144
+ end
145
+ end # class ItemGet
146
+
147
+
148
+ # ##########################################################################
149
+ # module
150
+
151
+ end # module UserProfiles
152
+ end # module RouteVerbAdaptors
153
+ end # module Applications
154
+ end # module Cassini
155
+ end # module RazorRisk
156
+
157
+ # ############################## end of file ############################# #
158
+
159
+
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ # ##########################################################################
4
+ #
5
+ # Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
6
+ #
7
+ # ##########################################################################
8
+
9
+
10
+ # ##########################################################
11
+ # requires
12
+
13
+ require 'razor_risk/cassini/applications/route_verb_adaptors/user_profiles/collection_get'
14
+ require 'razor_risk/cassini/applications/route_verb_adaptors/user_profiles/item_get'
15
+ require 'razor_risk/cassini/applications/route_verb_adaptors/user_profiles/custom_detail_put'
16
+ require 'razor_risk/cassini/applications/route_verb_adaptors/user_profiles/custom_detail_get'
17
+
18
+
19
+ # ############################## end of file ############################# #
20
+
21
+
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: restful-userprofiles
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Razor Risk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: razorrisk-cassini-common
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.26.24
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '1.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.26.24
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: razorrisk-razor-connectivity
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.14.4
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '1.0'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 0.14.4
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '1.0'
53
+ - !ruby/object:Gem::Dependency
54
+ name: razorrisk-razor-connectivity-entityconnectors
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.26.14
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 0.26.14
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '1.0'
73
+ - !ruby/object:Gem::Dependency
74
+ name: nokogiri
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '1.6'
80
+ type: :runtime
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '1.6'
87
+ - !ruby/object:Gem::Dependency
88
+ name: pantheios-ruby
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: 0.20.2
94
+ type: :runtime
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: 0.20.2
101
+ - !ruby/object:Gem::Dependency
102
+ name: xqsr3
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '0.30'
108
+ type: :runtime
109
+ prerelease: false
110
+ version_requirements: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '0.30'
115
+ - !ruby/object:Gem::Dependency
116
+ name: json
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '1.8'
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 1.8.3
125
+ type: :runtime
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.8'
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: 1.8.3
135
+ description: Razor Risk's Cassini Web-framework's UserProfiles RESTful microservice
136
+ email: operations@razor-risk.com
137
+ executables:
138
+ - razorrisk-microservice-userprofiles
139
+ extensions: []
140
+ extra_rdoc_files: []
141
+ files:
142
+ - bin/razorrisk-microservice-userprofiles
143
+ - lib/razor_risk/cassini/applications/microservices/restful/user_profiles.rb
144
+ - lib/razor_risk/cassini/applications/microservices/restful/user_profiles/app.rb
145
+ - lib/razor_risk/cassini/applications/microservices/restful/user_profiles/version.rb
146
+ - lib/razor_risk/cassini/applications/route_verb_adaptors/user_profiles.rb
147
+ - lib/razor_risk/cassini/applications/route_verb_adaptors/user_profiles/collection_get.rb
148
+ - lib/razor_risk/cassini/applications/route_verb_adaptors/user_profiles/custom_detail_get.rb
149
+ - lib/razor_risk/cassini/applications/route_verb_adaptors/user_profiles/custom_detail_put.rb
150
+ - lib/razor_risk/cassini/applications/route_verb_adaptors/user_profiles/item_get.rb
151
+ homepage: https://razor-risk.com/
152
+ licenses:
153
+ - Nonstandard
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - "~>"
162
+ - !ruby/object:Gem::Version
163
+ version: '2.0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.6.14
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Razor Risk Cassini User Profiles RESTful microservice
175
+ test_files: []