· 9 years ago · Nov 22, 2016, 01:14 AM
1import os
2import json
3import datetime
4import sqlite3
5import flask_sqlalchemy
6from flask import Flask, url_for, redirect, \
7 render_template, session, request
8from flask_sqlalchemy import SQLAlchemy
9from flask_login import LoginManager, login_required, login_user, \
10 logout_user, current_user, UserMixin
11from requests_oauthlib import OAuth2Session
12from requests.exceptions import HTTPError
13basedir = os.path.abspath(os.path.dirname(__file__))
14os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
15"""App Configuration"""
16class Auth:
17 """Google Project Credentials"""
18 CLIENT_ID = ('some-id'
19 '.apps.googleusercontent.com')
20 CLIENT_SECRET = 'some-secret'
21 REDIRECT_URI = 'https://localhost:5000/gCallback'
22 AUTH_URI = 'https://accounts.google.com/o/oauth2/auth'
23 TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'
24 USER_INFO = 'https://www.googleapis.com/userinfo/v2/me'
25 SCOPE = ['profile', 'email']
26class Config:
27
28 """Base config"""
29 APP_NAME = " Google Login"
30 SECRET_KEY = os.environ.get("SECRET_KEY") or "Top secret"
31class DevConfig(Config):
32
33 """Dev config"""
34 DEBUG = True
35 SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, "test.db")
36class ProdConfig(Config):
37
38 """Production config"""
39 DEBUG = False
40 SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, "prod.db")
41config = {
42 "dev": DevConfig,
43 "prod": ProdConfig,
44 "default": DevConfig
45}
46
47"""APP creation and configuration"""
48app = Flask(__name__)
49app.config.from_object(config['dev'])
50db = SQLAlchemy(app)
51login_manager = LoginManager(app)
52login_manager.login_view = "login"
53login_manager.session_protection = "strong"
54
55""" DB Models """
56
57
58class User(db.Model, UserMixin):
59 __tablename__ = "users"
60 id = db.Column(db.Integer, primary_key=True)
61 email = db.Column(db.String(100), unique=True, nullable=False)
62 name = db.Column(db.String(100), nullable=True)
63 avatar = db.Column(db.String(200))
64 tokens = db.Column(db.Text)
65 created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow())
66 group = db.Column(db.String(100))
67
68@login_manager.user_loader
69def load_user(user_id):
70 return User.query.get(int(user_id))
71
72""" OAuth Session creation """
73
74
75def get_google_auth(state=None, token=None):
76 if token:
77 return OAuth2Session(Auth.CLIENT_ID, token=token)
78 if state:
79 return OAuth2Session(
80 Auth.CLIENT_ID,
81 state=state,
82 redirect_uri=Auth.REDIRECT_URI)
83 oauth = OAuth2Session(
84 Auth.CLIENT_ID,
85 redirect_uri=Auth.REDIRECT_URI,
86 scope=Auth.SCOPE)
87 return oauth
88
89
90@app.route('/')
91@login_required
92def index():
93 return render_template('viewer.html')
94
95
96@app.route('/login')
97def login():
98 if current_user.is_authenticated:
99 return redirect(url_for('index'))
100 google = get_google_auth()
101 auth_url, state = google.authorization_url(
102 Auth.AUTH_URI, access_type='offline')
103 session['oauth_state'] = state
104 return render_template('login.html', auth_url=auth_url)
105
106
107@app.route('/gCallback')
108def callback():
109 if current_user is not None and current_user.is_authenticated:
110 return redirect(url_for('/index'))
111 if 'error' in request.args:
112 if request.args.get('error') == 'access_denied':
113 return 'You denied access.'
114 return 'Error encountered.'
115 if 'code' not in request.args and 'state' not in request.args:
116 return redirect(url_for('login'))
117 else:
118 google = get_google_auth(state=session['oauth_state'])
119 try:
120 token = google.fetch_token(
121 Auth.TOKEN_URI,
122 client_secret=Auth.CLIENT_SECRET,
123 authorization_response=request.url)
124 except HTTPError:
125 return 'HTTPError occurred.'
126 google = get_google_auth(token=token)
127 resp = google.get(Auth.USER_INFO)
128 if resp.status_code == 200:
129 user_data = resp.json()
130 email = user_data['email']
131 user = User.query.filter_by(email=email).first()
132 if user is None:
133 user = User()
134 user.email = email
135 user.name = user_data['name']
136 user.group = "viewer"
137 print(token)
138 user.tokens = json.dumps(token)
139 user.avatar = user_data['picture']
140 db.session.add(user)
141 db.session.commit()
142 login_user(user)
143 return redirect(url_for('index'))
144 return 'Could not fetch your information.'
145@app.route('/logout')
146@login_required
147def logout():
148 logout_user()
149 return redirect(url_for('index'))