decko 0.6.0 → 0.6.1

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
  SHA1:
3
- metadata.gz: c2c0b62be6973d42ca0313378dbbc42161349f30
4
- data.tar.gz: 065f3de25caebaa321a6170cdae58a7471456cb5
3
+ metadata.gz: aeacf2fbbf0981f2cee104c70ae92aa444ebaac7
4
+ data.tar.gz: f1eb236d57cf919828baeea2ee765b96a7d42fa1
5
5
  SHA512:
6
- metadata.gz: 75874b945a5c272db5bbbce646ecd8f866a80bb9dad9933caaaefcc6204b177288929e7166eca04339fae2a7b3c37f20cb47411f322607ba8cc4950039c3ed8f
7
- data.tar.gz: 20fd9ae8f95b4583d10f57fc3c6621d7d955daa4ea09ef977076e10e4feef9560db96bf20a9ed2e89db1a8c0893095855de96ab9364b50d89a9f1ef002dace22
6
+ metadata.gz: d877cc738c99466edc35464b075ea017bfe1fe48d2c322767c190ae2a61627c17cb59fcf0f9d91d20e784f809ccbc7e804ab0c2757450711c5b94f13082c853d
7
+ data.tar.gz: db58b0aecd2e3f1a9a59b714ff2925ade4bc3b64218fad93185f4df246cf0850be88dd13b2056787ba9087a226eb3e9ecba8fcba25fa5fb00b8579b0a712eda3
@@ -2,7 +2,22 @@ module Decko
2
2
  # methods for managing decko responses
3
3
  module Response
4
4
  private
5
- def card_redirect url
5
+ def respond format, result, status
6
+ if status == 302
7
+ hard_redirect result
8
+ elsif format.is_a?(Card::Format::FileFormat) && status == 200
9
+ send_file(*result)
10
+ else
11
+ render_response result.to_s.html_safe, status, format.mime_type
12
+ end
13
+ end
14
+
15
+ def render_response body, status, content_type
16
+ render body: body, status: status, content_type: content_type
17
+ end
18
+
19
+ # return a redirect response
20
+ def hard_redirect url
6
21
  url = card_url url # make sure we have absolute url
7
22
  if Card::Env.ajax?
8
23
  # lets client reset window location
@@ -14,93 +29,101 @@ module Decko
14
29
  end
15
30
  end
16
31
 
17
- def deliver format, result, status
18
- if status == 302
19
- card_redirect result
20
- elsif format.is_a?(Card::Format::FileFormat) && status == 200
21
- send_file(*result)
22
- else
23
- render body: result.to_s.html_safe,
24
- status: status,
25
- content_type: format.mime_type
26
- end
32
+ # return a standard GET response directly.
33
+ # Used in AJAX situations where PRG pattern is unwieldy
34
+ def soft_redirect success
35
+ @card = success.target
36
+ require_card_for_soft_redirect!
37
+ self.params = Card::Env[:params] = soft_redirect_params
38
+ load_action
39
+ show
27
40
  end
28
41
 
29
- def reset_card new_card
30
- @card = new_card
31
- update_params_for_success
32
- @card.select_action_by_params params
42
+ def soft_redirect_params
43
+ new_params = params.clone
44
+ new_params.delete :card
45
+ new_params.delete :action
46
+ new_params.merge Card::Env.success.params
33
47
  end
34
48
 
35
- def update_params_for_success
36
- success = Card::Env.success
37
- Card::Env[:params] =
38
- self.params =
39
- success.soft_redirect? ? success.params : params.merge(success.params)
49
+ def require_card_for_soft_redirect!
50
+ return if card.is_a? Card
51
+ raise Card::Error, "tried to do soft redirect without a card"
40
52
  end
41
53
 
54
+ # (obviously) deprecated
42
55
  def send_deprecated_asset
43
- filename = [params[:filename], params[:format]].join(".")
56
+ filename = [params[:mark], params[:format]].join(".")
44
57
  # for security, block relative paths
45
58
  raise Card::Error::BadAddress if filename.include? "../"
46
59
  path = Decko::Engine.paths["gem-assets"].existent.first
47
60
  send_file File.join(path, filename), x_sendfile: true
48
61
  end
49
62
 
50
- def format_from_params card
63
+ # TODO: everything below should go in a separate file
64
+ # below is about beginning (initialization). above is about end (response)
65
+ # Both this file and that would make sense as submodules of CardController
66
+
67
+ def load_format
68
+ request.format = :html if Card::Env.ajax? && !params[:format]
51
69
  card.format format_name_from_params
52
70
  end
53
71
 
54
72
  def format_name_from_params
55
- return :file if params[:explicit_file]
56
- format = request.format
57
- # format = request.parameters[:format]
58
- # unknown format
59
- return :file unless Card::Format.registered.member?(format)
60
- format.to_sym
61
- end
62
-
63
- def interpret_id id
64
- case id
65
- when "*previous" then
66
- return card_redirect(Card::Env.previous_location)
67
- when nil then
68
- determine_id
73
+ explicit_file_format? ? :file : request.format.to_sym
74
+ end
75
+
76
+ def explicit_file_format?
77
+ params[:explicit_file] || !Card::Format.registered.member?(request.format)
78
+ end
79
+
80
+ def interpret_mark mark
81
+ case mark
82
+ when "*previous"
83
+ # Why support this? It's only needed in Success, right? Deprecate?
84
+ return hard_redirect(Card::Env.previous_location)
85
+ when nil
86
+ implicit_mark
69
87
  else
70
- validate_id_encoding id
88
+ explicit_mark mark
71
89
  end
72
90
  end
73
91
 
74
- def determine_id
92
+ def explicit_mark mark
93
+ # we should find the place where we produce these bad urls
94
+ mark.valid_encoding? ? mark : mark.force_encoding("ISO-8859-1").encode("UTF-8")
95
+ end
96
+
97
+ def implicit_mark
75
98
  case
76
- when prompt_setup?
77
- prepare_setup_card!
78
- when params[:card] && params[:card][:name]
79
- params[:card][:name]
80
- when Card::Format.tagged(params[:view], :unknown_ok)
81
- ""
82
- else
83
- Card.global_setting(:home) || "Home"
99
+ when initial_setup then ""
100
+ when (name = params.dig :card, :name) then name
101
+ when view_does_not_require_name? then ""
102
+ else home_mark
84
103
  end
85
104
  end
86
105
 
87
- def prompt_setup?
88
- Card::Auth.needs_setup? && Card::Env.html?
106
+ def home_mark
107
+ Card.global_setting(:home) || "Home"
89
108
  end
90
109
 
91
- def prepare_setup_card!
92
- params[:card] = { type_id: Card.default_accounted_type_id }
93
- params[:view] = "setup"
94
- ""
110
+ def view_does_not_require_name?
111
+ Card::Format.tagged params[:view], :unknown_ok
95
112
  end
96
113
 
97
- def validate_id_encoding id
98
- # we should find the place where we produce these bad urls
99
- id.valid_encoding? ? id : id.force_encoding("ISO-8859-1").encode("UTF-8")
114
+ # alters params
115
+ def initial_setup
116
+ return unless initial_setup?
117
+ prepare_setup_card!
118
+ end
119
+
120
+ def initial_setup?
121
+ Card::Auth.needs_setup? && Card::Env.html?
100
122
  end
101
123
 
102
- def use_draft?
103
- params[:edit_draft] && card.drafts.present?
124
+ def prepare_setup_card!
125
+ params[:card] = { type_id: Card.default_accounted_type_id }
126
+ params[:view] = "setup"
104
127
  end
105
128
  end
106
129
  end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module Decko
4
+ # for use in REST API specs
5
+ module RestSpecMethods
6
+ def with_token_for usermark
7
+ yield Card[usermark].account.reset_token
8
+ end
9
+ end
10
+
11
+ # for use in REST API specs
12
+ module RestSpecHelper
13
+ def self.describe_api &block
14
+ RSpec.describe CardController, type: :controller do
15
+ routes { Decko::Engine.routes }
16
+ include Capybara::DSL
17
+ include RestSpecMethods
18
+ instance_eval(&block)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -49,37 +49,43 @@ class CardController < ActionController::Base
49
49
 
50
50
  before_action :setup, except: [:asset]
51
51
  before_action :authenticate, except: [:asset]
52
- before_action :load_id, only: [:read]
52
+ before_action :load_mark, only: [:read]
53
53
  before_action :load_card, except: [:asset]
54
+ before_action :load_action, only: [:read]
54
55
  before_action :refresh_card, only: [:create, :update, :delete]
55
56
 
56
57
  def setup
57
58
  Card::Machine.refresh_script_and_style unless params[:explicit_file]
58
59
  Card::Cache.renew
59
60
  Card::Env.reset controller: self
60
- request.format = :html if Card::Env.ajax? && !params[:format]
61
61
  end
62
62
 
63
63
  def authenticate
64
64
  Card::Auth.set_current params[:token], params[:current]
65
65
  end
66
66
 
67
- def load_id
68
- params[:id] = interpret_id params[:id]
67
+ def load_mark
68
+ params[:mark] = interpret_mark params[:mark]
69
69
  end
70
70
 
71
71
  def load_card
72
- @card = Card.controller_fetch params
73
- raise Card::Error::NotFound unless @card
74
- load_action
75
- record_as_main
76
- card.errors.any? ? render_errors : true
72
+ handle_errors do
73
+ @card = Card.controller_fetch params
74
+ raise Card::Error::NotFound unless card
75
+ record_as_main
76
+ end
77
77
  end
78
78
 
79
79
  def load_action
80
- @card.select_action_by_params params
80
+ handle_errors do
81
+ card.select_action_by_params params
82
+ if params[:edit_draft] && card.drafts.present?
83
+ card.content = card.last_draft_content
84
+ end
85
+ end
81
86
  end
82
87
 
88
+ # TODO: refactor this away this when new layout handling is ready
83
89
  def record_as_main
84
90
  Card::Env[:main_name] = params[:main] || card&.name || ""
85
91
  end
@@ -96,27 +102,27 @@ class CardController < ActionController::Base
96
102
  end
97
103
  end
98
104
 
105
+ def handle_errors
106
+ yield
107
+ card.errors.any? ? render_errors : true
108
+ end
109
+
110
+ # successful create, update, or delete action
99
111
  def render_success
100
- success = Card::Env.success
101
- success.name_context = @card.name
102
- if !Card::Env.ajax? || success.hard_redirect?
103
- card_redirect success.to_url
104
- elsif success.target.is_a? String
105
- render plain: success.target
112
+ success = Card::Env.success.in_context card.name
113
+ if Card::Env.ajax? && !success.hard_redirect?
114
+ soft_redirect success
106
115
  else
107
- reset_card success.target
108
- show
116
+ hard_redirect success.to_url
109
117
  end
110
118
  end
111
119
 
112
120
  def show view=nil, status=200
113
121
  card.action = :read
114
- card.content = card.last_draft_content if use_draft?
115
-
116
- format = format_from_params card
122
+ format = load_format
117
123
  result = render_page format, view
118
124
  status = format.error_status || status
119
- deliver format, result, status
125
+ respond format, result, status
120
126
  end
121
127
 
122
128
  def render_page format, view
@@ -1,55 +1,49 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  Decko::Engine.routes.draw do
4
- # most common
4
+ files = Decko::Engine.config.files_web_path
5
+ file_matchers = { mark: /[^-]+/, explicit_file: true, rev_id: /[^-]+/ }
6
+
5
7
  root "card#read"
6
- get "#{Decko::Engine.config.files_web_path}/:id/:rev_id(-:size).:format" =>
7
- "card#read", id: /[^-]+/, rev_id: /[^-]+/, explicit_file: true
8
- get "#{Decko::Engine.config.files_web_path}/:id(-:size)-:rev_id.:format" =>
9
- "card#read", id: /[^-]+/, explicit_file: true # deprecated
10
- get "assets/*filename" => "card#asset"
11
- get "javascripts/*filename" => "card#asset"
12
- get "jasmine/*filename" => "card#asset"
13
-
14
- get "recent(.:format)" => "card#read", id: ":recent" # obviate by making links use codename
15
- # match ':view:(:id(.:format))' => 'card#read', via: :get
16
- get "(/wagn)/:id(.:format)" => "card#read" # /wagn is deprecated
17
-
18
- # RESTful
19
- post "/" => "card#create"
20
- put "/" => "card#update"
21
- delete "/" => "card#delete"
22
8
 
23
- match ":id(.:format)" => "card#create", via: :post
24
- match ":id(.:format)" => "card#update", via: :put
25
- match ":id(.:format)" => "card#delete", via: :delete
9
+ # explicit file request
10
+ get({ "#{files}/:mark/:rev_id(-:size).:format" => "card#read" }.merge(file_matchers))
11
+
12
+ # DEPRECATED (old file and asset requests)
13
+ get({ "#{files}/:mark(-:size)-:rev_id.:format" => "card#read" }.merge(file_matchers))
14
+ %w[assets javascripts jasmine].each do |prefix|
15
+ get "#{prefix}/*mark" => "card#asset"
16
+ end
26
17
 
27
- get ":id/view/:view(.:format)" => "card#read"
18
+ # Standard GET requests
19
+ get "(/wagn)/:mark(.:format)" => "card#read" # /wagn is deprecated
28
20
 
29
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~
30
- # legacy
31
- get "new/:type" => "card#read", view: "new"
32
- get "card/:view(/:id(.:format))" => "card#read", view: /new|edit/
21
+ # Alternate GET requests
22
+ get "new/:type" => "card#read", view: "new" # common case for card without mark
23
+ get ":mark/view/:view(.:format)" => "card#read" # simplifies API documentation
24
+ get "card/:view(/:mark(.:format))" => "card#read", view: /new|edit/ # legacy
33
25
 
34
- get "account/signin" => "card#read", id: ":signin"
35
- get "account/signout" => "card#delete", id: ":signin"
36
- get "account/signup" => "card#read", view: "new", card: { type_code: :signup }
37
- get "account/invite" => "card#read", view: "new", card: { type_code: :signup }
38
- get "account/accept" => "card#read", view: "edit", card: { type_code: :signup }
39
- # use type_code rather than id because in some cases (eg populating test data) routes must get loaded without loading Card
26
+ # RESTful (without mark)
27
+ post "/" => "card#create"
28
+ put "/" => "card#update"
29
+ patch "/" => "card#update"
30
+ delete "/" => "card#delete"
40
31
 
41
- get "admin/stats" => "card#read", id: ":admin"
42
- get "admin/:task" => "card#update", id: ":admin"
43
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~
32
+ # RESTful (with mark)
33
+ match ":mark(.:format)" => "card#create", via: :post
34
+ match ":mark(.:format)" => "card#update", via: %i[put patch]
35
+ match ":mark(.:format)" => "card#delete", via: :delete
44
36
 
45
- # standard non-RESTful
37
+ # explicit GET alternatives for transactions
46
38
  %w[create read update delete asset].each do |action|
47
- get "(card)/#{action}(/:id(.:format))" => "card", action: action
39
+ get "(card)/#{action}(/:mark(.:format))" => "card", action: action
48
40
  end
49
41
 
50
- match "(card)/create(/:id(.:format))" => "card#create", via: [:post, :patch]
51
- match "(card)/update(/:id(.:format))" => "card#update", via: [:post, :put, :patch]
52
- match "(card)/delete(/:id(.:format))" => "card#delete", via: :delete
53
- # other
54
- get "*id" => "card#read", view: "bad_address"
42
+ # for super-explicit over-achievers
43
+ match "(card)/create(/:mark(.:format))" => "card#create", via: %i[post patch]
44
+ match "(card)/update(/:mark(.:format))" => "card#update", via: %i[post put patch]
45
+ match "(card)/delete(/:mark(.:format))" => "card#delete", via: :delete
46
+
47
+ # Wildcard for bad addresses
48
+ get "*mark" => "card#read", view: "bad_address"
55
49
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decko
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan McCutchen
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2018-07-23 00:00:00.000000000 Z
14
+ date: 2018-08-20 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: card
@@ -19,14 +19,14 @@ dependencies:
19
19
  requirements:
20
20
  - - '='
21
21
  - !ruby/object:Gem::Version
22
- version: 1.96.0
22
+ version: 1.96.1
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - '='
28
28
  - !ruby/object:Gem::Version
29
- version: 1.96.0
29
+ version: 1.96.1
30
30
  description: a wiki approach to stuctured data, dynamic interaction, and web design
31
31
  email:
32
32
  - info@decko.org
@@ -113,6 +113,7 @@ files:
113
113
  - lib/decko/generators/decko/templates/spec/spec_helper.rb
114
114
  - lib/decko/mods_spec_helper.rb
115
115
  - lib/decko/response.rb
116
+ - lib/decko/rest_spec_helper.rb
116
117
  - lib/decko/script_decko_loader.rb
117
118
  - lib/decko/tasks/alias.rb
118
119
  - lib/decko/tasks/cucumber.rake