equipment 0.1.0 → 1.4.84

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGES +9 -0
  2. data/LICENSE +340 -0
  3. data/README +29 -12
  4. data/Rakefile +157 -0
  5. data/TODO +14 -0
  6. data/doc/structure.dia +0 -0
  7. data/doc/structure.png +0 -0
  8. data/lib/camping_ext.rb +72 -0
  9. data/lib/equipment.rb +39 -116
  10. data/lib/ext.rb +33 -0
  11. data/lib/ext/active_record.rb +146 -0
  12. data/lib/ext/basic_auth.rb +15 -15
  13. data/lib/ext/controls.rb +16 -14
  14. data/lib/ext/flash.rb +35 -17
  15. data/lib/ext/form_helpers.rb +46 -0
  16. data/lib/ext/forward.rb +44 -15
  17. data/lib/ext/js_helpers.rb +66 -19
  18. data/lib/ext/logging.rb +61 -0
  19. data/lib/ext/mount.rb +33 -27
  20. data/lib/ext/negociate_content.rb +90 -0
  21. data/lib/ext/og.rb +18 -10
  22. data/lib/ext/og_scaffold.rb +5 -8
  23. data/lib/ext/resource.rb +127 -0
  24. data/lib/ext/security.rb +66 -31
  25. data/lib/ext/sendfile.rb +3 -4
  26. data/lib/ext/settings.rb +243 -0
  27. data/lib/ext/template_view.rb +9 -37
  28. data/lib/ext/use_helper.rb +6 -10
  29. data/lib/ext/view.rb +98 -0
  30. data/lib/ext/view_slot.rb +60 -0
  31. data/lib/mimetype_ext.rb +12 -0
  32. data/lib/more/typecast.rb +288 -0
  33. data/lib/ruby_ext.rb +126 -0
  34. data/share/js/date_ext.js +234 -0
  35. data/share/js/es-confirm.js +23 -0
  36. data/share/js/event-selector.js +145 -0
  37. data/share/js/jquery.js +1793 -0
  38. data/share/js/prototype.js +2012 -0
  39. metadata +50 -35
  40. data/ProjectInfo +0 -55
  41. data/examples/basicauthtest.rb +0 -59
  42. data/examples/erubytest.rb +0 -36
  43. data/examples/flashtest.rb +0 -46
  44. data/examples/index.erb +0 -9
  45. data/examples/mounttest.rb +0 -34
  46. data/examples/ogtest.rb +0 -41
  47. data/examples/patchestest.rb +0 -40
  48. data/examples/sendfiletest.rb +0 -29
  49. data/lib/ext/forms.rb +0 -22
  50. data/lib/ext/patches.rb +0 -130
  51. data/lib/ext/ressource.rb +0 -88
@@ -1,79 +1,114 @@
1
1
  require 'equipment'
2
- require 'ext/patches'
2
+ require 'ext/app_util'
3
3
  require 'ext/forward'
4
+ require 'ext/view'
4
5
 
5
6
  module Ext
6
7
 
7
- # Generic authentication module. Used by BasicAuth for example.
8
+ # Generic authentication module. Used by BasicAuth for example.
9
+ #
10
+ # == Warning
11
+ #
12
+ # Never use this module alone. You should at least create another module that
13
+ # extends Base. This is because of how Equipment works right now. You wouldn't
14
+ # be able to define authenticate and authorize and call super. Ask zimbatm for
15
+ # more information on this if you're interested... :-)
16
+ #
17
+ # == Usage
18
+ #
19
+ # Security is split in two methods ; authenticate and authorize.
20
+ # The role of authenticate is to detect the user, loaded by session or
21
+ # other. The role of authorize is to tell if the user is authorized or
22
+ # not. Authorize must be overriden if you want to secure some place of
23
+ # your app. Defining it in Base will act globally. You can also define
24
+ # them individually in each controller, like you want. Finally, both
25
+ # methods are chained, so you can use super to mix various security
26
+ # mechanism.
27
+ #
28
+ # In your app, override authenticate if you want to load your users
29
+ # from the database. eg.
30
+ #
31
+ # def authenticate
32
+ # user, pass = *super
33
+ # @user = User.find_by_login_and_password(user, pass)
34
+ # return [user, pass] if @user
35
+ # return [nil, nil]
36
+ # end
37
+ #
38
+ # Override authotize like that
39
+ #
40
+ # def authorize(user, pass)
41
+ # # some auth mechanism
42
+ # if user == pass
43
+ # return true
44
+ # else
45
+ # return false
46
+ # end
47
+ # end
8
48
  #
9
49
  # == Dependencies
10
50
  #
11
51
  # * Equipment
52
+ # * AppUtil
12
53
  # * Forward
13
- # * Patches
14
- #
15
- # == TODO
54
+ # * View
16
55
  #
17
- # * More doc
18
56
  module Security
19
57
  extend Equipment
20
- depends_on Patches
58
+ depends_on AppUtil
21
59
  depends_on Forward
22
-
23
- def self.equip(app)
24
- super
25
- app::Controllers::Unauthorized.send :include, app::C, app::Base, app::Models
26
- app::Controllers::Unauthenticated.send :include, app::C, app::Base, app::Models
27
- end
60
+ depends_on View
28
61
 
29
62
  module Base
30
- # Blank authentication, returns [nil, nil]
63
+ # Blank authentication terminator, returns [nil, nil]
31
64
  def authenticate; return nil, nil end
32
65
 
33
- # Blank authorization, returns true
34
- def authorize(user, pass, force=false); not force; end
66
+ # Blank authorization terminator, returns nil as ternary operator.
67
+ def authorize(user, pass); return nil end
35
68
 
36
69
  # Checks the credencials when serving a page if `authorize` is defined
37
- # in your app, Base or controller.
70
+ # in your app, Base or controller. If you forward to controllers
71
+ # that don't have urls, the security will not be checked.
38
72
  def service(*a)
39
- puts "Walking trough service"
73
+ return super if self.class.urls.empty?
40
74
  user, pass = authenticate
41
- if authorize(user, pass)
42
- super
75
+ if authorize(user, pass) != false # nil is accepted, not false
76
+ return super
43
77
  elsif not user
44
- puts "Forwarding to Unauthenticated"
45
- forward(app::Controllers::Unauthenticated)
78
+ forward app::Controllers::Unauthenticated, 'get'
46
79
  else
47
- puts "Forwarding to Unauthorized"
48
- forward(app::Controllers::Unauthorized, user)
80
+ forward app::Controllers::Unauthorized, 'get', user
49
81
  end
50
82
  self
51
83
  end
52
84
 
53
85
  end
54
86
 
87
+ # Security defines two controllers that correspond to your those two
88
+ # methods.
55
89
  module Controllers
56
90
  # Called when an url is not authorized. You can override this is your app.
57
91
  # Or create an `unauthorized` view. @bad_user is the user name.
58
92
  class Unauthorized
59
93
  def self.urls; [] end # do not serve urls directly.
60
- def authenticate; return nil, nil end
61
- def authorize(user, pass, force=false); true; end
62
94
 
63
95
  def get(bad_user)
64
96
  @bad_user = bad_user
65
- render(:unauthorized) rescue "Unauthorized user : #@bad_user"
97
+ if has_view?(:unauthorized)
98
+ render(:unauthorized)
99
+ else "Unauthorized user : #@bad_user" end
66
100
  end
67
101
  end
68
102
 
69
- # Customize by creating an "unauthenticated" view
103
+ # Customize by creating an "unauthenticated" view. You could
104
+ # implement a login page here.
70
105
  class Unauthenticated
71
106
  def self.urls; [] end # do not serve urls directly.
72
- def authenticate; return nil, nil end
73
- def authorize(user, pass, force=false); true; end
74
107
 
75
108
  def get
76
- render(:unauthenticated) rescue 'Unauthenticated'
109
+ if has_view?(:unauthenticated)
110
+ render(:unauthenticated)
111
+ else 'Unauthenticated' end
77
112
  end
78
113
  end
79
114
 
@@ -3,7 +3,7 @@ require 'ext/app_util'
3
3
  require 'ext/forward'
4
4
 
5
5
  begin
6
- require 'mime/types' # requires that package
6
+ require 'mimetype_ext' # requires that package
7
7
  rescue LoadError
8
8
  STDERR.puts '*** mime/types not available. You will have to specify mime \
9
9
  types in Equipment::Sendfile.'
@@ -23,7 +23,6 @@ module Ext
23
23
  # == Dependencies
24
24
  #
25
25
  # * Equipment
26
- # * AppUtil
27
26
  # * Forward
28
27
  # * `mime-types` package. Available as a gem.
29
28
  # * `sendfile` package (optional). Available as a gem.
@@ -68,13 +67,13 @@ module Ext
68
67
 
69
68
  # Sendfile is used ?
70
69
  if $mongrel_has_sendfile
71
- @headers['X-Sendfile'] = path
70
+ @headers['X-SENDFILE'] = path
72
71
  else
73
72
  @body = file.read
74
73
  end
75
74
 
76
75
  rescue Errno::ENOENT, Errno::EISDIR # File not found
77
- forward(app::Controllers::NotFound, @env.PATH_INFO)
76
+ forward app::Controllers::NotFound, 'get', @env.PATH_INFO
78
77
  ensure
79
78
  file.close if file
80
79
  end
@@ -0,0 +1,243 @@
1
+ require 'equipment'
2
+ require 'forwardable'
3
+ require 'yaml'
4
+
5
+ module Ext
6
+ # Settings allow you to have configurable settings in your app. Define
7
+ # your own configuration settings in the app root and then call
8
+ # #load_settings.
9
+ #
10
+ # NOTE : This Equipment is usable without Camping.
11
+ #
12
+ # == Example
13
+ #
14
+ # require 'camping'
15
+ # require 'ext/settings'
16
+ #
17
+ # Camping.goes :YourApp
18
+ #
19
+ # module YourApp
20
+ # equip Ext::Settings
21
+ #
22
+ # setting :database, {:store=>'mysql', :hostname=>'localhost'}
23
+ #
24
+ # load_settings('your_config.yaml')
25
+ # end
26
+ #
27
+ # YourApp.database #=> {:store=>'mysql', :hostname=>'localhost'}
28
+ #
29
+ # == Dependencies
30
+ #
31
+ # * Equipment
32
+ # * YAML
33
+ # * Forwardable
34
+ #
35
+ # == TODO
36
+ #
37
+ # Implement type-casting ?
38
+ #
39
+ module Settings
40
+ extend Equipment
41
+
42
+ # Define C if not defined.
43
+ def self.equip(app)
44
+ app.module_eval "C=self" unless app.const_defined? :C
45
+ super
46
+ end
47
+
48
+ # Class methods for your app.
49
+ module CClassMethods
50
+ attr_accessor :settings_path
51
+
52
+ # This is the method that let you create settings. If you pass a
53
+ # block, it will be called when the key is assigned and the return
54
+ # value will be used.
55
+ #
56
+ # == Example
57
+ #
58
+ # setting :user, 'HEY', do |new,old|
59
+ # new.downcase
60
+ # end
61
+ #
62
+ # self.user #=> "hey"
63
+ def setting(key, value, &on_change)
64
+ settings.set(key, value, &on_change)
65
+
66
+ # reader
67
+ metaclass.send :define_method, key do
68
+ settings[key].value
69
+ end
70
+
71
+ # writer
72
+ metaclass.send :define_method, "#{key}=" do |val|
73
+ settings[key].value = val
74
+ end
75
+ end
76
+
77
+ # The group of settings. You can call settings.to_yaml to get the
78
+ # output.
79
+ def settings; @settings ||= SettingGroup.new(self) end
80
+
81
+ # Loads the specified file. If none is given, it will look in /etc
82
+ # and your home folder for a file called you_app.yaml
83
+ def load_settings(yaml_file=settings_path)
84
+ if yaml_file
85
+ settings.load(yaml_file)
86
+ puts "INFO: '#{yaml_file}' loaded." if $DBG
87
+ else
88
+ name = self.name.methodize
89
+
90
+ # YAML config
91
+ configs = []
92
+ configs << File.join(ENV['HOME'], ".#{name}.yaml") if ENV['HOME']
93
+ configs << File.join(ENV['APPDATA'], "#{name}.yaml") if ENV['APPDATA']
94
+ configs << "/etc/#{name}.yaml"
95
+ configs.each do |conf|
96
+ conf = File.expand_path(conf)
97
+ if File.exists?(conf)
98
+ settings_path = conf
99
+ load_settings(conf)
100
+ break
101
+ end
102
+ end
103
+
104
+ # Ruby config
105
+ configs = []
106
+ configs << File.join(ENV['HOME'], ".#{name}.rb") if ENV['HOME']
107
+ configs << File.join(ENV['APPDATA'], "#{name}.yaml") if ENV['APPDATA']
108
+ configs << "/etc/#{name}.rb"
109
+ configs.each do |conf|
110
+ conf = File.expand_path(conf)
111
+ if File.exists?(conf)
112
+ load conf
113
+ break
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ # Export the settings once they're changed. You'll have to call
120
+ # this by hand.
121
+ #
122
+ # Oh and, the keys will be stored in the following format :
123
+ # 'YourApp.keyname'
124
+ def save_settings(yaml_file=settings_path)
125
+ raise ArgumentError, "No settings path given" unless yaml_file
126
+ settings.save(yaml_file)
127
+ end
128
+ end
129
+
130
+ # This is the class that represent one setting. You should not use
131
+ # that directly but access it trough the YourApp.settings method.
132
+ #
133
+ # default_value is the value that you specified when defining the
134
+ # setting.
135
+ class Setting
136
+ # klass is not used here. It's for YAML.
137
+ attr_reader :klass, :key, :value, :default_value
138
+ def initialize(klass, key, default_value, &on_change)
139
+ @klass, @key = klass, key
140
+ @on_change = on_change
141
+ @default_value = self.value = default_value
142
+ end
143
+
144
+ # Calls the on_change transformer if available.
145
+ def value=(new_val)
146
+ if @on_change
147
+ @value = @on_change.call(new_val)
148
+ else
149
+ @value = new_val
150
+ end
151
+ end
152
+
153
+ def on_change(&block)
154
+ raise ArgumentError, "please give a block" unless block_given?
155
+ @on_change = block
156
+ end
157
+ end
158
+
159
+ # This is the class that represent YourApp.settings. Do not use it
160
+ # directly. Kind of HashWithIndifferentAccess.
161
+ class SettingGroup
162
+ extend Forwardable
163
+
164
+ def_delegators :@hash, :keys
165
+
166
+ # To generate the YAML keys.
167
+ attr_reader :klass
168
+
169
+ def initialize(klass)
170
+ @klass = klass
171
+ @hash = {}
172
+ end
173
+
174
+ def get(key)
175
+ key = convert_key(key)
176
+ @hash[key]
177
+ end
178
+ alias_method :[], :get
179
+
180
+ def set(key, value, &on_change)
181
+ key = convert_key(key)
182
+ raise ArgumentError, "#{klass}.#{key} already defined" if @hash.has_key? key
183
+ @hash[key] = Setting.new(klass, key, value, &on_change)
184
+ end
185
+ alias_method :[]=, :set
186
+
187
+ def method_missing(m)
188
+ raise NoMethodError unless @hash.has_key? m
189
+ @hash[m]
190
+ end
191
+
192
+ # Loads your configuration file. Used by load_settings.
193
+ def load(file)
194
+
195
+ case file
196
+ when String
197
+ file = File.open(file)
198
+ end
199
+
200
+ vals = YAML::load(file)
201
+ if vals.kind_of? Hash
202
+ vals.select{|k,v| /^#{klass.name}\./ =~ k}.each do |k,v|
203
+ key = k.sub /^#{klass.name}\./,''
204
+ if @hash.has_key? key
205
+ @hash[key].value = v
206
+ else
207
+ puts "INFO: #{klass.name}.#{key} does not exist. #{@hash.inspect}"
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ # Exports your configuration file as YAML. Used by save_settings.
214
+ def save(file)
215
+
216
+ case file
217
+ when String
218
+ file = File.open(file, 'w')
219
+ end
220
+
221
+ file.write(to_yaml)
222
+ end
223
+
224
+ def to_hash
225
+ @hash.keys.sort.inject(Hash.new) do |hash,k|
226
+ hash["#{klass}.#{k}"] = @hash[k].value
227
+ hash
228
+ end
229
+ end
230
+
231
+ def to_yaml
232
+ to_hash.to_yaml
233
+ end
234
+
235
+ private
236
+
237
+ def convert_key(key)
238
+ key.to_s
239
+ end
240
+ end
241
+ end
242
+ end
243
+
@@ -1,9 +1,10 @@
1
1
  require 'equipment'
2
- require 'ext/patches'
2
+ require 'ext/view'
3
+
4
+ raise "Templates are broken for now, sorry !"
3
5
 
4
6
  module Ext
5
- # A microcospical extension to decouple views from camping. Especially
6
- # the ones based on templates.
7
+ # A microcospical extension to decouple template views from camping.
7
8
  #
8
9
  # Adds a V class to your app on which all instance variables
9
10
  # will be sent before rendering the view.
@@ -11,39 +12,26 @@ module Ext
11
12
  # == Dependencies
12
13
  #
13
14
  # * Equipment
14
- # * Patches
15
+ # * View
15
16
  #
16
17
  # == TODO
17
18
  #
18
19
  # * Add support for layouts
19
20
  module TemplateView
20
21
  extend Equipment
21
- depends_on Patches
22
-
23
- def self.equip(app)
24
- super
25
- app.module_eval <<-SOME_VIEW
26
- # Some kind of view data proxy for template-based renderers
27
- class V
28
- include Helpers
29
- include Controllers
30
- def bind(m,*a,&b); binding; end
31
- def R(klass, *args); self / super; end
32
- end
33
- SOME_VIEW
34
- end
22
+ depends_on View
35
23
 
36
24
  module Base
37
25
  # Takes template_root from ViewsClassMethods#template_root.
38
26
  #
39
27
  # You can change that by setting @template_root in your controller.
40
- def template_root; @template_root || app::Views.template_root || '' end
28
+ def template_root; @template_root || app.template_root || '' end
41
29
 
42
30
  # Same as #template_root
43
- def use_cache; @use_cache || app::Views.use_cache; end
31
+ def use_cache; @use_cache || app.use_cache; end
44
32
  end
45
33
 
46
- module ViewsClassMethods
34
+ module CClassMethods
47
35
  # Sets the template_root. Usage is up to the template.
48
36
  attr_accessor :template_root
49
37
 
@@ -54,19 +42,3 @@ module Ext
54
42
 
55
43
  end
56
44
 
57
- class Object
58
-
59
- # Sets all instance variables of an object to another
60
- #
61
- # if force is set to true, existing instance variables will be overwritten
62
- def instance_variables_send(obj, force=false)
63
- instance_variables.each do |v|
64
- if force or not obj.instance_variables.include? v
65
- obj.instance_variable_set(v, instance_variable_get(v))
66
- end
67
- end
68
- obj
69
- end
70
- alias :ivs_send :instance_variables_send
71
- end
72
-