OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Utilities for generating and verifying user authentication.""" |
| 6 |
| 7 __author__ = 'agable@google.com (Aaron Gable)' |
| 8 |
| 9 |
| 10 import functools |
| 11 import logging |
| 12 |
| 13 from google.appengine.api import users |
| 14 from google.appengine.ext import ndb |
| 15 |
| 16 import constants |
| 17 import model |
| 18 |
| 19 |
| 20 def CheckUserAuth(handler): |
| 21 """Decorator for webapp2 request handler methods. |
| 22 |
| 23 Only use on webapp2.RequestHandler methods (e.g. get, post, put). |
| 24 |
| 25 Checks to see if the user is logged in, and if they are |
| 26 * If they are an administrator of the app, or |
| 27 * If their email appears in the list of allowed addresses |
| 28 |
| 29 Sets request.authenticated to 'user' if successful. Otherwise, None. |
| 30 """ |
| 31 @functools.wraps(handler) |
| 32 def wrapper(self, *args, **kwargs): |
| 33 """Does the real legwork and calls the wrapped handler.""" |
| 34 def abort_auth(log_msg): |
| 35 """Helper method to be an exit hatch when authentication fails.""" |
| 36 logging.warning(log_msg) |
| 37 self.request.authenticated = None |
| 38 handler(self, *args, **kwargs) |
| 39 |
| 40 def finish_auth(log_msg): |
| 41 """Helper method to be an exit hatch when authentication succeeds.""" |
| 42 logging.info(log_msg) |
| 43 self.request.authenticated = 'user' |
| 44 handler(self, *args, **kwargs) |
| 45 |
| 46 if getattr(self.request, 'authenticated', None): |
| 47 finish_auth('Already authenticated.') |
| 48 return |
| 49 |
| 50 user = users.get_current_user() |
| 51 if not user: |
| 52 abort_auth('No logged in user.') |
| 53 return |
| 54 |
| 55 if users.is_current_user_admin(): |
| 56 finish_auth('User is admin.') |
| 57 return |
| 58 |
| 59 email = user.email() |
| 60 email_list = ndb.Key(model.EmailList, constants.LIST).get() |
| 61 allowed_emails = email_list.emails if email_list else [] |
| 62 |
| 63 if email in allowed_emails: |
| 64 finish_auth('User in allowed email list.') |
| 65 return |
| 66 |
| 67 if (email.endswith('@google.com') and |
| 68 email.replace('@google.com', '@chromium.org') in allowed_emails): |
| 69 finish_auth('User in allowed email list via google -> chromium map.') |
| 70 return |
| 71 |
| 72 abort_auth('User not in allowed email list.') |
| 73 |
| 74 return wrapper |
| 75 |
| 76 |
| 77 def RequireAuth(handler): |
| 78 """Decorator for webapp2 request handler methods. |
| 79 |
| 80 Only use on webapp2.RequestHandler methods (e.g. get, post, put), |
| 81 and only after using a 'Check____Auth' decorator. |
| 82 |
| 83 Expects the handler's self.request.authenticated to be not False-ish. |
| 84 If it doesn't exist or evaluates to False, 403s. Otherwise, passes |
| 85 control to the wrapped handler. |
| 86 """ |
| 87 @functools.wraps(handler) |
| 88 def wrapper(self, *args, **kwargs): |
| 89 """Does the real legwork and calls the wrapped handler.""" |
| 90 if not getattr(self.request, 'authenticated', None): |
| 91 self.abort(403) |
| 92 else: |
| 93 handler(self, *args, **kwargs) |
| 94 |
| 95 return wrapper |
OLD | NEW |