morpho 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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