restful-userprofiles 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ 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: []