morpho 1.1.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e6a96107096cf61bdcd55849c2bbad3d5c27c085bac23afd061fab4fb508b86
4
- data.tar.gz: 7c061fe271965fc176adde62d3856f343b9e9605ab1e0a7cb096d78d8d78409c
3
+ metadata.gz: 82024952461a4e2bd7809b6490d89a95ea14ffbdb09bf0eb48f38293195a77d3
4
+ data.tar.gz: 3f7ddb7bdb31f77544040cc6b6b7576fd6ec2536f88cc66bcbe9e2c4b8ca0065
5
5
  SHA512:
6
- metadata.gz: f6f6c509deaafd28182fd49d91fc8255aa9d52675753150d0e028e1efb698956131884f2b609c5aac80770eb74996aa47b538c2edc0ee46b52b0d415002047e3
7
- data.tar.gz: 45d6a0a2a2aaf7551453373c40ef750c90a3f5f3caf7fa32c6124fdb45baaa5b38249e8c382be7511fa6f03d39c25922b4b4733dd77d8c6bb8b39d0f38b3a8aa
6
+ metadata.gz: 9accfa9064d5a4d9cfcc2110c107007a8fe511c6847bdb368206d2f57caf5e8549c08e1fbed88b47ed61661ee3eb2deae199196a14955db7f0f829382e469202
7
+ data.tar.gz: 60ed2c1e0f7fed8363d114ff1d98801455b02ad5f9c627e2b6f098b0443dfdbd6352c9001f565257924a7cd91992a6637bc542b7d325f4bede7533daf4ad7254
@@ -1,8 +1,27 @@
1
1
  module Morpho
2
2
  module Entities
3
3
  class Error < ::Grape::Entity
4
- expose :message, documentation: { type: 'string', desc: 'Error standard message', required: true }
5
- expose :errors, safe: true, documentation: { type: 'object', desc: 'Error message details' }
4
+ expose :errors, safe: true, documentation: { type: 'array', desc: 'Error message details' }
5
+
6
+ def errors
7
+ messages = []
8
+
9
+ keys = object.errors.keys
10
+
11
+ keys.each do |key|
12
+ messages << {
13
+ field_name: key,
14
+ messages: object.errors.messages[key]
15
+ }
16
+ end
17
+
18
+ messages << {
19
+ field_name: 'base',
20
+ messages: [ object.message ]
21
+ } if messages.empty?
22
+
23
+ messages
24
+ end
6
25
  end
7
26
  end
8
27
  end
@@ -0,0 +1,19 @@
1
+ module Morpho
2
+ module Exceptions
3
+ class StandardError < ::StandardError
4
+ attr_reader :status
5
+ attr_reader :message
6
+ attr_reader :errors
7
+
8
+ def initialize(*args)
9
+ options = args.extract_options!
10
+
11
+ @status = options[:status] || 422
12
+ @message = options[:message] || I18n.t("morpho.api.messages.general.#{@status}")
13
+ @errors = options[:errors] || {}
14
+
15
+ super(@message)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ module Morpho
2
+ module Formatters
3
+ module StandardError
4
+ class << self
5
+ def call(message, backtrace, options, env, original_exception)
6
+ if message.is_a?(String)
7
+ result = {
8
+ message: message,
9
+ errors: [
10
+ { field_name: 'base', messages: [ message ] }
11
+ ]
12
+ }
13
+ elsif message.is_a?(Hash)
14
+ result = message
15
+ elsif message.is_a?(Object)
16
+ return message.to_json if message.respond_to?(:to_json)
17
+
18
+ result = message
19
+ end
20
+
21
+ ::Grape::Json.dump(result)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -3,76 +3,52 @@ module Morpho
3
3
  module HTTPResponses
4
4
  protected
5
5
 
6
- def render_bad_request(errors = {})
7
- error!({
8
- message: I18n.t('morpho.api.messages.bad_request'),
9
- errors: errors,
10
- with: Morpho::Entities::Error
11
- }, 400)
6
+ def render_bad_request
7
+ raise Morpho::Exceptions::StandardError.new(
8
+ status: 400
9
+ )
12
10
  end
13
11
 
14
- def render_unauthorized(errors = {})
15
- error!({
16
- message: I18n.t('morpho.api.messages.unauthorized'),
17
- errors: errors,
18
- with: Morpho::Entities::Error
19
- }, 401)
12
+ def render_unauthorized
13
+ raise Morpho::Exceptions::StandardError.new(
14
+ status: 401
15
+ )
20
16
  end
21
17
 
22
- def render_unauthorized_detailed(errors = {})
23
- render_unauthorized(errors)
18
+ def render_payment_required
19
+ raise Morpho::Exceptions::StandardError.new(
20
+ status: 402
21
+ )
24
22
  end
25
23
 
26
- def render_payment_required(errors = {})
27
- error!({
28
- message: I18n.t('morpho.api.messages.payment_required'),
29
- errors: errors,
30
- with: Morpho::Entities::Error
31
- }, 402)
24
+ def render_forbidden
25
+ raise Morpho::Exceptions::StandardError.new(
26
+ status: 403
27
+ )
32
28
  end
33
29
 
34
- def render_forbidden(errors = {})
35
- error!({
36
- message: I18n.t('morpho.api.messages.forbidden'),
37
- errors: errors,
38
- with: Morpho::Entities::Error
39
- }, 403)
30
+ def render_not_found
31
+ raise Morpho::Exceptions::StandardError.new(
32
+ status: 404
33
+ )
40
34
  end
41
35
 
42
- def render_not_found(errors = {})
43
- error!({
44
- message: I18n.t('morpho.api.messages.not_found'),
45
- errors: errors,
46
- with: Morpho::Entities::Error
47
- }, 404)
36
+ def render_method_not_allowed
37
+ raise Morpho::Exceptions::StandardError.new(
38
+ status: 405
39
+ )
48
40
  end
49
41
 
50
- def render_method_not_allowed(errors = {})
51
- error!({
52
- message: I18n.t('morpho.api.messages.method_not_allowed'),
53
- errors: errors,
54
- with: Morpho::Entities::Error
55
- }, 405)
42
+ def render_unprocessable_entity
43
+ raise Morpho::Exceptions::StandardError.new(
44
+ status: 422
45
+ )
56
46
  end
57
47
 
58
- def render_unprocessable_entity(errors = {})
59
- error!({
60
- message: I18n.t('morpho.api.messages.unprocessable_entity'),
61
- errors: errors,
62
- with: Morpho::Entities::Error
63
- }, 422)
64
- end
65
-
66
- def render_locked(errors = {})
67
- error!({
68
- message: I18n.t('morpho.api.messages.locked'),
69
- errors: errors,
70
- with: Morpho::Entities::Error
71
- }, 423)
72
- end
73
-
74
- def render_unprocessable_entity_detailed(errors = {})
75
- render_unprocessable_entity(errors)
48
+ def render_locked
49
+ raise Morpho::Exceptions::StandardError.new(
50
+ status: 423
51
+ )
76
52
  end
77
53
 
78
54
  def render_no_content
@@ -5,11 +5,12 @@ module Morpho
5
5
 
6
6
  namespace :activations do
7
7
  desc 'Request user activation token' do
8
+ detail ''
8
9
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::User)
9
10
  failure [
10
- [ 404, I18n.t('morpho.api.messages.not_found'), Morpho::Entities::Error ],
11
- [ 405, I18n.t('morpho.api.messages.method_not_allowed'), Morpho::Entities::Error ],
12
- [ 422, I18n.t('morpho.api.messages.unprocessable_entity'), Morpho::Entities::Error ]
11
+ [ 404, I18n.t('morpho.api.messages.general.404'), Morpho::Entities::Error ],
12
+ [ 405, I18n.t('morpho.api.messages.general.405'), Morpho::Entities::Error ],
13
+ [ 422, I18n.t('morpho.api.messages.general.422'), Morpho::Entities::Error ]
13
14
  ]
14
15
  end
15
16
  params do
@@ -20,17 +21,6 @@ module Morpho
20
21
 
21
22
  if result.success?
22
23
  present result['model'], with: Morpho::Entities::User
23
- else
24
- case result['error']
25
- when :unprocessable_entity
26
- render_unprocessable_entity(result['contract'].errors)
27
- when :not_found
28
- render_not_found({ base: I18n.t('morpho.api.messages.activate.not_found') })
29
- when :method_not_allowed
30
- render_method_not_allowed({ base: I18n.t('morpho.api.messages.activate.method_not_allowed') })
31
- else
32
- render_unprocessable_entity
33
- end
34
24
  end
35
25
  end
36
26
  end
@@ -5,7 +5,11 @@ module Morpho
5
5
 
6
6
  namespace :externals do
7
7
  desc 'Request user authentication from external provider' do
8
+ detail ''
8
9
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::AuthenticationToken)
10
+ failure [
11
+ [ 422, I18n.t('morpho.api.messages.general.422'), Morpho::Entities::Error ]
12
+ ]
9
13
  end
10
14
  params do
11
15
  requires :data, type: Morpho::Entities::External
@@ -15,13 +19,6 @@ module Morpho
15
19
 
16
20
  if result.success?
17
21
  present result['token'], with: Morpho::Entities::AuthenticationToken
18
- else
19
- case result['error']
20
- when :unprocessable_entity
21
- render_unprocessable_entity(result['contract'].errors)
22
- else
23
- render_unprocessable_entity
24
- end
25
22
  end
26
23
  end
27
24
  end
@@ -5,6 +5,7 @@ module Morpho
5
5
 
6
6
  namespace :hello do
7
7
  desc 'Request hello message' do
8
+ detail ''
8
9
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::Message)
9
10
  end
10
11
  get :public do
@@ -19,9 +20,10 @@ module Morpho
19
20
  end
20
21
 
21
22
  desc 'Request hello message' do
23
+ detail ''
22
24
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::Message)
23
25
  failure [
24
- [ 401, I18n.t('morpho.api.messages.unauthorized'), Morpho::Entities::Error ]
26
+ [ 401, I18n.t('morpho.api.messages.general.401'), Morpho::Entities::Error ]
25
27
  ]
26
28
  end
27
29
  get :private do
@@ -5,11 +5,12 @@ module Morpho
5
5
 
6
6
  namespace :passwords do
7
7
  desc 'Request user reset password token' do
8
+ detail ''
8
9
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::User)
9
10
  failure [
10
- [ 404, I18n.t('morpho.api.messages.not_found'), Morpho::Entities::Error ],
11
- [ 405, I18n.t('morpho.api.messages.method_not_allowed'), Morpho::Entities::Error ],
12
- [ 422, I18n.t('morpho.api.messages.unprocessable_entity'), Morpho::Entities::Error ]
11
+ [ 404, I18n.t('morpho.api.messages.general.404'), Morpho::Entities::Error ],
12
+ [ 405, I18n.t('morpho.api.messages.general.405'), Morpho::Entities::Error ],
13
+ [ 422, I18n.t('morpho.api.messages.general.422'), Morpho::Entities::Error ]
13
14
  ]
14
15
  end
15
16
  params do
@@ -20,19 +21,6 @@ module Morpho
20
21
 
21
22
  if result.success?
22
23
  present result['model'], with: Morpho::Entities::User
23
- else
24
- case result['error']
25
- when :not_valid
26
- render_unprocessable_entity(result['contract'].errors)
27
- when :not_found
28
- render_not_found
29
- when :not_allowed
30
- render_method_not_allowed
31
- when :not_delivered
32
- render_unprocessable_entity
33
- else
34
- render_unprocessable_entity
35
- end
36
24
  end
37
25
  end
38
26
  end
@@ -5,13 +5,14 @@ module Morpho
5
5
 
6
6
  namespace :tokens do
7
7
  desc 'Request user authentication token' do
8
+ detail ''
8
9
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::AuthenticationToken)
9
10
  failure [
10
- [ 401, I18n.t('morpho.api.messages.unauthorized'), Morpho::Entities::Error ],
11
- [ 403, I18n.t('morpho.api.messages.forbidden'), Morpho::Entities::Error ],
12
- [ 404, I18n.t('morpho.api.messages.not_found'), Morpho::Entities::Error ],
13
- [ 422, I18n.t('morpho.api.messages.unprocessable_entity'), Morpho::Entities::Error ],
14
- [ 423, I18n.t('morpho.api.messages.locked'), Morpho::Entities::Error ]
11
+ [ 401, I18n.t('morpho.api.messages.general.401'), Morpho::Entities::Error ],
12
+ [ 403, I18n.t('morpho.api.messages.general.403'), Morpho::Entities::Error ],
13
+ [ 404, I18n.t('morpho.api.messages.general.404'), Morpho::Entities::Error ],
14
+ [ 422, I18n.t('morpho.api.messages.general.422'), Morpho::Entities::Error ],
15
+ [ 423, I18n.t('morpho.api.messages.general.423'), Morpho::Entities::Error ]
15
16
  ]
16
17
  end
17
18
  params do
@@ -22,29 +23,15 @@ module Morpho
22
23
 
23
24
  if result.success?
24
25
  present result['token'], with: Morpho::Entities::AuthenticationToken
25
- else
26
- case result['error']
27
- when :unprocessable_entity
28
- render_unprocessable_entity(result['contract'].errors)
29
- when :not_found
30
- render_not_found({ base: I18n.t('morpho.api.messages.sign_in.not_found') })
31
- when :forbidden
32
- render_forbidden({ base: I18n.t('morpho.api.messages.sign_in.forbidden') })
33
- when :locked
34
- render_locked({ base: I18n.t('morpho.api.messages.sign_in.locked') })
35
- when :unauthorized
36
- render_unauthorized({ base: I18n.t('morpho.api.messages.sign_in.unauthorized') })
37
- else
38
- render_unprocessable_entity
39
- end
40
26
  end
41
27
  end
42
28
 
43
29
  desc 'Refresh user authentication token' do
30
+ detail ''
44
31
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::AuthenticationToken)
45
32
  failure [
46
- [ 404, I18n.t('morpho.api.messages.not_found'), Morpho::Entities::Error ],
47
- [ 422, I18n.t('morpho.api.messages.unprocessable_entity'), Morpho::Entities::Error ]
33
+ [ 404, I18n.t('morpho.api.messages.general.404'), Morpho::Entities::Error ],
34
+ [ 422, I18n.t('morpho.api.messages.general.422'), Morpho::Entities::Error ]
48
35
  ]
49
36
  end
50
37
  params do
@@ -55,15 +42,6 @@ module Morpho
55
42
 
56
43
  if result.success?
57
44
  present result['token'], with: Morpho::Entities::AuthenticationToken
58
- else
59
- case result['error']
60
- when :unprocessable_entity
61
- render_unprocessable_entity(result['contract'].errors)
62
- when :not_found
63
- render_not_found({ base: I18n.t('morpho.api.messages.refresh_token.not_found') })
64
- else
65
- render_unprocessable_entity
66
- end
67
45
  end
68
46
  end
69
47
  end
@@ -5,11 +5,12 @@ module Morpho
5
5
 
6
6
  namespace :unlocks do
7
7
  desc 'Request user unlock token' do
8
+ detail ''
8
9
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::UserEmail)
9
10
  failure [
10
- [ 404, I18n.t('morpho.api.messages.not_found'), Morpho::Entities::Error ],
11
- [ 405, I18n.t('morpho.api.messages.method_not_allowed'), Morpho::Entities::Error ],
12
- [ 422, I18n.t('morpho.api.messages.unprocessable_entity'), Morpho::Entities::Error ]
11
+ [ 404, I18n.t('morpho.api.messages.general.404'), Morpho::Entities::Error ],
12
+ [ 405, I18n.t('morpho.api.messages.general.405'), Morpho::Entities::Error ],
13
+ [ 422, I18n.t('morpho.api.messages.general.422'), Morpho::Entities::Error ]
13
14
  ]
14
15
  end
15
16
  params do
@@ -20,17 +21,6 @@ module Morpho
20
21
 
21
22
  if result.success?
22
23
  present result['model'], with: Morpho::Entities::User
23
- else
24
- case result['error']
25
- when :unprocessable_entity
26
- render_unprocessable_entity(result['contract'].errors)
27
- when :not_found
28
- render_not_found({ base: I18n.t('morpho.api.messages.unlock.not_found') })
29
- when :method_not_allowed
30
- render_method_not_allowed({ base: I18n.t('morpho.api.messages.unlock.method_not_allowed') })
31
- else
32
- render_unprocessable_entity
33
- end
34
24
  end
35
25
  end
36
26
  end
@@ -5,9 +5,10 @@ module Morpho
5
5
 
6
6
  namespace :users do
7
7
  desc 'User registration' do
8
+ detail ''
8
9
  success Morpho::Grape::DataWrapper.new(Morpho::Entities::User)
9
10
  failure [
10
- [ 422, I18n.t('morpho.api.messages.unprocessable_entity'), Morpho::Entities::Error ]
11
+ [ 422, I18n.t('morpho.api.messages.general.422'), Morpho::Entities::Error ]
11
12
  ]
12
13
  end
13
14
  params do
@@ -18,15 +19,6 @@ module Morpho
18
19
 
19
20
  if result.success?
20
21
  present result['model'], with: Morpho::Entities::User
21
- else
22
- case result['error']
23
- when :not_valid
24
- render_unprocessable_entity(result['contract'].errors)
25
- when :not_saved
26
- render_unprocessable_entity(result['model'].errors)
27
- else
28
- render_unprocessable_entity
29
- end
30
22
  end
31
23
  end
32
24
  end
@@ -1,40 +1,42 @@
1
1
  module Morpho
2
2
  class User::Operation::Activate < Trailblazer::Operation
3
- step :validate
4
- fail :unprocessable_entity, fail_fast: true
5
- step :find
6
- fail :not_found, fail_fast: true
7
- step :check
8
- fail :method_not_allowed, fail_fast: true
9
- pass :activation_email
3
+ pass :validate!
4
+ pass :find!
5
+ pass :check!
6
+ pass :activation_email!
10
7
 
11
- def validate (options, **)
8
+ def validate!(options, **)
12
9
  options['contract'] = Morpho::User::Contract::Activate.new(OpenStruct.new)
13
- options['contract'].validate(options['data'])
14
- end
15
-
16
- def find (options, **)
17
- options['model'] = Morpho::User.find_by(email: options['data']['email'])
18
- end
19
10
 
20
- def check (options, **)
21
- !options['model'].active?
11
+ unless options['contract'].validate(options['data'])
12
+ raise Morpho::Exceptions::StandardError.new(
13
+ errors: options['contract'].errors
14
+ )
15
+ end
22
16
  end
23
17
 
24
- def activation_email (options, **)
25
- options['model'].resend_activation_needed_email!
26
- end
18
+ def find!(options, **)
19
+ options['model'] = Morpho::User.find_by(email: options['data']['email'])
27
20
 
28
- def unprocessable_entity (options, **)
29
- options['error'] = :unprocessable_entity
21
+ if options['model'].nil?
22
+ raise Morpho::Exceptions::StandardError.new(
23
+ message: I18n.t('morpho.api.messages.activate.email_not_exists'),
24
+ status: 404
25
+ )
26
+ end
30
27
  end
31
28
 
32
- def not_found (options, **)
33
- options['error'] = :not_found
29
+ def check!(options, **)
30
+ if options['model'].active?
31
+ raise Morpho::Exceptions::StandardError.new(
32
+ message: I18n.t('morpho.api.messages.activate.account_already_confirmed'),
33
+ status: 405
34
+ )
35
+ end
34
36
  end
35
37
 
36
- def method_not_allowed (options, **)
37
- options['error'] = :method_not_allowed
38
+ def activation_email!(options, **)
39
+ options['model'].resend_activation_needed_email!
38
40
  end
39
41
  end
40
42
  end
@@ -1,48 +1,52 @@
1
1
  module Morpho
2
2
  class User::Operation::ExternalSignIn < Trailblazer::Operation
3
- step :validate
4
- fail :unprocessable_entity, fail_fast: true
5
- pass :find_authentication
6
- pass :find_user
7
- pass :sign_in
8
- pass :register
9
- pass :sign_up
10
- step :generate_refresh_token
11
- step :register_last_login_activity
12
- step :authentication_token
3
+ pass :validate!
4
+ pass :find_authentication!
5
+ pass :find_user!
6
+ pass :sign_in!
7
+ pass :register!
8
+ pass :sign_up!
9
+ pass :generate_refresh_token!
10
+ pass :register_last_login_activity!
11
+ pass :authentication_token!
13
12
 
14
- def validate (options, **)
13
+ def validate!(options, **)
15
14
  options['contract'] = Morpho::User::Contract::ExternalSignIn.new(OpenStruct.new)
16
- options['contract'].validate(options['data'])
15
+
16
+ unless options['contract'].validate(options['data'])
17
+ raise Morpho::Exceptions::StandardError.new(
18
+ errors: options['contract'].errors
19
+ )
20
+ end
17
21
  end
18
22
 
19
- def find_authentication (options, **)
23
+ def find_authentication!(options, **)
20
24
  options['authentication.model'] = Morpho::Authentication.find_by(
21
25
  uid: options['data']['uid'],
22
26
  provider: options['data']['provider']
23
27
  )
24
28
  end
25
29
 
26
- def find_user (options, **)
30
+ def find_user!(options, **)
27
31
  options['user.model'] = Morpho::User.find_by(email: options['data']['email'])
28
32
  end
29
33
 
30
- def sign_in (options, **)
34
+ def sign_in!(options, **)
31
35
  if options['authentication.model']
32
36
  options['user.model'] = options['authentication.model'].user
33
37
  end
34
38
  end
35
39
 
36
- def register (options, **)
37
- if options['user.model'] && !options['authentication.model']
40
+ def register!(options, **)
41
+ if options['user.model'] && options['authentication.model'].nil?
38
42
  provider = options['data']['provider'].downcase
39
43
 
40
44
  options['user.model'].add_provider_to_user(provider, options['data']['uid'])
41
45
  end
42
46
  end
43
47
 
44
- def sign_up (options, **)
45
- if !options['user.model'] && !options['authentication.model']
48
+ def sign_up!(options, **)
49
+ if options['user.model'].nil? && options['authentication.model'].nil?
46
50
  provider = options['data']['provider'].downcase
47
51
 
48
52
  options['user.model'] = Morpho::User.create_from_provider(provider, options['data']['uid'], {
@@ -51,19 +55,15 @@ module Morpho
51
55
  end
52
56
  end
53
57
 
54
- def generate_refresh_token (options, **)
58
+ def generate_refresh_token!(options, **)
55
59
  options['user.model'].generate_refresh_token!
56
60
  end
57
61
 
58
- def register_last_login_activity (options, **)
62
+ def register_last_login_activity!(options, **)
59
63
  options['user.model'].register_last_login_activity!(options['ip'])
60
64
  end
61
65
 
62
- def unprocessable_entity (options, **)
63
- options['error'] = :unprocessable_entity
64
- end
65
-
66
- def authentication_token (options, **)
66
+ def authentication_token!(options, **)
67
67
  options['token'] = ::Morpho::JWT::Payload.new(options['user.model'])
68
68
  end
69
69
  end
@@ -1,34 +1,36 @@
1
1
  module Morpho
2
2
  class User::Operation::RefreshToken < Trailblazer::Operation
3
- step :validate
4
- fail :unprocessable_entity, fail_fast: true
5
- step :find
6
- fail :not_found, fail_fast: true
7
- step :generate_refresh_token
8
- step :authentication_token
3
+ pass :validate!
4
+ pass :find!
5
+ pass :generate_refresh_token!
6
+ pass :authentication_token!
9
7
 
10
- def validate (options, **)
8
+ def validate!(options, **)
11
9
  options['contract'] = Morpho::User::Contract::RefreshToken.new(OpenStruct.new)
12
- options['contract'].validate(options['data'])
13
- end
14
10
 
15
- def find (options, **)
16
- options['model'] = Morpho::User.find_by(refresh_token: options['data']['refresh_token'])
11
+ unless options['contract'].validate(options['data'])
12
+ raise Morpho::Exceptions::StandardError.new(
13
+ errors: options['contract'].errors
14
+ )
15
+ end
17
16
  end
18
17
 
19
- def generate_refresh_token (options, **)
20
- options['model'].generate_refresh_token!
21
- end
18
+ def find!(options, **)
19
+ options['model'] = Morpho::User.find_by(refresh_token: options['data']['refresh_token'])
22
20
 
23
- def unprocessable_entity (options, **)
24
- options['error'] = :unprocessable_entity
21
+ if options['model'].nil?
22
+ raise Morpho::Exceptions::StandardError.new(
23
+ message: I18n.t('morpho.api.messages.refresh_token.invalid'),
24
+ status: 404
25
+ )
26
+ end
25
27
  end
26
28
 
27
- def not_found (options, **)
28
- options['error'] = :not_found
29
+ def generate_refresh_token!(options, **)
30
+ options['model'].generate_refresh_token!
29
31
  end
30
32
 
31
- def authentication_token (options, **)
33
+ def authentication_token!(options, **)
32
34
  options['token'] = ::Morpho::JWT::Payload.new(options['model'])
33
35
  end
34
36
  end
@@ -1,49 +1,40 @@
1
1
  module Morpho
2
2
  class User::Operation::ResetPassword < Trailblazer::Operation
3
- step :validate
4
- fail :not_valid, fail_fast: true
5
- step :find
6
- fail :not_found, fail_fast: true
7
- step :check
8
- fail :not_allowed, fail_fast: true
9
- step :reset_password_email
10
- fail :not_delivered, fail_fast: true
3
+ pass :validate!
4
+ pass :find!
5
+ pass :check!
6
+ pass :reset_password_email!
11
7
 
12
- def validate (options, **)
8
+ def validate!(options, **)
13
9
  options['contract'] = Morpho::User::Contract::ResetPassword.new(OpenStruct.new)
14
- options['contract'].validate(options['data'])
15
- end
16
-
17
- def find (options, **)
18
- options['model'] = Morpho::User.find_by(email: options['data']['email'])
19
- end
20
-
21
- def check (options, **)
22
- !options['model'].external?
23
- end
24
10
 
25
- def reset_password_email (options, **)
26
- options['model'].deliver_reset_password_instructions!
27
- end
28
-
29
- def not_valid (options, **)
30
- options['error'] = :not_valid
11
+ unless options['contract'].validate(options['data'])
12
+ raise Morpho::Exceptions::StandardError.new(
13
+ errors: options['contract'].errors
14
+ )
15
+ end
31
16
  end
32
17
 
33
- def not_found (options, **)
34
- options['error'] = :not_found
35
- end
18
+ def find!(options, **)
19
+ options['model'] = Morpho::User.find_by(email: options['data']['email'])
36
20
 
37
- def not_allowed (options, **)
38
- options['error'] = :not_allowed
21
+ if options['model'].nil?
22
+ raise Morpho::Exceptions::StandardError.new(
23
+ status: 404
24
+ )
25
+ end
39
26
  end
40
27
 
41
- def not_delivered (options, **)
42
- options['error'] = :not_delivered
28
+ def check!(options, **)
29
+ if options['model'].external?
30
+ raise Morpho::Exceptions::StandardError.new(
31
+ status: 405
32
+ )
33
+ end
43
34
  end
44
35
 
45
- def render (options, **)
46
- options['model']
36
+ def reset_password_email!(options, **)
37
+ options['model'].deliver_reset_password_instructions!
47
38
  end
48
39
  end
49
40
  end
@@ -1,70 +1,72 @@
1
1
  module Morpho
2
2
  class User::Operation::SignIn < Trailblazer::Operation
3
- step :validate
4
- fail :unprocessable_entity, fail_fast: true
5
- step :find
6
- fail :not_found, fail_fast: true
7
- step :check_active
8
- fail :forbidden, fail_fast: true
9
- step :check_unlocked
10
- fail :locked, fail_fast: true
11
- step :check_password
12
- fail :unauthorized, fail_fast: true
13
- step :generate_refresh_token
14
- step :register_last_login_activity
15
- step :authentication_token
3
+ pass :validate!
4
+ pass :find!
5
+ pass :check_active!
6
+ pass :check_unlocked!
7
+ pass :check_password!
8
+ pass :generate_refresh_token!
9
+ pass :register_last_login_activity!
10
+ pass :authentication_token!
16
11
 
17
- def validate (options, **)
12
+ def validate!(options, **)
18
13
  options['contract'] = Morpho::User::Contract::SignIn.new(OpenStruct.new)
19
- options['contract'].validate(options['data'])
14
+
15
+ unless options['contract'].validate(options['data'])
16
+ raise Morpho::Exceptions::StandardError.new(
17
+ errors: options['contract'].errors
18
+ )
19
+ end
20
20
  end
21
21
 
22
- def find (options, **)
22
+ def find!(options, **)
23
23
  options['model'] = Morpho::User.find_by(email: options['data']['email'])
24
+
25
+ if options['model'].nil?
26
+ raise Morpho::Exceptions::StandardError.new(
27
+ message: I18n.t('morpho.api.messages.sign_in.email_not_exists'),
28
+ status: 404
29
+ )
30
+ end
24
31
  end
25
32
 
26
- def check_active (options, **)
27
- options['model'].active?
33
+ def check_active!(options, **)
34
+ unless options['model'].active?
35
+ raise Morpho::Exceptions::StandardError.new(
36
+ message: I18n.t('morpho.api.messages.sign_in.account_not_confirmed'),
37
+ status: 403
38
+ )
39
+ end
28
40
  end
29
41
 
30
- def check_unlocked (options, **)
31
- options['model'].unlocked?
42
+ def check_unlocked!(options, **)
43
+ unless options['model'].unlocked?
44
+ raise Morpho::Exceptions::StandardError.new(
45
+ message: I18n.t('morpho.api.messages.sign_in.account_locked'),
46
+ status: 423
47
+ )
48
+ end
32
49
  end
33
50
 
34
- def check_password (options, **)
35
- options['model'].valid_password?(options['data']['password'])
51
+ def check_password!(options, **)
52
+ unless options['model'].valid_password?(options['data']['password'])
53
+ options['model'].register_failed_login!
54
+ raise Morpho::Exceptions::StandardError.new(
55
+ message: I18n.t('morpho.api.messages.sign_in.bad_credentials'),
56
+ status: 401
57
+ )
58
+ end
36
59
  end
37
60
 
38
- def generate_refresh_token (options, **)
61
+ def generate_refresh_token!(options, **)
39
62
  options['model'].generate_refresh_token!
40
63
  end
41
64
 
42
- def register_last_login_activity (options, **)
65
+ def register_last_login_activity!(options, **)
43
66
  options['model'].register_last_login_activity!(options['ip'])
44
67
  end
45
68
 
46
- def unprocessable_entity (options, **)
47
- options['error'] = :unprocessable_entity
48
- end
49
-
50
- def not_found (options, **)
51
- options['error'] = :not_found
52
- end
53
-
54
- def forbidden (options, **)
55
- options['error'] = :forbidden
56
- end
57
-
58
- def locked (options, **)
59
- options['error'] = :locked
60
- end
61
-
62
- def unauthorized (options, **)
63
- options['model'].register_failed_login!
64
- options['error'] = :unauthorized
65
- end
66
-
67
- def authentication_token (options, **)
69
+ def authentication_token!(options, **)
68
70
  options['token'] = ::Morpho::JWT::Payload.new(options['model'])
69
71
  end
70
72
  end
@@ -1,36 +1,32 @@
1
1
  module Morpho
2
2
  class User::Operation::SignUp < Trailblazer::Operation
3
- step :validate
4
- fail :not_valid, fail_fast: true
5
- step :sync
6
- fail :not_synced, fail_fast: true
7
- step :save
8
- fail :not_saved, fail_fast: true
3
+ pass :validate!
4
+ pass :sync!
5
+ pass :save!
9
6
 
10
- def validate(options, **)
7
+ def validate!(options, **)
11
8
  options['contract'] = Morpho::User::Contract::SignUp.new(Morpho::User.new)
12
- options['contract'].validate(options['data'])
9
+
10
+ unless options['contract'].validate(options['data'])
11
+ raise Morpho::Exceptions::StandardError.new(
12
+ errors: options['contract'].errors
13
+ )
14
+ end
13
15
  end
14
16
 
15
- def sync(options, **)
17
+ def sync!(options, **)
16
18
  options['contract'].sync
17
19
  end
18
20
 
19
- def save (options, **)
21
+ def save!(options, **)
20
22
  options['model'] = options['contract'].model
21
23
  options['model'].save
22
- end
23
-
24
- def not_valid(options, **)
25
- options['error'] = :not_valid
26
- end
27
-
28
- def not_synced(options, **)
29
- options['error'] = :not_synced
30
- end
31
24
 
32
- def not_saved(options, **)
33
- options['error'] = :not_saved
25
+ unless options['model'].persisted?
26
+ raise Morpho::Exceptions::StandardError.new(
27
+ errors: options['model'].errors
28
+ )
29
+ end
34
30
  end
35
31
  end
36
32
  end
@@ -1,40 +1,42 @@
1
1
  module Morpho
2
2
  class User::Operation::Unlock < Trailblazer::Operation
3
- step :validate
4
- fail :unprocessable_entity, fail_fast: true
5
- step :find
6
- fail :not_found, fail_fast: true
7
- step :check
8
- fail :method_not_allowed, fail_fast: true
9
- pass :unlock_token_email
3
+ pass :validate!
4
+ pass :find!
5
+ pass :check!
6
+ pass :unlock_token_email!
10
7
 
11
- def validate (options, **)
8
+ def validate!(options, **)
12
9
  options['contract'] = Morpho::User::Contract::Unlock.new(OpenStruct.new)
13
- options['contract'].validate(options['data'])
14
- end
15
-
16
- def find (options, **)
17
- options['model'] = Morpho::User.find_by(email: options['data']['email'])
18
- end
19
10
 
20
- def check (options, **)
21
- options['model'].login_locked?
11
+ unless options['contract'].validate(options['data'])
12
+ raise Morpho::Exceptions::StandardError.new(
13
+ errors: options['contract'].errors
14
+ )
15
+ end
22
16
  end
23
17
 
24
- def unlock_token_email (options, **)
25
- options['model'].resend_unlock_token_email!
26
- end
18
+ def find!(options, **)
19
+ options['model'] = Morpho::User.find_by(email: options['data']['email'])
27
20
 
28
- def unprocessable_entity (options, **)
29
- options['error'] = :unprocessable_entity
21
+ if options['model'].nil?
22
+ raise Morpho::Exceptions::StandardError.new(
23
+ message: I18n.t('morpho.api.messages.unlock.email_not_exists'),
24
+ status: 404
25
+ )
26
+ end
30
27
  end
31
28
 
32
- def not_found (options, **)
33
- options['error'] = :not_found
29
+ def check!(options, **)
30
+ unless options['model'].login_locked?
31
+ raise Morpho::Exceptions::StandardError.new(
32
+ message: I18n.t('morpho.api.messages.unlock.account_not_locked'),
33
+ status: 405
34
+ )
35
+ end
34
36
  end
35
37
 
36
- def method_not_allowed (options, **)
37
- options['error'] = :method_not_allowed
38
+ def unlock_token_email!(options, **)
39
+ options['model'].resend_unlock_token_email!
38
40
  end
39
41
  end
40
42
  end
@@ -10,6 +10,10 @@ module Morpho
10
10
  self.activation_state == 'active'
11
11
  end
12
12
 
13
+ def inactive?
14
+ self.activation_state == 'pending'
15
+ end
16
+
13
17
  def unlocked?
14
18
  !self.login_locked?
15
19
  end
@@ -130,27 +130,28 @@ en:
130
130
 
131
131
  api:
132
132
  messages:
133
- bad_request: 'Bad request'
134
- unauthorized: 'Unauthorized'
135
- payment_required: 'Payment required'
136
- forbidden: 'Forbidden'
137
- not_found: 'Not found'
138
- method_not_allowed: 'Method not allowed'
139
- unprocessable_entity: 'Unprocessable entity'
140
- locked: 'Locked'
133
+ general:
134
+ "400": 'Bad request'
135
+ "401": 'Unauthorized'
136
+ "402": 'Payment required'
137
+ "403": 'Forbidden'
138
+ "404": 'Not found'
139
+ "405": 'Method not allowed'
140
+ "422": 'Unprocessable entity'
141
+ "423": 'Locked'
141
142
  activate:
142
- not_found: 'Email address does not belongs to a registered account'
143
- method_not_allowed: 'User account has already been confirmed'
143
+ email_not_exists: 'Email address does not belongs to a registered account'
144
+ account_already_confirmed: 'User account has already been confirmed'
144
145
  sign_in:
145
- not_found: 'Email address does not belongs to a registered account'
146
- forbidden: 'User account has not been confirmed'
147
- unauthorized: 'User email and/or password is incorrect'
148
- locked: 'User account has been locked'
146
+ email_not_exists: 'Email address does not belongs to a registered account'
147
+ account_not_confirmed: 'User account has not been confirmed'
148
+ account_locked: 'User account has been locked'
149
+ bad_credentials: 'User email and/or password is incorrect'
149
150
  refresh_token:
150
- not_found: 'Invalid token'
151
+ invalid: 'Invalid token'
151
152
  unlock:
152
- not_found: 'Email address does not belongs to a registered account'
153
- method_not_allowed: 'User account has not been locked'
153
+ email_not_exists: 'Email address does not belongs to a registered account'
154
+ account_not_locked: 'User account has not been locked'
154
155
  simple_form:
155
156
  'yes': 'Yes'
156
157
  'no': 'No'
@@ -130,27 +130,28 @@ es:
130
130
 
131
131
  api:
132
132
  messages:
133
- bad_request: 'Solicitud incorrecta'
134
- unauthorized: 'No autorizado'
135
- payment_required: 'Pago requerido'
136
- forbidden: 'Prohibido'
137
- not_found: 'No encontrado'
138
- method_not_allowed: 'Método no permitido'
139
- unprocessable_entity: 'Entidad no procesable'
140
- locked: 'Bloqueado'
133
+ general:
134
+ "400": 'Solicitud incorrecta'
135
+ "401": 'No autorizado'
136
+ "402": 'Pago requerido'
137
+ "403": 'Prohibido'
138
+ "404": 'No encontrado'
139
+ "405": 'Método no permitido'
140
+ "422": 'Entidad no procesable'
141
+ "423": 'Bloqueado'
141
142
  activate:
142
- not_found: 'Correo electrónico no pertenece a un usuario registrado'
143
- method_not_allowed: 'Cuenta de usuario ya ha sido confirmada'
143
+ email_not_exists: 'Correo electrónico no pertenece a un usuario registrado'
144
+ account_already_confirmed: 'Cuenta de usuario ya ha sido confirmada'
144
145
  sign_in:
145
- not_found: 'Correo electrónico no pertenece a un usuario registrado'
146
- forbidden: 'Cuenta de usuario no ha sido confirmada'
147
- unauthorized: 'Correo electrónico y/o contraseña es incorrecto(a)'
148
- locked: 'Cuenta de usuario ha sido bloqueada'
146
+ email_not_exists: 'Correo electrónico no pertenece a un usuario registrado'
147
+ account_not_confirmed: 'Cuenta de usuario no ha sido confirmada'
148
+ account_locked: 'Cuenta de usuario ha sido bloqueada'
149
+ bad_credentials: 'Correo electrónico y/o contraseña es incorrecto(a)'
149
150
  refresh_token:
150
- not_found: 'El token es inválido'
151
+ invalid: 'El token es inválido'
151
152
  unlock:
152
- not_found: 'Correo electrónico no pertenece a un usuario registrado'
153
- method_not_allowed: 'Cuenta de usuario no ha sido bloqueada'
153
+ email_not_exists: 'Correo electrónico no pertenece a un usuario registrado'
154
+ account_not_locked: 'Cuenta de usuario no ha sido bloqueada'
154
155
  simple_form:
155
156
  'yes': 'Si'
156
157
  'no': 'No'
@@ -1,3 +1,3 @@
1
1
  module Morpho
2
- VERSION = '1.1.2'
2
+ VERSION = '1.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: morpho
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hugo Gilmar Erazo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-01 00:00:00.000000000 Z
11
+ date: 2018-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -296,6 +296,8 @@ files:
296
296
  - app/api/morpho/entities/user.rb
297
297
  - app/api/morpho/entities/user_email.rb
298
298
  - app/api/morpho/entities/user_sign_up.rb
299
+ - app/api/morpho/exceptions/standard_error.rb
300
+ - app/api/morpho/formatters/standard_error.rb
299
301
  - app/api/morpho/helpers/http_responses.rb
300
302
  - app/api/morpho/helpers/jwt_utils.rb
301
303
  - app/api/morpho/resources/activations.rb