card 1.16.12 → 1.16.13
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/card.gemspec +1 -1
- data/db/migrate_core_cards/20130823192433_add_style_cards.rb +39 -24
- data/db/migrate_core_cards/20140629222005_add_email_cards.rb +6 -11
- data/db/migrate_core_cards/20151120180631_add_token_expiration.rb +7 -0
- data/db/seed/new/card_actions.yml +396 -388
- data/db/seed/new/card_acts.yml +1 -595
- data/db/seed/new/card_changes.yml +8154 -23619
- data/db/seed/new/card_references.yml +1009 -988
- data/db/seed/new/cards.yml +1445 -1423
- data/db/seed/test/fixtures/card_actions.yml +1375 -1399
- data/db/seed/test/fixtures/card_acts.yml +445 -1063
- data/db/seed/test/fixtures/card_changes.yml +11440 -26881
- data/db/seed/test/fixtures/card_references.yml +1523 -1502
- data/db/seed/test/fixtures/cards.yml +2736 -2715
- data/db/seed/test/seed.rb +7 -10
- data/db/version_core_cards.txt +1 -1
- data/lib/card/auth.rb +65 -19
- data/lib/card/cache.rb +18 -18
- data/lib/card/env.rb +10 -10
- data/lib/card/format.rb +41 -30
- data/lib/card/location.rb +3 -5
- data/lib/card/subcards.rb +0 -3
- data/lib/card/success.rb +14 -11
- data/mod/01_core/set/all/subcards.rb +4 -2
- data/mod/01_core/set/all/trash.rb +4 -1
- data/mod/02_basic_types/set/type/pointer.rb +5 -2
- data/mod/05_email/set/all/notify.rb +85 -73
- data/mod/05_email/spec/set/all/notify_spec.rb +74 -55
- data/mod/05_standard/set/all/comment.rb +18 -12
- data/mod/05_standard/set/all/error.rb +5 -1
- data/mod/05_standard/set/right/account.rb +50 -73
- data/mod/05_standard/set/right/token.rb +49 -2
- data/mod/05_standard/set/self/signin.rb +14 -12
- data/mod/05_standard/set/type/signup.rb +17 -21
- data/mod/05_standard/spec/set/all/account_spec.rb +1 -1
- data/mod/05_standard/spec/set/right/account_spec.rb +76 -52
- data/mod/05_standard/spec/set/right/password_spec.rb +10 -11
- data/mod/05_standard/spec/set/right/token_spec.rb +19 -1
- data/mod/05_standard/spec/set/type/signup_spec.rb +3 -4
- data/spec/lib/card/auth_spec.rb +46 -5
- metadata +5 -4
data/db/seed/test/seed.rb
CHANGED
@@ -2,19 +2,17 @@
|
|
2
2
|
require 'timecop'
|
3
3
|
|
4
4
|
class SharedData
|
5
|
-
#attr_accessor :users
|
6
5
|
USERS = [
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
'Joe User', 'Joe Admin', 'Joe Camel', 'Sample User', 'No count',
|
7
|
+
'u1', 'u2', 'u3',
|
8
|
+
'Big Brother', 'Optic fan', 'Sunglasses fan', 'Narcissist'
|
9
|
+
]
|
11
10
|
|
12
11
|
def self.account_args hash
|
13
|
-
{ "+*account" => { "+*password" =>'joe_pass' }.merge(
|
12
|
+
{ "+*account" => { "+*password" => 'joe_pass' }.merge(hash) }
|
14
13
|
end
|
15
14
|
|
16
15
|
def self.add_test_data
|
17
|
-
|
18
16
|
Card::Cache.reset_global
|
19
17
|
Card::Env.reset
|
20
18
|
Card::Auth.as_bot
|
@@ -52,13 +50,12 @@ class SharedData
|
|
52
50
|
#above still necessary? try commenting out above and 'Sign up' below
|
53
51
|
Card::Auth.current_id = Card::WagnBotID # need to reset after creating sign up, which changes current_id for extend phase
|
54
52
|
|
53
|
+
no_samples = %( user sign_up set number list listed_by )
|
55
54
|
Card::Auth.createable_types.each do |type|
|
56
|
-
next if
|
55
|
+
next if no_samples.include? type.to_name.key
|
57
56
|
Card.create! type: type, name: "Sample #{type}"
|
58
57
|
end
|
59
58
|
|
60
|
-
|
61
|
-
|
62
59
|
# data for role_test.rb
|
63
60
|
|
64
61
|
Card.create! name: 'u1', type_code: 'user', subcards: account_args('+*email'=>'u1@user.com', '+*password'=>'u1_pass')
|
data/db/version_core_cards.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
20151120180631
|
data/lib/card/auth.rb
CHANGED
@@ -13,33 +13,67 @@ class Card
|
|
13
13
|
class << self
|
14
14
|
# Authenticates a user by their login name and unencrypted password.
|
15
15
|
def authenticate email, password
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
account = Auth[email]
|
17
|
+
case
|
18
|
+
when !account then nil
|
19
|
+
when !account.active? then nil
|
20
|
+
when Card.config.no_authentication then account
|
21
|
+
when password_valid?(account, password.strip) then account
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def password_valid? account, password
|
26
26
|
account.password == encrypt(password, account.salt)
|
27
27
|
end
|
28
28
|
|
29
|
+
def set_current_from_token token, current=nil
|
30
|
+
account = find_by_token token
|
31
|
+
if account && account.validate_token!(token)
|
32
|
+
unless current && always_ok_usr_id?(account.left_id)
|
33
|
+
current = account.left_id
|
34
|
+
end
|
35
|
+
set_current_from_mark current
|
36
|
+
elsif Env.params[:live_token]
|
37
|
+
true
|
38
|
+
# Used for activations and resets.
|
39
|
+
# Continue as anonymous and address problem later
|
40
|
+
else
|
41
|
+
false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_current_from_mark mark
|
46
|
+
self.current_id =
|
47
|
+
if mark.to_s =~ /@/
|
48
|
+
account = Auth[mark.downcase]
|
49
|
+
account && account.active? ? account.left_id : Card::AnonymousID
|
50
|
+
else
|
51
|
+
mark
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_by_token token
|
56
|
+
Auth.as_bot do
|
57
|
+
Card.search(
|
58
|
+
right_id: Card::AccountID,
|
59
|
+
right_plus: [{ id: Card::TokenID }, { content: token.strip }]
|
60
|
+
).first
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
29
64
|
# Encrypts some data with the salt.
|
30
65
|
def encrypt password, salt
|
31
66
|
Digest::SHA1.hexdigest "#{salt}--#{password}--"
|
32
67
|
end
|
33
68
|
|
34
|
-
# find
|
69
|
+
# find account by email
|
35
70
|
def [] email
|
71
|
+
email = email.strip.downcase
|
36
72
|
Auth.as_bot do
|
37
|
-
Card.search(
|
38
|
-
|
39
|
-
{
|
40
|
-
|
41
|
-
] }
|
42
|
-
]).first
|
73
|
+
Card.search(
|
74
|
+
right_id: Card::AccountID,
|
75
|
+
right_plus: [{ id: Card::EmailID }, { content: email }]
|
76
|
+
).first
|
43
77
|
end
|
44
78
|
end
|
45
79
|
|
@@ -78,6 +112,7 @@ class Card
|
|
78
112
|
|
79
113
|
def current_id= card_id
|
80
114
|
@@current = @@as_id = @@as_card = nil
|
115
|
+
card_id = card_id.to_i if card_id.present?
|
81
116
|
@@current_id = card_id
|
82
117
|
end
|
83
118
|
|
@@ -90,15 +125,21 @@ class Card
|
|
90
125
|
end
|
91
126
|
|
92
127
|
def as given_user
|
93
|
-
tmp_id
|
128
|
+
tmp_id = @@as_id
|
129
|
+
tmp_card = @@as_card
|
130
|
+
|
131
|
+
@@as_id = get_user_id(given_user)
|
132
|
+
@@as_card = nil
|
94
133
|
# we could go ahead and set as_card if given a card...
|
95
|
-
@@as_id, @@as_card = get_user_id(given_user), nil
|
96
134
|
|
97
135
|
@@current_id = @@as_id if @@current_id.nil?
|
98
136
|
|
99
137
|
return unless block_given?
|
100
138
|
value = yield
|
101
|
-
|
139
|
+
|
140
|
+
@@as_id = tmp_id
|
141
|
+
@@as_card = tmp_card
|
142
|
+
|
102
143
|
value
|
103
144
|
end
|
104
145
|
|
@@ -146,8 +187,12 @@ class Card
|
|
146
187
|
end
|
147
188
|
|
148
189
|
def always_ok?
|
149
|
-
|
150
|
-
return false
|
190
|
+
usr_id = as_id
|
191
|
+
return false if !usr_id
|
192
|
+
always_ok_usr_id? usr_id
|
193
|
+
end
|
194
|
+
|
195
|
+
def always_ok_usr_id? usr_id
|
151
196
|
return true if usr_id == Card::WagnBotID # cannot disable
|
152
197
|
|
153
198
|
always = Card.cache.read('ALWAYS') || {}
|
@@ -163,6 +208,7 @@ class Card
|
|
163
208
|
# warn Rails.logger.warn("aok? #{usr_id}, #{always[usr_id]}")
|
164
209
|
always[usr_id]
|
165
210
|
end
|
211
|
+
|
166
212
|
# PERMISSIONS
|
167
213
|
|
168
214
|
def createable_types
|
data/lib/card/cache.rb
CHANGED
@@ -54,11 +54,13 @@ class Card
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def generate_cache_id
|
57
|
-
((Time.now.to_f * 100).to_i).to_s +
|
57
|
+
((Time.now.to_f * 100).to_i).to_s +
|
58
|
+
('a'..'z').to_a[rand(26)] +
|
59
|
+
('a'..'z').to_a[rand(26)]
|
58
60
|
end
|
59
61
|
|
60
62
|
def reset_global
|
61
|
-
cache_by_class.each do |
|
63
|
+
cache_by_class.each do |_klass, cache|
|
62
64
|
cache.reset hard=true
|
63
65
|
end
|
64
66
|
Card::Codename.reset_cache
|
@@ -67,9 +69,11 @@ class Card
|
|
67
69
|
|
68
70
|
def reset_local
|
69
71
|
cache_by_class.each do |cc, cache|
|
70
|
-
if Card::Cache===cache
|
72
|
+
if Card::Cache === cache
|
71
73
|
cache.reset_local
|
72
|
-
else
|
74
|
+
else
|
75
|
+
warn "reset class #{cc}, #{cache.class} #{caller[0..8] * "\n"} ???"
|
76
|
+
end
|
73
77
|
end
|
74
78
|
end
|
75
79
|
|
@@ -91,20 +95,16 @@ class Card
|
|
91
95
|
private
|
92
96
|
|
93
97
|
def prepopulate
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
98
|
+
return unless @@prepopulating
|
99
|
+
@@rule_cache ||= Card.rule_cache
|
100
|
+
@@user_ids_cache ||= Card.user_ids_cache
|
101
|
+
@@read_rule_cache ||= Card.read_rule_cache
|
102
|
+
@@rule_keys_cache ||= Card.rule_keys_cache
|
103
|
+
Card.cache.write_local 'RULES', @@rule_cache
|
104
|
+
Card.cache.write_local 'READRULES', @@read_rule_cache
|
105
|
+
Card.cache.write_local 'USER_IDS', @@user_ids_cache
|
106
|
+
Card.cache.write_local 'RULE_KEYS', @@rule_keys_cache
|
104
107
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
108
|
end
|
109
109
|
|
110
110
|
attr_reader :prefix, :store, :klass
|
@@ -179,7 +179,7 @@ class Card
|
|
179
179
|
|
180
180
|
def delete key
|
181
181
|
@store.delete(@prefix + key) if @store
|
182
|
-
|
182
|
+
delete_local key
|
183
183
|
end
|
184
184
|
|
185
185
|
def delete_local key
|
data/lib/card/env.rb
CHANGED
@@ -66,29 +66,29 @@ class Card
|
|
66
66
|
#include Card::Location
|
67
67
|
|
68
68
|
def location_history
|
69
|
-
#warn "sess #{session.class}, #{session.object_id}"
|
70
69
|
session[:history] ||= [Card::Location.card_path('')]
|
71
|
-
if session[:history]
|
72
|
-
|
73
|
-
session[:history]
|
74
|
-
end
|
70
|
+
session[:history].shift if session[:history].size > 5
|
71
|
+
session[:history]
|
75
72
|
end
|
76
73
|
|
77
74
|
def save_location card
|
78
|
-
return if Env.ajax? || !Env.html? || !card.known? ||
|
75
|
+
return if Env.ajax? || !Env.html? || !card.known? ||
|
76
|
+
(card.codename == 'signin')
|
79
77
|
discard_locations_for card
|
80
|
-
session[:previous_location] =
|
78
|
+
session[:previous_location] =
|
79
|
+
Card::Location.card_path card.cardname.url_key
|
81
80
|
location_history.push previous_location
|
82
81
|
end
|
83
82
|
|
84
83
|
def previous_location
|
85
|
-
|
84
|
+
return unless location_history
|
85
|
+
session[:previous_location] ||= location_history.last
|
86
86
|
end
|
87
87
|
|
88
|
-
def discard_locations_for
|
88
|
+
def discard_locations_for card
|
89
89
|
# quoting necessary because cards have things like "+*" in the names..
|
90
90
|
session[:history] = location_history.reject do |loc|
|
91
|
-
if url_key = url_key_for_location(loc)
|
91
|
+
if (url_key = url_key_for_location(loc))
|
92
92
|
url_key.to_name.key == card.key
|
93
93
|
end
|
94
94
|
end.compact
|
data/lib/card/format.rb
CHANGED
@@ -443,8 +443,9 @@ class Card
|
|
443
443
|
end
|
444
444
|
|
445
445
|
def nest nested_card, opts={}
|
446
|
-
#ActiveSupport::Notifications.instrument('card', message:
|
447
|
-
|
446
|
+
# ActiveSupport::Notifications.instrument('card', message:
|
447
|
+
# "nest: #{nested_card.name}, #{opts}") do
|
448
|
+
opts.delete_if { |_k, v| v.nil? }
|
448
449
|
opts.reverse_merge! inclusion_defaults(nested_card)
|
449
450
|
|
450
451
|
sub = nil
|
@@ -455,37 +456,48 @@ class Card
|
|
455
456
|
sub.inclusion_opts = opts[:items] ? opts[:items].clone : {}
|
456
457
|
end
|
457
458
|
|
458
|
-
|
459
459
|
view = canonicalize_view opts.delete :view
|
460
460
|
opts[:home_view] = [:closed, :edit].member?(view) ? :open : view
|
461
461
|
# FIXME: special views should be represented in view definitions
|
462
462
|
|
463
|
-
view =
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
when :closed
|
470
|
-
case
|
471
|
-
when @@closed_views[view] == true || @@error_codes[view] ; view
|
472
|
-
when specified_view = @@closed_views[view] ; specified_view
|
473
|
-
when !nested_card.known? ; :closed_missing
|
474
|
-
else ; :closed_content
|
463
|
+
view =
|
464
|
+
case @mode
|
465
|
+
when :edit then view_in_edit_mode(view, nested_card)
|
466
|
+
when :template then :template_rule
|
467
|
+
when :closed then view_in_closed_mode(view, nested_card)
|
468
|
+
else view
|
475
469
|
end
|
476
|
-
else
|
477
|
-
view
|
478
|
-
end
|
479
470
|
|
480
471
|
sub.optional_render view, opts
|
481
|
-
#end
|
472
|
+
# end
|
473
|
+
end
|
474
|
+
|
475
|
+
def view_in_edit_mode homeview, nested_card
|
476
|
+
not_in_form =
|
477
|
+
@@perms[homeview] == :none || # view configured not to keep in form
|
478
|
+
nested_card.structure || # not yet nesting structures
|
479
|
+
nested_card.key.blank? # eg {{_self|type}} on new cards
|
480
|
+
|
481
|
+
not_in_form ? :blank : :edit_in_form
|
482
|
+
end
|
483
|
+
|
484
|
+
def view_in_closed_mode homeview, nested_card
|
485
|
+
approved_view = @@closed_views[homeview]
|
486
|
+
case
|
487
|
+
when approved_view == true then homeview
|
488
|
+
when @@error_codes[homeview] then homeview
|
489
|
+
when approved_view then approved_view
|
490
|
+
when !nested_card.known? then :closed_missing
|
491
|
+
else :closed_content
|
492
|
+
end
|
482
493
|
end
|
483
494
|
|
484
495
|
def get_inclusion_content cardname
|
485
|
-
content = params[cardname.to_s.
|
496
|
+
content = params[cardname.to_s.tr('+', '_')]
|
486
497
|
|
487
|
-
# CLEANME This is a hack
|
488
|
-
|
498
|
+
# CLEANME This is a hack so plus cards re-populate on failed signups
|
499
|
+
p = params['subcards']
|
500
|
+
if p && card_params = p[cardname.to_s]
|
489
501
|
content = card_params['content']
|
490
502
|
end
|
491
503
|
content if content.present? # why is this necessary? - efm
|
@@ -510,26 +522,26 @@ class Card
|
|
510
522
|
:name
|
511
523
|
end
|
512
524
|
|
513
|
-
|
514
525
|
#
|
515
526
|
# ------------ LINKS ---------------
|
516
527
|
#
|
517
528
|
|
518
529
|
def add_class options, klass
|
519
|
-
options[:class] = [
|
530
|
+
options[:class] = [options[:class], klass].flatten.compact * ' '
|
520
531
|
end
|
521
532
|
|
522
|
-
|
523
533
|
def unique_id
|
524
534
|
"#{card.key}-#{Time.now.to_i}-#{rand(3)}"
|
525
535
|
end
|
526
536
|
|
527
|
-
def format_date date, include_time
|
528
|
-
#
|
537
|
+
def format_date date, include_time=true
|
538
|
+
# using DateTime because Time doesn't support %e on some platforms
|
529
539
|
if include_time
|
530
|
-
DateTime.new(
|
540
|
+
DateTime.new(
|
541
|
+
date.year, date.mon, date.day, date.hour, date.min, date.sec
|
542
|
+
).strftime('%B %e, %Y %H:%M:%S')
|
531
543
|
else
|
532
|
-
DateTime.new(date.year, date.mon, date.day).strftime(
|
544
|
+
DateTime.new(date.year, date.mon, date.day).strftime('%B %e, %Y')
|
533
545
|
end
|
534
546
|
end
|
535
547
|
|
@@ -538,7 +550,6 @@ class Card
|
|
538
550
|
@context_names += name.to_name.part_names
|
539
551
|
@context_names.uniq!
|
540
552
|
end
|
541
|
-
|
542
553
|
end
|
543
554
|
end
|
544
555
|
|
data/lib/card/location.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
class Card
|
2
|
-
|
3
2
|
module Location
|
4
|
-
#
|
5
|
-
#
|
3
|
+
# page_path takes a Card::Name, adds the format and query string to
|
4
|
+
# url_key (site-absolute)
|
6
5
|
# card_path makes a relative path site-absolute (if not already)
|
7
6
|
# card_url makes it a full url (if not already)
|
8
7
|
|
@@ -34,5 +33,4 @@ class Card
|
|
34
33
|
|
35
34
|
extend Location
|
36
35
|
end
|
37
|
-
|
38
|
-
end
|
36
|
+
end
|
data/lib/card/subcards.rb
CHANGED
data/lib/card/success.rb
CHANGED
@@ -11,9 +11,6 @@ class Card
|
|
11
11
|
case success_params
|
12
12
|
when Hash
|
13
13
|
apply(success_params)
|
14
|
-
when /^REDIRECT:\s*(.+)/
|
15
|
-
@redirect=true
|
16
|
-
self.target = $1
|
17
14
|
when nil ; self.name = '_self'
|
18
15
|
else ; self.target = success_params
|
19
16
|
end
|
@@ -59,14 +56,20 @@ class Card
|
|
59
56
|
|
60
57
|
def target= value
|
61
58
|
@id = @name = @card = nil
|
62
|
-
@target =
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
59
|
+
@target = process_target value
|
60
|
+
end
|
61
|
+
|
62
|
+
def process_target value
|
63
|
+
case value
|
64
|
+
when '' then ''
|
65
|
+
when '*previous', :previous then :previous
|
66
|
+
when /^(http|\/)/ then value
|
67
|
+
when /^TEXT:\s*(.+)/ then $1
|
68
|
+
when /^REDIRECT:\s*(.+)/
|
69
|
+
@redirect = true
|
70
|
+
process_target $1
|
71
|
+
else self.mark = value
|
72
|
+
end
|
70
73
|
end
|
71
74
|
|
72
75
|
def apply args
|