card 1.16.13 → 1.16.14
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/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 
     | 
    
         
            -
             
     |