1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2009 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 from functools
import wraps
23 from couchdbkit
import ResourceConflict
25 from django
.http
import Http404
26 from django
.shortcuts
import render
27 from django
.http
import HttpResponseForbidden
, HttpResponseNotAllowed
30 def requires_token(token_name
, denied_template
=None):
32 returns a decorator that checks if the security token in the 'token' GET
33 parameter matches the requires token for the resource. The protected
34 resource is indicated by
35 * the username parameter passed to the decorated function
36 * token_name passed to this method
38 The decorated method is returned, if
39 * no token is required for the resource
40 * the token in the 'token' GET parameter matches the required token
42 If the passed token does not match
43 * the denied_template is rendered and returned if given
44 * HttpResponseForbidden is returned, if denied_template is not given
48 def tmp(request
, username
, *args
, **kwargs
):
50 from mygpo
.users
.models
import User
51 user
= User
.get_user(username
)
55 token
= user
.get_token(token_name
)
56 u_token
= request
.GET
.get('token', '')
58 if token
== '' or token
== u_token
:
59 return fn(request
, username
, *args
, **kwargs
)
63 return render(request
, denied_template
, {
68 return HttpResponseForbidden()
74 def allowed_methods(methods
):
77 def tmp(request
, *args
, **kwargs
):
78 if request
.method
in methods
:
79 return fn(request
, *args
, **kwargs
)
81 return HttpResponseNotAllowed(methods
)
88 class repeat_on_conflict(object):
89 """ Repeats an update operation in case of a ResourceConflict
91 In case of a CouchDB ResourceConflict, reloads the parameter with the given
92 name and repeats the function call until it succeeds. When calling the
93 function, the parameter that should be reloaded must be given as a
96 ARGSPEC
= '__repeat_argspec__'
98 def __init__(self
, obj_names
=[], reload_f
=None):
99 self
.obj_names
= obj_names
100 self
.reload_f
= reload_f
or self
.default_reload
102 def default_reload(self
, obj
):
103 return obj
.__class
__.get(obj
._id
)
105 def build_locals(self
, f
, args
, kwargs
):
106 argspec
= getattr(f
, self
.ARGSPEC
)
107 if len(args
) > len(argspec
.args
):
108 varargs
= args
[len(args
):]
109 args
= args
[:len(args
)]
112 locals = dict(zip(argspec
.args
, args
))
113 if argspec
.varargs
is not None:
114 locals.update({argspec
.varargs
: varargs
})
115 if argspec
.keywords
is not None:
116 locals.update({argspec
.keywords
: kwargs
})
117 locals.update(kwargs
)
120 def __call__(self
, f
):
122 if not hasattr(f
, self
.ARGSPEC
):
123 argspec
= inspect
.getargspec(f
)
124 setattr(f
, self
.ARGSPEC
, argspec
)
127 def wrapper(*args
, **kwargs
):
128 all_args
= before
= self
.build_locals(f
, args
, kwargs
)
130 # repeat until operation succeeds
131 # TODO: adding an upper bound might make sense
136 except ResourceConflict
:
137 for obj_name
in self
.obj_names
:
138 obj
= all_args
[obj_name
]
139 all_args
[obj_name
] = self
.reload_f(obj
)
144 def query_if_required():
145 """ If required, queries some resource before calling the function
147 The decorated method is expected to be bound and its class is
148 expected to have define the methods _needs_query() and _query().
153 def wrapper(self
, *args
, **kwargs
):
155 if self
._needs
_query
():
158 return f(self
, *args
, **kwargs
)