Jak utworzyć funkcję dekoratora Pythona w kolbie z argumentami (do autoryzacji)
Użyłem fragmentu kolby dla mojego logowania do kolby, które sprawdza, czy użytkownik jest zalogowany:
from functools import wraps
def logged_in(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if session.get('logged_in') is not None:
return f(*args, **kwargs)
else:
flash('Please log in first.', 'error')
return redirect(url_for('login'))
return decorated_function
I dekoruję widoki w taki sposób:
@app.route('/secrets', methods=['GET', 'POST'])
@logged_in
def secrets():
error = None
Chciałbym też zrobić coś podobnego do autoryzacji. W tej chwili mam wiele widoków, aby sprawdzić, czy użytkownik jest właścicielem zasobu, powiedzmyhotdogs
ratunek.
Jeśli użytkownik zalogowany jest właścicielem tego hot-doga, może edytować i zarządzać swoimi hot dogami. Jeśli nie, wyrzucam go na nieautoryzowany ekran.
@app.route('/<hotdog>/addmustard/',methods=["GET"])
@logged_in
def addmustard(hotdog):
if not (authorizeowner(hotdog)):
return redirect(url_for('unauthorized'))
do_stuff()
authorizeowner()
przyjmuje hotdog jako wejście i sprawdza, czy zarejestrowany właściciel hot-doga pasuje do nazwy właściciela wymienionej w zmiennej sesji.
Próbowałem, aby funkcja wrapper / decorator typu owns_hotdog była podobna do mojej zalogowanej, ale skarżyła się, że nie akceptuje argumentów. Jak mogę osiągnąć coś podobnego? Coś jak...
def owns_hotdog(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not authorizeowner(hotdog):
return f(*args, **kwargs)
else:
flash('Please log in first.', 'error')
return redirect(url_for('login'))
return decorated_function
Wydaje się, że z komunikatu o błędzie dekorator nie otrzymuje argumentu hot-dog, do którego widoki Flask mają dostęp ze zmiennej na trasie. Mam nadzieję na coś takiego ...
@app.route('/<hotdog>/addmustard/',methods=["GET"])
@logged_in
@owns_hotdog(hotdog)
def addmustard(hotdog):
do_stuff()
Wszystko działa z moją obecną funkcją authorizeowner (hotdog), ale wydaje mi się, że jest bardziej czysta, aby mieć ją jako wrapper na mojej trasie, a nie jako pierwszą linię wewnątrz trasy.
Inne uwagi:
Wiem, że Flask-Security i Flask-Principal mogą zarządzać autoryzacją dla mnie. Niestety używam nieobsługiwanego zaplecza bazy danych i nie mogę korzystać z tych rozszerzeń. Więc jestem zmuszony do uwierzytelniania bez nich.Jeśli widzisz w ten sposób rażące dziury w autoryzacji, daj mi znać!