Class: DAV4Rack::Resource
- Inherits:
-
Object
- Object
- DAV4Rack::Resource
- Includes:
- HTTPStatus
- Defined in:
- lib/dav4rack/resource.rb
Direct Known Subclasses
Constant Summary collapse
- @@blocks =
{}
Constants included from HTTPStatus
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#public_path ⇒ Object
readonly
Returns the value of attribute public_path.
-
#request ⇒ Object
readonly
Returns the value of attribute request.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
-
#user ⇒ Object
Returns the value of attribute user.
Class Method Summary collapse
-
.method_missing(*args, &block) ⇒ Object
This lets us define a bunch of before and after blocks that are either called before all methods on the resource, or only specific methods on the resource.
Instance Method Summary collapse
-
#==(other) ⇒ Object
- other
-
Resource Returns if current resource is equal to other resource.
-
#child(name) ⇒ Object
- name
- Name of child Create a new child with the given name NOTE
-
Include trailing ‘/’ if child is collection.
-
#children ⇒ Object
If this is a collection, return the child resources.
-
#collection? ⇒ Boolean
Is this resource a collection?.
-
#content_length ⇒ Object
Return the size in bytes for this resource.
-
#content_type ⇒ Object
Return the mime type of this resource.
-
#copy(dest, overwrite = false) ⇒ Object
HTTP COPY request.
-
#creation_date ⇒ Object
Return the creation time.
-
#delete ⇒ Object
HTTP DELETE request.
-
#descendants ⇒ Object
Return list of descendants.
-
#display_name ⇒ Object
Name of the resource to be displayed to the client.
-
#etag ⇒ Object
Return an Etag, an unique hash value for this resource.
-
#exist? ⇒ Boolean
Does this resource exist?.
-
#get(request, response) ⇒ Object
HTTP GET request.
-
#get_property(name) ⇒ Object
- name
-
String - Property name Returns the value of the given property.
-
#initialize(public_path, path, request, response, options) ⇒ Resource
constructor
- public_path
- Path received via request path
- Internal resource path (Only different from public path when using root_uri’s for webdav) request
- Rack::Request options
-
Any options provided for this resource Creates a new instance of the resource.
-
#last_modified ⇒ Object
Return the time of last modification.
-
#last_modified=(time) ⇒ Object
Set the time of last modification.
-
#lock(args) ⇒ Object
- args
-
Hash of lock arguments Request for a lock on the given resource.
-
#lock_check(lock_scope = nil) ⇒ Object
- lock_scope
-
scope of lock Check if resource is locked.
-
#make_collection ⇒ Object
Create this resource as collection.
-
#method_missing(*args) ⇒ Object
This allows us to call before and after blocks.
-
#move(dest, overwrite = false) ⇒ Object
HTTP MOVE request.
-
#name ⇒ Object
Name of the resource.
-
#parent ⇒ Object
Return parent of this resource.
-
#parent_exists? ⇒ Boolean
Does the parent resource exist?.
-
#post(request, response) ⇒ Object
HTTP POST request.
-
#property_names ⇒ Object
Available properties.
-
#put(request, response) ⇒ Object
HTTP PUT request.
-
#remove_property(name) ⇒ Object
- name
-
Property name Remove the property from the resource.
-
#resource_type ⇒ Object
Return the resource type.
-
#set_property(name, value) ⇒ Object
- name
- String - Property name value
-
New value Set the property to the given value.
-
#unlock(token) ⇒ Object
- token
-
Lock token Remove the given lock.
Constructor Details
#initialize(public_path, path, request, response, options) ⇒ Resource
- public_path
-
Path received via request
- path
-
Internal resource path (Only different from public path when using root_uri’s for webdav)
- request
-
Rack::Request
- options
-
Any options provided for this resource
Creates a new instance of the resource. NOTE: path and public_path will only differ if the root_uri has been set for the resource. The
controller will strip out the starting path so the resource can easily determine what
it is working on. For example:
request -> /my/webdav/directory/actual/path
public_path -> /my/webdav/directory/actual/path
path -> /actual/path
NOTE: Customized Resources should not use initialize for setup. Instead
use the #setup method
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/dav4rack/resource.rb', line 65 def initialize(public_path, path, request, response, ) @skip_alias = [ :authenticate, :authentication_error_msg, :authentication_realm, :path, :options, :public_path, :request, :response, :user, :user=, :setup ] @public_path = public_path.dup @path = path.dup @request = request @response = response unless(.has_key?(:lock_class)) require 'dav4rack/lock_store' @lock_class = LockStore else @lock_class = [:lock_class] raise NameError.new("Unknown lock type constant provided: #{@lock_class}") unless @lock_class.nil? || defined?(@lock_class) end @options = .dup @max_timeout = [:max_timeout] || 86400 @default_timeout = [:default_timeout] || 60 @user = @options[:user] || request.ip setup if respond_to?(:setup) public_methods(false).each do |method| next if @skip_alias.include?(method.to_sym) || method[0,4] == 'DAV_' || method[0,5] == '_DAV_' self.class.class_eval "alias :'_DAV_#{method}' :'#{method}'" self.class.class_eval "undef :'#{method}'" end @runner = lambda do |class_sym, kind, method_name| [:'__all__', method_name.to_sym].each do |sym| if(@@blocks[class_sym] && @@blocks[class_sym][kind] && @@blocks[class_sym][kind][sym]) @@blocks[class_sym][kind][sym].each do |b| args = [self, sym == :'__all__' ? method_name : nil].compact b.call(*args) end end end end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(*args) ⇒ Object
This allows us to call before and after blocks
106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/dav4rack/resource.rb', line 106 def method_missing(*args) result = nil orig = args.shift class_sym = self.class.name.to_sym m = orig.to_s[0,5] == '_DAV_' ? orig : "_DAV_#{orig}" # If hell is doing the same thing over and over and expecting a different result this is a hell preventer raise NoMethodError.new("Undefined method: #{orig} for class #{self}.") unless respond_to?(m) @runner.call(class_sym, :before, orig) result = send m, *args @runner.call(class_sym, :after, orig) result end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
19 20 21 |
# File 'lib/dav4rack/resource.rb', line 19 def @options end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
19 20 21 |
# File 'lib/dav4rack/resource.rb', line 19 def path @path end |
#public_path ⇒ Object (readonly)
Returns the value of attribute public_path.
19 20 21 |
# File 'lib/dav4rack/resource.rb', line 19 def public_path @public_path end |
#request ⇒ Object (readonly)
Returns the value of attribute request.
19 20 21 |
# File 'lib/dav4rack/resource.rb', line 19 def request @request end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
19 20 21 |
# File 'lib/dav4rack/resource.rb', line 19 def response @response end |
#user ⇒ Object
Returns the value of attribute user.
20 21 22 |
# File 'lib/dav4rack/resource.rb', line 20 def user @user end |
Class Method Details
.method_missing(*args, &block) ⇒ Object
This lets us define a bunch of before and after blocks that are either called before all methods on the resource, or only specific methods on the resource
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/dav4rack/resource.rb', line 28 def method_missing(*args, &block) class_sym = self.name.to_sym @@blocks[class_sym] ||= {:before => {}, :after => {}} m = args.shift parts = m.to_s.split('_') type = parts.shift.to_s.to_sym method = parts.empty? ? nil : parts.join('_').to_sym if(@@blocks[class_sym][type] && block_given?) if(method) @@blocks[class_sym][type][method] ||= [] @@blocks[class_sym][type][method] << block else @@blocks[class_sym][type][:'__all__'] ||= [] @@blocks[class_sym][type][:'__all__'] << block end else raise NoMethodError.new("Undefined method #{m} for class #{self}") end end |
Instance Method Details
#==(other) ⇒ Object
- other
-
Resource
Returns if current resource is equal to other resource
325 326 327 |
# File 'lib/dav4rack/resource.rb', line 325 def ==(other) path == other.path end |
#child(name) ⇒ Object
- name
-
Name of child
Create a new child with the given name
- NOTE
-
Include trailing ‘/’ if child is collection
381 382 383 384 385 386 387 388 389 |
# File 'lib/dav4rack/resource.rb', line 381 def child(name) new_public = public_path.dup new_public = new_public + '/' unless new_public[-1,1] == '/' new_public = '/' + new_public unless new_public[0,1] == '/' new_path = path.dup new_path = new_path + '/' unless new_path[-1,1] == '/' new_path = '/' + new_path unless new_path[0,1] == '/' self.class.new("#{new_public}#{name}", "#{new_path}#{name}", request, response, .merge(:user => @user)) end |
#children ⇒ Object
If this is a collection, return the child resources.
119 120 121 |
# File 'lib/dav4rack/resource.rb', line 119 def children NotImplemented end |
#collection? ⇒ Boolean
Is this resource a collection?
124 125 126 |
# File 'lib/dav4rack/resource.rb', line 124 def collection? NotImplemented end |
#content_length ⇒ Object
Return the size in bytes for this resource.
170 171 172 |
# File 'lib/dav4rack/resource.rb', line 170 def content_length NotImplemented end |
#content_type ⇒ Object
Return the mime type of this resource.
165 166 167 |
# File 'lib/dav4rack/resource.rb', line 165 def content_type NotImplemented end |
#copy(dest, overwrite = false) ⇒ Object
HTTP COPY request.
Copy this resource to given destination resource.
205 206 207 |
# File 'lib/dav4rack/resource.rb', line 205 def copy(dest, overwrite=false) NotImplemented end |
#creation_date ⇒ Object
Return the creation time.
139 140 141 |
# File 'lib/dav4rack/resource.rb', line 139 def creation_date NotImplemented end |
#delete ⇒ Object
HTTP DELETE request.
Delete this resource.
198 199 200 |
# File 'lib/dav4rack/resource.rb', line 198 def delete NotImplemented end |
#descendants ⇒ Object
Return list of descendants
399 400 401 402 403 404 405 406 |
# File 'lib/dav4rack/resource.rb', line 399 def descendants list = [] children.each do |child| list << child list.concat(child.descendants) end list end |
#display_name ⇒ Object
Name of the resource to be displayed to the client
335 336 337 |
# File 'lib/dav4rack/resource.rb', line 335 def display_name name end |
#etag ⇒ Object
Return an Etag, an unique hash value for this resource.
154 155 156 |
# File 'lib/dav4rack/resource.rb', line 154 def etag NotImplemented end |
#exist? ⇒ Boolean
Does this resource exist?
129 130 131 |
# File 'lib/dav4rack/resource.rb', line 129 def exist? NotImplemented end |
#get(request, response) ⇒ Object
HTTP GET request.
Write the content of the resource to the response.body.
177 178 179 |
# File 'lib/dav4rack/resource.rb', line 177 def get(request, response) NotImplemented end |
#get_property(name) ⇒ Object
- name
-
String - Property name
Returns the value of the given property
346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/dav4rack/resource.rb', line 346 def get_property(name) case name when 'resourcetype' then resource_type when 'displayname' then display_name when 'creationdate' then creation_date.xmlschema when 'getcontentlength' then content_length.to_s when 'getcontenttype' then content_type when 'getetag' then etag when 'getlastmodified' then last_modified.httpdate end end |
#last_modified ⇒ Object
Return the time of last modification.
144 145 146 |
# File 'lib/dav4rack/resource.rb', line 144 def last_modified NotImplemented end |
#last_modified=(time) ⇒ Object
Set the time of last modification.
149 150 151 |
# File 'lib/dav4rack/resource.rb', line 149 def last_modified=(time) NotImplemented end |
#lock(args) ⇒ Object
- args
-
Hash of lock arguments
Request for a lock on the given resource. A valid lock should lock all descendents. Failures should be noted and returned as an exception using LockFailure. Valid args keys: :timeout -> requested timeout
:depth -> lock depth
:scope -> lock scope
:type -> lock type
:owner -> lock owner
Should return a tuple: [lock_time, locktoken] where lock_time is the given timeout NOTE: See section 9.10 of RFC 4918 for guidance about how locks should be generated and the expected responses (www.webdav.org/specs/rfc4918.html#rfc.section.9.10)
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/dav4rack/resource.rb', line 231 def lock(args) unless(@lock_class) NotImplemented else unless(parent_exists?) Conflict else lock_check(args[:scope]) lock = @lock_class.explicit_locks(@path).find{|l| l.scope == args[:scope] && l.kind == args[:type] && l.user == @user} unless(lock) token = UUIDTools::UUID.random_create.to_s lock = @lock_class.generate(@path, @user, token) lock.scope = args[:scope] lock.kind = args[:type] lock.owner = args[:owner] lock.depth = args[:depth].is_a?(Symbol) ? args[:depth] : args[:depth].to_i if(args[:timeout]) lock.timeout = args[:timeout] <= @max_timeout && args[:timeout] > 0 ? args[:timeout] : @max_timeout else lock.timeout = @default_timeout end lock.save if lock.respond_to? :save end begin lock_check(args[:type]) rescue DAV4Rack::LockFailure => lock_failure lock.destroy raise lock_failure rescue HTTPStatus::Status => status status end [lock.remaining_timeout, lock.token] end end end |
#lock_check(lock_scope = nil) ⇒ Object
- lock_scope
-
scope of lock
Check if resource is locked. Raise DAV4Rack::LockFailure if locks are in place.
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/dav4rack/resource.rb', line 269 def lock_check(lock_scope=nil) return unless @lock_class if(@lock_class.explicitly_locked?(@path)) raise Locked if @lock_class.explicit_locks(@path).find_all{|l|l.scope == 'exclusive' && l.user != @user}.size > 0 elsif(@lock_class.implicitly_locked?(@path)) if(lock_scope.to_s == 'exclusive') locks = @lock_class.implicit_locks(@path) failure = DAV4Rack::LockFailure.new("Failed to lock: #{@path}") locks.each do |lock| failure.add_failure(@path, Locked) end raise failure else locks = @lock_class.implict_locks(@path).find_all{|l| l.scope == 'exclusive' && l.user != @user} if(locks.size > 0) failure = LockFailure.new("Failed to lock: #{@path}") locks.each do |lock| failure.add_failure(@path, Locked) end raise failure end end end end |
#make_collection ⇒ Object
Create this resource as collection.
319 320 321 |
# File 'lib/dav4rack/resource.rb', line 319 def make_collection NotImplemented end |
#move(dest, overwrite = false) ⇒ Object
HTTP MOVE request.
Move this resource to given destination resource.
212 213 214 |
# File 'lib/dav4rack/resource.rb', line 212 def move(dest, overwrite=false) NotImplemented end |
#name ⇒ Object
Name of the resource
330 331 332 |
# File 'lib/dav4rack/resource.rb', line 330 def name File.basename(path) end |
#parent ⇒ Object
Return parent of this resource
392 393 394 395 396 |
# File 'lib/dav4rack/resource.rb', line 392 def parent elements = @path.scan(/[^\/]+/) return nil if elements.empty? self.class.new(('/' + @public_path.scan(/[^\/]+/)[0..-2].join('/')), ('/' + elements[0..-2].to_a.join('/')), @request, @response, @options.merge(:user => @user)) end |
#parent_exists? ⇒ Boolean
Does the parent resource exist?
134 135 136 |
# File 'lib/dav4rack/resource.rb', line 134 def parent_exists? parent.exist? end |
#post(request, response) ⇒ Object
HTTP POST request.
Usually forbidden.
191 192 193 |
# File 'lib/dav4rack/resource.rb', line 191 def post(request, response) NotImplemented end |
#property_names ⇒ Object
Available properties
340 341 342 |
# File 'lib/dav4rack/resource.rb', line 340 def property_names %w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength) end |
#put(request, response) ⇒ Object
HTTP PUT request.
Save the content of the request.body.
184 185 186 |
# File 'lib/dav4rack/resource.rb', line 184 def put(request, response) NotImplemented end |
#remove_property(name) ⇒ Object
- name
-
Property name
Remove the property from the resource
374 375 376 |
# File 'lib/dav4rack/resource.rb', line 374 def remove_property(name) Forbidden end |
#resource_type ⇒ Object
Return the resource type. Generally only used to specify resource is a collection.
160 161 162 |
# File 'lib/dav4rack/resource.rb', line 160 def resource_type :collection if collection? end |
#set_property(name, value) ⇒ Object
- name
-
String - Property name
- value
-
New value
Set the property to the given value
361 362 363 364 365 366 367 368 369 370 |
# File 'lib/dav4rack/resource.rb', line 361 def set_property(name, value) case name when 'resourcetype' then self.resource_type = value when 'getcontenttype' then self.content_type = value when 'getetag' then self.etag = value when 'getlastmodified' then self.last_modified = Time.httpdate(value) end rescue ArgumentError Conflict end |
#unlock(token) ⇒ Object
- token
-
Lock token
Remove the given lock
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/dav4rack/resource.rb', line 296 def unlock(token) unless(@lock_class) NotImplemented else token = token.slice(1, token.length - 2) if(token.nil? || token.empty?) BadRequest else lock = @lock_class.find_by_token(token) if(lock.nil? || lock.user != @user) Forbidden elsif(lock.path !~ /^#{Regexp.escape(@path)}.*$/) Conflict else lock.destroy NoContent end end end end |