Skip to content

Commit

Permalink
Merge branch 'release/1.5.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
kopertop committed Feb 27, 2015
2 parents a3302c0 + 0029a25 commit 72f1cd1
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 9 deletions.
2 changes: 1 addition & 1 deletion botoweb/__init__.py
Expand Up @@ -18,7 +18,7 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
__version__ = '1.5.4'
__version__ = '1.5.5'
env = None
import logging
log = logging.getLogger('botoweb')
Expand Down
72 changes: 66 additions & 6 deletions botoweb/request.py
Expand Up @@ -112,17 +112,74 @@ def formDict(self):
vals[k] = self.POST[k]
return vals

def loginUsingGooglePlus(self):
# Google+ login
from httplib2 import Http
from oauth2client.client import OAuth2WebServerFlow
from apiclient.discovery import build

if not (self.get('state') and self.get('state').startswith('googleplus')):
return None

flow = OAuth2WebServerFlow(client_id=boto.config.get('GooglePlus', 'client_id'),
client_secret=boto.config.get('GooglePlus', 'client_secret'),
scope='email',
state='googleplus',
redirect_uri='postmessage')
flow.redirect_uri = 'postmessage'
code = self.get('code')
if not code:
return None

user = None
try:
credentials = flow.step2_exchange(code)
http = credentials.authorize(Http())
service = build("plus", "v1", http=http)
profile = service.people().get(userId='me').execute()
log.info('Looking up user with profile %s', str(profile))
email = profile['emails'][0]['value']

if email:
log.info('Looking up user email: "%s"' % email)
try:
user = botoweb.user.find(email=email, deleted=False).next()
except StopIteration:
log.warn("Unknown user using Google+ login: %s" % email)
botoweb.report("Unknown user using Google+ login: %s" % email, status=401, req=self, name="LoginFailure", priority=3)
user = None

if user:
log.info("Google+ login: %s as %s" % (email, user))
self._user = user

# Re-use an old auth-token if it's available
from datetime import datetime, timedelta
now = datetime.utcnow()
if user.auth_token and (user.sys_modstamp - now) <= timedelta(hours=6) and user.auth_token.startswith(user.username):
bw_auth_token = user.auth_token
else:
# Set up an Auth Token
bw_auth_token = "%s:%s" % (user.username, uuid.uuid4().hex)
user.auth_token = bw_auth_token
user.put()
self.cookies['BW_AUTH_TOKEN'] = bw_auth_token
addCachedUser(user)
except:
log.exception('Exception while trying Google+ login flow')
return user

def getUser(self):
"""
Get the user from this request object
@return: User object, or None
@rtype: User or None
"""
# We only want to TRY to
# authenticate them once,
# We only want to TRY to
# authenticate them once,
# so we use "False" if they've
# already been attempted to be authed,
# None if they haven't even been through
# already been attempted to be authed,
# None if they haven't even been through
# this yet

if self._user == None:
Expand All @@ -146,7 +203,7 @@ def getUser(self):
if user and user.password == password:
self._user = user
return self._user

# ajax session authentication
session_key = self.cookies.get("session")
if session_key and botoweb.memc:
Expand Down Expand Up @@ -190,6 +247,9 @@ def getUser(self):
self._user = user
return self._user

if self.loginUsingGooglePlus():
return self._user

# google federated login
openID = self.get("openid.op_endpoint")
if openID:
Expand Down Expand Up @@ -237,7 +297,7 @@ def getUser(self):
botoweb.report("Invalid OpenID: %s" % identifier, status=401, req=self, name="LoginFailure", priority=3)
else:
log.warn("An error occured trying to authenticate the user: %s" % openParams)

# JanRain Authentication token
jr_auth_token = self.POST.get("token")
if jr_auth_token:
Expand Down
8 changes: 6 additions & 2 deletions setup.py
Expand Up @@ -16,7 +16,7 @@
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
Expand All @@ -39,7 +39,7 @@
license = 'MIT',
scripts = ['tools/botoweb', 'tools/botoweb_client', 'tools/bw_client_upload'],
platforms = 'Posix; MacOS X; Windows',
classifiers = [
classifiers = [
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
Expand All @@ -55,5 +55,9 @@
"boto",
"lxml",
"pytz",
# The next three are required to handle Google+ login
"httplib2",
"urllib3",
"google_api_python_client",
],
)

0 comments on commit 72f1cd1

Please sign in to comment.