card 1.16.13 → 1.16.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/db/migrate_core_cards/20150501010515_responsive_sidebar.rb +11 -0
- data/db/schema.rb +1 -1
- data/lib/card/auth.rb +3 -2
- data/lib/card/env.rb +1 -1
- data/lib/card/loader.rb +79 -40
- data/lib/card/query.rb +5 -5
- data/lib/card/query/sql_statement.rb +10 -4
- data/lib/card/query/value.rb +5 -8
- data/lib/card/set.rb +0 -1
- data/lib/cardio.rb +18 -22
- data/mod/01_core/chunk/link.rb +37 -34
- data/mod/01_core/chunk/query_reference.rb +1 -1
- data/mod/01_core/set/all/fetch.rb +66 -58
- data/mod/01_core/set/all/permissions.rb +84 -83
- data/mod/01_core/set/all/templating.rb +6 -5
- data/mod/01_core/set/all/type.rb +16 -14
- data/mod/02_basic_types/set/all/base.rb +3 -3
- data/mod/02_basic_types/set/type/pointer.rb +4 -4
- data/mod/02_basic_types/spec/set/all/base_spec.rb +16 -1
- data/mod/03_machines/lib/javascript/wagn_mod.js.coffee +65 -0
- data/mod/05_email/set/all/follow.rb +6 -10
- data/mod/05_email/set/type/email_template.rb +1 -1
- data/mod/05_standard/lib/file_uploader.rb +39 -41
- data/mod/05_standard/set/all/account.rb +18 -20
- data/mod/05_standard/set/all/rich_html/toolbar.rb +1 -1
- data/mod/05_standard/set/right/account.rb +2 -2
- data/mod/05_standard/set/right/email.rb +14 -13
- data/mod/05_standard/set/right/password.rb +20 -12
- data/mod/05_standard/set/right/status.rb +2 -2
- data/mod/05_standard/set/self/head.rb +66 -53
- data/mod/05_standard/set/type/search_type.rb +3 -2
- data/mod/05_standard/set/type/set.rb +3 -3
- data/mod/06_bootstrap/lib/stylesheets/bootstrap_cards.scss +50 -0
- data/spec/lib/card/query_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -1
- metadata +3 -2
data/mod/01_core/chunk/link.rb
CHANGED
@@ -1,30 +1,29 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
|
-
require_dependency File.expand_path(
|
3
|
+
require_dependency File.expand_path('../reference', __FILE__)
|
4
4
|
|
5
5
|
module Card::Chunk
|
6
6
|
class Link < Reference
|
7
7
|
attr_reader :link_text
|
8
8
|
word = /\s*([^\]\|]+)\s*/
|
9
9
|
# Groups: $1, [$2]: [[$1]] or [[$1|$2]] or $3, $4: [$3][$4]
|
10
|
-
Card::Chunk.register_class self,
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
}
|
10
|
+
Card::Chunk.register_class self,
|
11
|
+
prefix_re: '\\[',
|
12
|
+
full_re: /^\[\[([^\]]+)\]\]/,
|
13
|
+
idx_char: '['
|
15
14
|
|
16
|
-
def interpret match,
|
15
|
+
def interpret match, _content
|
17
16
|
target, @link_text =
|
18
17
|
if (raw_syntax = match[1])
|
19
|
-
if i = divider_index(
|
20
|
-
[
|
18
|
+
if (i = divider_index(raw_syntax)) # [[A | B]]
|
19
|
+
[raw_syntax[0..(i-1)], raw_syntax[(i+1)..-1]]
|
21
20
|
else # [[ A ]]
|
22
|
-
[
|
21
|
+
[raw_syntax, nil]
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
25
|
@link_text = objectify @link_text
|
27
|
-
if target =~
|
26
|
+
if target =~ %r(/|mailto:)
|
28
27
|
@explicit_link = objectify target
|
29
28
|
else
|
30
29
|
@name = target
|
@@ -32,29 +31,25 @@ module Card::Chunk
|
|
32
31
|
end
|
33
32
|
|
34
33
|
def divider_index string
|
35
|
-
#there's probably a better way to do the following. point is to find the first pipe that's not inside an inclusion
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
string_copy.gsub! incl, ('x'*incl.length)
|
41
|
-
end
|
42
|
-
string_copy.index '|'
|
34
|
+
# there's probably a better way to do the following. point is to find the first pipe that's not inside an inclusion
|
35
|
+
return unless string.index '|'
|
36
|
+
string_copy = "#{string}" # had to do this to create new string?!
|
37
|
+
string.scan /\{\{[^\}]*\}\}/ do |incl|
|
38
|
+
string_copy.gsub! incl, ('x' * incl.length)
|
43
39
|
end
|
40
|
+
string_copy.index '|'
|
44
41
|
end
|
45
42
|
|
46
43
|
def objectify raw
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
44
|
+
return unless raw
|
45
|
+
raw.strip!
|
46
|
+
if raw =~ /(^|[^\\])\{\{/
|
47
|
+
Card::Content.new raw, format
|
48
|
+
else
|
49
|
+
raw
|
54
50
|
end
|
55
51
|
end
|
56
52
|
|
57
|
-
|
58
53
|
def render_link
|
59
54
|
@link_text = render_obj @link_text
|
60
55
|
|
@@ -62,7 +57,8 @@ module Card::Chunk
|
|
62
57
|
@explicit_link = render_obj @explicit_link
|
63
58
|
format.web_link @explicit_link, text: @link_text
|
64
59
|
elsif @name
|
65
|
-
format.card_link referee_name, text: @link_text,
|
60
|
+
format.card_link referee_name, text: @link_text,
|
61
|
+
known: referee_card.send_if(:known?)
|
66
62
|
end
|
67
63
|
end
|
68
64
|
|
@@ -71,19 +67,26 @@ module Card::Chunk
|
|
71
67
|
end
|
72
68
|
|
73
69
|
def inspect
|
74
|
-
"<##{self.class}:e[#{@explicit_link}]n[#{@name}]l[#{@link_text}]
|
70
|
+
"<##{self.class}:e[#{@explicit_link}]n[#{@name}]l[#{@link_text}]" \
|
71
|
+
"p[#{@process_chunk}] txt:#{@text}>"
|
75
72
|
end
|
76
73
|
|
77
74
|
def replace_reference old_name, new_name
|
78
75
|
replace_name_reference old_name, new_name
|
79
76
|
|
80
|
-
if Card::Content
|
81
|
-
@link_text.find_chunks(Card::Chunk::Reference).each
|
82
|
-
|
83
|
-
|
77
|
+
if Card::Content === @link_text
|
78
|
+
@link_text.find_chunks(Card::Chunk::Reference).each do |chunk|
|
79
|
+
chunk.replace_reference old_name, new_name
|
80
|
+
end
|
81
|
+
elsif old_name.to_name == @link_text
|
82
|
+
@link_text = new_name
|
84
83
|
end
|
85
84
|
|
86
|
-
@text = @link_text.nil?
|
85
|
+
@text = if @link_text.nil?
|
86
|
+
"[[#{referee_name}]]"
|
87
|
+
else
|
88
|
+
"[[#{referee_name}|#{@link_text}]]"
|
89
|
+
end
|
87
90
|
end
|
88
91
|
end
|
89
92
|
end
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# = Card#fetch
|
2
2
|
#
|
3
|
-
# A multipurpose retrieval operator that
|
4
|
-
|
3
|
+
# A multipurpose retrieval operator that integrates caching, database lookups,
|
4
|
+
# and "virtual" card construction
|
5
5
|
module ClassMethods
|
6
|
-
|
7
6
|
# === fetch
|
8
7
|
#
|
9
8
|
# looks for cards in
|
@@ -23,7 +22,7 @@ module ClassMethods
|
|
23
22
|
# :local_only Use only local cache for lookup and storing
|
24
23
|
# new: { card opts } Return a new card when not found
|
25
24
|
#
|
26
|
-
def fetch mark, opts
|
25
|
+
def fetch mark, opts={}
|
27
26
|
validate_fetch_opts! opts
|
28
27
|
mark = normalize_mark mark
|
29
28
|
|
@@ -43,22 +42,25 @@ module ClassMethods
|
|
43
42
|
end
|
44
43
|
|
45
44
|
write_to_cache card, opts if needs_caching
|
45
|
+
standard_fetch_results card, mark, opts
|
46
|
+
end
|
46
47
|
|
48
|
+
def standard_fetch_results card, mark, opts
|
47
49
|
if card.new_card?
|
48
50
|
case
|
49
51
|
when opts[:new].present? then return card.renew(opts)
|
50
52
|
when opts[:new] # noop for empty hash
|
51
53
|
when opts[:skip_virtual] then return nil
|
52
54
|
end
|
53
|
-
card.
|
55
|
+
card.name_from_mark! mark, opts
|
54
56
|
end
|
55
57
|
# need to load modules here to call the right virtual? method
|
56
58
|
card.include_set_modules unless opts[:skip_modules]
|
57
59
|
card if opts[:new] || card.known?
|
58
60
|
end
|
59
61
|
|
60
|
-
def fetch_local mark, opts
|
61
|
-
fetch mark, opts.merge(:
|
62
|
+
def fetch_local mark, opts={}
|
63
|
+
fetch mark, opts.merge(local_only: true)
|
62
64
|
end
|
63
65
|
|
64
66
|
def fetch_id mark
|
@@ -76,7 +78,7 @@ module ClassMethods
|
|
76
78
|
fetch mark, skip_virtual: true, skip_modules: true
|
77
79
|
end
|
78
80
|
|
79
|
-
def assign_or_initialize_by name, attributes, fetch_opts
|
81
|
+
def assign_or_initialize_by name, attributes, fetch_opts={}
|
80
82
|
if (known_card = Card.fetch(name, fetch_opts))
|
81
83
|
known_card.refresh.assign_attributes attributes
|
82
84
|
known_card
|
@@ -99,24 +101,24 @@ module ClassMethods
|
|
99
101
|
card.present?
|
100
102
|
end
|
101
103
|
|
102
|
-
def expire name, subcards
|
104
|
+
def expire name, subcards=false
|
103
105
|
# note: calling instance method breaks on dirty names
|
104
106
|
key = name.to_name.key
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
111
|
-
Card.cache.delete key
|
112
|
-
Card.cache.delete "~#{card.id}" if card.id
|
107
|
+
return unless (card = Card.cache.read key)
|
108
|
+
if subcards
|
109
|
+
card.expire_subcards
|
110
|
+
else
|
111
|
+
card.preserve_subcards
|
113
112
|
end
|
114
|
-
|
113
|
+
Card.cache.delete key
|
114
|
+
Card.cache.delete "~#{card.id}" if card.id
|
115
115
|
end
|
116
116
|
|
117
117
|
# set_names reverse map (cached)
|
118
|
-
|
119
|
-
|
118
|
+
# FIXME: move to set handling
|
119
|
+
def cached_set_members key
|
120
|
+
set_cache_list = Card.cache.read "$#{key}"
|
121
|
+
set_cache_list.nil? ? [] : set_cache_list.keys
|
120
122
|
end
|
121
123
|
|
122
124
|
def set_members set_names, key
|
@@ -135,9 +137,8 @@ module ClassMethods
|
|
135
137
|
end
|
136
138
|
|
137
139
|
def validate_fetch_opts! opts
|
138
|
-
|
139
|
-
|
140
|
-
end
|
140
|
+
return unless opts[:new] && opts[:skip_virtual]
|
141
|
+
fail Card::Error, 'fetch called with new args and skip_virtual'
|
141
142
|
end
|
142
143
|
|
143
144
|
def cache
|
@@ -145,45 +146,59 @@ module ClassMethods
|
|
145
146
|
end
|
146
147
|
|
147
148
|
def fetch_from_cache cache_key, local_only=false
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
149
|
+
return unless Card.cache
|
150
|
+
if local_only
|
151
|
+
Card.cache.read_local cache_key
|
152
|
+
else
|
153
|
+
Card.cache.read cache_key
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def parse_mark! mark, opts
|
158
|
+
# return mark_type, mark_value, and absolutized mark
|
159
|
+
if mark.is_a? Integer
|
160
|
+
[:id, mark, mark]
|
161
|
+
else
|
162
|
+
fullname = fullname_from_name mark, opts[:new]
|
163
|
+
[:key, fullname.key, fullname.s]
|
154
164
|
end
|
155
165
|
end
|
156
166
|
|
157
167
|
def fetch_from_cache_or_db mark, opts
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
if
|
165
|
-
|
166
|
-
|
167
|
-
card = fetch_from_db query
|
168
|
+
mark_type, mark_key, mark = parse_mark! mark, opts
|
169
|
+
needs_caching = false # until proven true :)
|
170
|
+
|
171
|
+
# look in cache
|
172
|
+
card = send "fetch_from_cache_by_#{mark_type}", mark_key, opts[:local_only]
|
173
|
+
|
174
|
+
# if that doesn't work, look in db
|
175
|
+
if card.nil? || retrieve_trashed_from_db?(card, opts)
|
176
|
+
card = fetch_from_db mark_type, mark_key, opts
|
168
177
|
needs_caching = card && !card.trash
|
169
|
-
card.restore_subcards if card
|
170
178
|
end
|
171
179
|
|
172
180
|
[card, mark, needs_caching]
|
173
181
|
end
|
174
182
|
|
175
|
-
def
|
176
|
-
|
177
|
-
|
178
|
-
|
183
|
+
def retrieve_trashed_from_db? card, opts
|
184
|
+
opts[:look_in_trash] && card.new_card? && !card.trash
|
185
|
+
end
|
186
|
+
|
187
|
+
def fetch_from_cache_by_id id, local_only=false
|
188
|
+
name = fetch_from_cache "~#{id}", local_only
|
189
|
+
fetch_from_cache name, local_only if name
|
179
190
|
end
|
180
191
|
|
181
|
-
def fetch_from_cache_by_key key, local_only
|
192
|
+
def fetch_from_cache_by_key key, local_only=false
|
182
193
|
fetch_from_cache key, local_only
|
183
194
|
end
|
184
195
|
|
185
|
-
def fetch_from_db
|
186
|
-
|
196
|
+
def fetch_from_db mark_type, mark_key, opts
|
197
|
+
query = { mark_type => mark_key }
|
198
|
+
query[:trash] = false unless opts[:look_in_trash]
|
199
|
+
card = Card.where(query).take
|
200
|
+
card.restore_subcards if card
|
201
|
+
card
|
187
202
|
end
|
188
203
|
|
189
204
|
def new_for_cache name, opts
|
@@ -197,7 +212,7 @@ module ClassMethods
|
|
197
212
|
# different from the cached variant
|
198
213
|
# and can postpone type lookup for the cached variant
|
199
214
|
# if skipping virtual no need to look for actual type
|
200
|
-
opts[:skip_virtual] || opts[:new].present?
|
215
|
+
opts[:skip_virtual] || opts[:new].present? || opts[:skip_type_lookup]
|
201
216
|
end
|
202
217
|
|
203
218
|
def write_to_cache card, opts
|
@@ -215,14 +230,6 @@ module ClassMethods
|
|
215
230
|
Card.cache.write_local "~#{card.id}", card.key if card.id && card.id != 0
|
216
231
|
end
|
217
232
|
|
218
|
-
def expand_mark mark, opts
|
219
|
-
if mark.is_a?(Integer)
|
220
|
-
mark
|
221
|
-
else
|
222
|
-
fullname_from_name(mark, opts[:new]).key
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
233
|
def normalize_mark mark
|
227
234
|
case mark
|
228
235
|
when String
|
@@ -242,7 +249,7 @@ module ClassMethods
|
|
242
249
|
end
|
243
250
|
|
244
251
|
def fullname_from_name name, new_opts={}
|
245
|
-
if new_opts && supercard = new_opts[:supercard]
|
252
|
+
if new_opts && (supercard = new_opts[:supercard])
|
246
253
|
name.to_name.to_absolute_name supercard.name
|
247
254
|
else
|
248
255
|
name.to_name
|
@@ -304,7 +311,8 @@ def type_unknown?
|
|
304
311
|
type_id.nil?
|
305
312
|
end
|
306
313
|
|
307
|
-
def
|
314
|
+
def name_from_mark! mark, opts
|
315
|
+
return if opts[:local_only]
|
308
316
|
return unless mark && mark.to_s != name
|
309
317
|
self.name = mark.to_s
|
310
318
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
|
2
|
-
Card.error_codes.merge! permission_denied: [:denial, 403],
|
3
|
-
|
2
|
+
Card.error_codes.merge! permission_denied: [:denial, 403],
|
3
|
+
captcha: [:errors, 449]
|
4
4
|
|
5
5
|
# ok? and ok! are public facing methods to approve one action at a time
|
6
6
|
#
|
7
7
|
# fetching: if the optional :trait parameter is supplied, it is passed
|
8
8
|
# to fetch and the test is perfomed on the fetched card, therefore:
|
9
9
|
#
|
10
|
-
# trait: :account
|
11
|
-
# trait: :roles, new: {} would initialize a new card with default ({})
|
12
|
-
|
10
|
+
# trait: :account would fetch this card plus a tag codenamed :account
|
11
|
+
# trait: :roles, new: {} would initialize a new card with default ({})
|
12
|
+
# options.
|
13
13
|
|
14
14
|
def ok? action
|
15
15
|
@action_ok = true
|
@@ -21,31 +21,35 @@ def ok_with_fetch? action, opts={}
|
|
21
21
|
card = opts[:trait].nil? ? self : fetch(opts)
|
22
22
|
card && card.ok_without_fetch?(action)
|
23
23
|
end
|
24
|
-
alias_method_chain :ok?, :fetch # note: method is chained so that we can return the instance variable @action_ok
|
25
24
|
|
25
|
+
# note: method is chained so that we can return the instance variable @action_ok
|
26
|
+
alias_method_chain :ok?, :fetch
|
26
27
|
|
27
28
|
def ok! action, opts={}
|
28
29
|
raise Card::PermissionDenied.new self unless ok? action, opts
|
29
30
|
end
|
30
31
|
|
31
32
|
def who_can action
|
32
|
-
#warn "who_can[#{name}] #{(prc=permission_rule_card(action)).inspect},
|
33
|
+
# warn "who_can[#{name}] #{(prc=permission_rule_card(action)).inspect},
|
34
|
+
# #{prc.first.item_cards.map(&:id)}" if action == :update
|
33
35
|
permission_rule_card(action).first.item_cards.map &:id
|
34
36
|
end
|
35
37
|
|
36
|
-
|
37
38
|
def permission_rule_card action
|
38
39
|
opcard = rule_card action
|
39
40
|
|
40
|
-
|
41
|
+
# RULE missing. should not be possible.
|
42
|
+
# generalize this to handling of all required rules
|
43
|
+
unless opcard
|
41
44
|
errors.add :permission_denied, "No #{action} rule for #{name}"
|
42
45
|
raise Card::PermissionDenied.new(self)
|
43
46
|
end
|
44
47
|
|
45
48
|
rcard = Auth.as_bot do
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
# compound cards can inherit permissions from left parent
|
50
|
+
if ['_left', '[[_left]]'].member?(opcard.db_content) && self.junction?
|
51
|
+
lcard = left_or_new(skip_virtual: true, skip_modules: true)
|
52
|
+
if action == :create && lcard.real? && !lcard.action == :create
|
49
53
|
action = :update
|
50
54
|
end
|
51
55
|
lcard.permission_rule_card(action).first
|
@@ -64,67 +68,61 @@ def you_cant what
|
|
64
68
|
"You don't have permission to #{what}"
|
65
69
|
end
|
66
70
|
|
67
|
-
|
68
71
|
def deny_because why
|
69
72
|
@permission_errors << why if @permission_errors
|
70
73
|
@action_ok = false
|
71
74
|
end
|
72
75
|
|
73
76
|
def permitted? action
|
77
|
+
return if Card.config.read_only
|
78
|
+
return true if action != :comment and Auth.always_ok?
|
74
79
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
permitted_ids
|
79
|
-
|
80
|
-
|
81
|
-
!permitted_ids.empty?
|
82
|
-
else
|
83
|
-
Auth.among? permitted_ids
|
84
|
-
end
|
80
|
+
permitted_ids = who_can action
|
81
|
+
if action == :comment && Auth.always_ok?
|
82
|
+
# admin can comment if anyone can
|
83
|
+
!permitted_ids.empty?
|
84
|
+
else
|
85
|
+
Auth.among? permitted_ids
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
88
89
|
def permit action, verb=nil
|
89
|
-
|
90
90
|
if Card.config.read_only # not called by ok_to_read
|
91
|
-
deny_because
|
91
|
+
deny_because 'Currently in read-only mode'
|
92
92
|
end
|
93
93
|
|
94
|
+
return if permitted? action
|
94
95
|
verb ||= action.to_s
|
95
|
-
|
96
|
-
deny_because you_cant("#{verb} #{name.present? ? name : 'this'}")
|
97
|
-
end
|
96
|
+
deny_because you_cant("#{verb} #{name.present? ? name : 'this'}")
|
98
97
|
end
|
99
98
|
|
100
99
|
def ok_to_create
|
101
100
|
permit :create
|
102
|
-
if
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
101
|
+
return if !@action_ok || !junction?
|
102
|
+
|
103
|
+
[:left, :right].each do |side|
|
104
|
+
# left is supercard; create permissions will get checked there.
|
105
|
+
next if side == :left && @superleft
|
106
|
+
part_card = send side, new: {}
|
107
|
+
if part_card && part_card.new_card? # if no card, there must be other errors
|
108
|
+
unless part_card.ok? :create
|
109
|
+
deny_because you_cant("create #{part_card.name}")
|
110
110
|
end
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
115
|
def ok_to_read
|
116
|
-
if
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
121
|
-
end
|
116
|
+
return if Auth.always_ok?
|
117
|
+
@read_rule_id ||= permission_rule_card(:read).first.id.to_i
|
118
|
+
return if Auth.as_card.read_rules.member? @read_rule_id
|
119
|
+
deny_because you_cant 'read this'
|
122
120
|
end
|
123
121
|
|
124
122
|
def ok_to_update
|
125
123
|
permit :update
|
126
|
-
if @action_ok
|
127
|
-
deny_because you_cant(
|
124
|
+
if @action_ok && type_id_changed? && !permitted?(:create)
|
125
|
+
deny_because you_cant('change to this type (need create permission)')
|
128
126
|
end
|
129
127
|
ok_to_read if @action_ok
|
130
128
|
end
|
@@ -135,13 +133,11 @@ end
|
|
135
133
|
|
136
134
|
def ok_to_comment
|
137
135
|
permit :comment, 'comment on'
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
136
|
+
return unless @action_ok
|
137
|
+
deny_because 'No comments allowed on templates' if is_template?
|
138
|
+
deny_because 'No comments allowed on structured content' if structure
|
142
139
|
end
|
143
140
|
|
144
|
-
|
145
141
|
event :set_read_rule, before: :store do
|
146
142
|
if trash == true
|
147
143
|
self.read_rule_id = self.read_rule_class = nil
|
@@ -150,7 +146,8 @@ event :set_read_rule, before: :store do
|
|
150
146
|
rcard, rclass = permission_rule_card(:read)
|
151
147
|
self.read_rule_id = rcard.id
|
152
148
|
self.read_rule_class = rclass
|
153
|
-
#find all cards with me as trunk and update their read_rule
|
149
|
+
# find all cards with me as trunk and update their read_rule
|
150
|
+
# (because of *type plus right)
|
154
151
|
# skip if name is updated because will already be resaved
|
155
152
|
|
156
153
|
if !new_card? && type_id_changed?
|
@@ -168,16 +165,18 @@ def update_read_rule
|
|
168
165
|
|
169
166
|
reset_patterns # why is this needed?
|
170
167
|
rcard, rclass = permission_rule_card :read
|
171
|
-
|
172
|
-
|
168
|
+
# these two are just to make sure vals are correct on current object
|
169
|
+
self.read_rule_id = rcard.id
|
170
|
+
# warn "updating read rule for #{inspect} to #{rcard.inspect}, #{rclass}"
|
173
171
|
|
174
172
|
self.read_rule_class = rclass
|
175
|
-
Card.where(id:
|
173
|
+
Card.where(id: id).update_all read_rule_id: rcard.id, read_rule_class: rclass
|
176
174
|
expire
|
177
175
|
|
178
|
-
# currently doing a brute force search for every card that may be impacted.
|
176
|
+
# currently doing a brute force search for every card that may be impacted.
|
177
|
+
# may want to optimize(?)
|
179
178
|
Auth.as_bot do
|
180
|
-
Card.search(left:
|
179
|
+
Card.search(left: name).each do |plus_card|
|
181
180
|
if plus_card.rule(:read) == '_left'
|
182
181
|
plus_card.update_read_rule
|
183
182
|
end
|
@@ -192,13 +191,13 @@ def add_to_read_rule_update_queue updates
|
|
192
191
|
@read_rule_update_queue = Array.wrap(@read_rule_update_queue).concat updates
|
193
192
|
end
|
194
193
|
|
195
|
-
|
196
194
|
event :check_permissions, after: :approve do
|
197
|
-
task =
|
198
|
-
:comment
|
199
|
-
|
200
|
-
|
201
|
-
|
195
|
+
task =
|
196
|
+
if @action != :delete && comment # will be obviated by new comment handling
|
197
|
+
:comment
|
198
|
+
else
|
199
|
+
@action
|
200
|
+
end
|
202
201
|
track_permission_errors do
|
203
202
|
ok? task
|
204
203
|
end
|
@@ -216,19 +215,22 @@ def track_permission_errors
|
|
216
215
|
result
|
217
216
|
end
|
218
217
|
|
219
|
-
|
220
218
|
def recaptcha_on?
|
221
219
|
have_recaptcha_keys? &&
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
220
|
+
Env[:controller] &&
|
221
|
+
!Auth.signed_in? &&
|
222
|
+
!Auth.needs_setup? &&
|
223
|
+
!Auth.always_ok? &&
|
224
|
+
Card.toggle(rule :captcha)
|
227
225
|
end
|
228
226
|
|
229
227
|
def have_recaptcha_keys?
|
230
|
-
@@have_recaptcha_keys =
|
231
|
-
|
228
|
+
@@have_recaptcha_keys =
|
229
|
+
if defined?(@@have_recaptcha_keys)
|
230
|
+
@@have_recaptcha_keys
|
231
|
+
else
|
232
|
+
!!(Card.config.recaptcha_public_key && Card.config.recaptcha_private_key)
|
233
|
+
end
|
232
234
|
end
|
233
235
|
|
234
236
|
event :recaptcha, before: :approve do
|
@@ -239,21 +241,23 @@ event :recaptcha, before: :approve do
|
|
239
241
|
end
|
240
242
|
|
241
243
|
module Accounts
|
242
|
-
# This is a short-term hack that is used in account-related cards to allow a
|
243
|
-
# permissions are restricted to the owner of the
|
244
|
-
#
|
245
|
-
#
|
244
|
+
# This is a short-term hack that is used in account-related cards to allow a
|
245
|
+
# permissions pattern where permissions are restricted to the owner of the
|
246
|
+
# account (and, by default, Admin)
|
247
|
+
# That pattern should be permitted by our card representation
|
248
|
+
# (without creating separate rules for each account holder) but is not yet.
|
246
249
|
|
247
250
|
def permit action, verb=nil
|
248
251
|
case
|
249
|
-
when action
|
250
|
-
when action
|
251
|
-
#restricts account creation to subcard handling on permitted card
|
252
|
-
|
253
|
-
|
252
|
+
when action == :comment then @action_ok = false
|
253
|
+
when action == :create then @superleft ? true : super(action, verb)
|
254
|
+
# restricts account creation to subcard handling on permitted card
|
255
|
+
# (unless explicitly permitted)
|
256
|
+
when own_account? then true
|
257
|
+
else
|
258
|
+
super action, verb
|
254
259
|
end
|
255
260
|
end
|
256
|
-
|
257
261
|
end
|
258
262
|
|
259
263
|
module Follow
|
@@ -271,13 +275,10 @@ module Follow
|
|
271
275
|
|
272
276
|
def permit action, verb=nil
|
273
277
|
if [:create, :delete, :update].include?(action) && Auth.signed_in? &&
|
274
|
-
|
278
|
+
(user = rule_user) && Auth.current_id == user.id
|
275
279
|
return true
|
276
280
|
else
|
277
281
|
super action, verb
|
278
282
|
end
|
279
283
|
end
|
280
|
-
|
281
284
|
end
|
282
|
-
|
283
|
-
|