card 1.16.12 → 1.16.13
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 +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
|