/
application.py
227 lines (207 loc) · 7.25 KB
/
application.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# inspired by https://github.com/cenkalti/github-flask/blob/master/example.py
# setup flask
from flask import Flask, render_template, request, redirect, url_for, jsonify, flash, g, session
from flask.ext.seasurf import SeaSurf
app = Flask(__name__)
csrf = SeaSurf(app)
# setup ssl if needed
"""import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_cert_chain('/etc/ssl/private/server.pem')"""
# setup client id and secret of github application for oauth
from flask.ext.github import GitHub
# config application
app.config['GITHUB_CLIENT_ID'] = 'eeb4dfb78a394e99200c'
app.config['GITHUB_CLIENT_SECRET'] = 'e4a94257eaf8a0724670bd861340e12ff51d92ad'
app_secret = 'gh_app_secret'
github_callback_url = "http://localhost:5000/github-callback"
github = GitHub(app)
# setup sqlalchemy
from sqlalchemy import create_engine, desc
from sqlalchemy.orm import sessionmaker,scoped_session
from database_setup import Base, Category, Item, User
engine = create_engine('sqlite:///catalog.db')
Base.metadata.bind = engine
# http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#sqlalchemy.orm.scoping.scoped_session
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base.query = db_session.query_property()
# flask functions
##################
@app.route('/')
#show whole catalog with latest items
@app.route('/catalog/')
def showCatalog():
categories = Category.query.all()
items = Item.query.order_by(Item.created.desc()).all()
return render_template('catalog.html', categories = categories,items=items,user=g.user)
@app.route('/catalog/<string:category_name>/')
#show a category with its items
def showCategory(category_name):
categories = Category.query.all()
category = Category.query.filter_by(name=category_name).one()
items = Item.query.filter_by(category = category).all()
return render_template('catalog.html', categories = categories,items=items,category=category,user=g.user)
@app.route('/item/<int:item_id>/')
#show a item
def showItem(item_id):
item = Item.query.filter_by(id = item_id).one()
return render_template('item.html', item = item,user=g.user)
@app.route('/catalog/<string:category_name>/add/', methods = ['GET', 'POST'])
#add a item
def addItem(category_name):
categories = Category.query.all()
category = Category.query.filter_by(name = category_name).one()
user = g.user
# check if user is authenticated
if user is not None:
if request.method == 'POST':
# check if an item name was entered
if request.form['name'] != "":
mycategory = Category.query.filter_by(name=request.form['category']).one()
item = Item(name=request.form['name'],
image=request.form['image'],
description=request.form['description'],
category=mycategory,
owner=user)
db_session.add(item)
db_session.commit()
flash("Item " + item.name + " added to " + item.category.name)
return redirect(url_for('showCategory',category_name=mycategory.name))
else:
flash("Item name must not be empty")
return redirect(url_for('addItem',category_name=category_name))
else:
return render_template('additem.html',category=category,categories=categories,user=user)
else:
flash("Unauthorized user")
return redirect(url_for('showCatalog'))
@app.route('/item/<int:item_id>/edit/', methods = ['GET', 'POST'])
#edit a item
def editItem(item_id):
item = Item.query.filter_by(id = item_id).one()
user = g.user
# check if user is owner
if user == item.owner:
if request.method == 'POST':
# check if an item name was entered
if request.form['name'] != "":
item.name = request.form['name']
item.image = request.form['image']
item.description = request.form['description']
if request.form['category']:
category = Category.query.filter_by(name=request.form['category']).one()
item.category = category
db_session.add(item)
db_session.commit()
flash("Item " + item.name + " saved")
return redirect(url_for('showItem',item_id=item.id))
else:
flash("Item name must not be empty")
return redirect(url_for('editItem',item_id=item.id))
else:
categories = Category.query.all()
return render_template('edititem.html', item = item,categories=categories,user=user)
else:
flash("Unauthorized user")
return redirect(url_for('showCatalog'))
@app.route('/item/<int:item_id>/delete/', methods = ['GET', 'POST'])
#delete a item
def deleteItem(item_id):
item = Item.query.filter_by(id = item_id).one()
category = item.category
user = g.user
# check if user is owner
if user == item.owner:
if request.method == 'POST':
flash("Item " + item.name + " deleted")
db_session.delete(item)
db_session.commit()
return redirect(url_for('showCategory', category_name=category.name))
else:
return render_template('deleteitem.html', item = item, user=g.user)
else:
flash("Unauthorized user")
return redirect(url_for('showCatalog'))
@app.route('/login')
#user Login
def loginUser():
# send user back to the source page
uri = github_callback_url + "?next=" + request.referrer
return github.authorize(redirect_uri=uri)
# if session.get('user_id', None) is None:
# return github.authorize()
# else:
# flash('User is already logged in')
# return redirect(url_for('showCatalog'))
#logout user and show main catalog view
@app.route('/logout')
def logoutUser():
session.pop('user_id', None)
flash('User logged out')
return redirect(url_for('showCatalog'))
@app.route('/github-callback')
#callback for github oauth
@github.authorized_handler
def authorized(oauth_token):
next_url = request.args.get('next') or url_for('showCatalog')
if oauth_token is None:
# something went wront
flash("Authorization failed")
flash(request.args.get('error'))
flash(request.args.get('error_description'))
flash(request.args.get('error_uri'))
return redirect(next_url)
user = User.query.filter_by(github_access_token=oauth_token).first()
if user is None:
# new user is not in database
user = User(name="",github_access_token=oauth_token)
db_session.add(user)
# save oauth token in database
user.github_access_token = oauth_token
db_session.commit()
session['user_id'] = user.id
flash("User " + user.name + " logged in")
return redirect(next_url)
@github.access_token_getter
#github token getter
def token_getter():
user = g.user
if user is not None:
return user.github_access_token
# Registers a function to run before each request.
@app.before_request
#save user data to database, maybe it changed or user is new
def before_request():
g.user = None
if 'user_id' in session:
g.user = User.query.get(session['user_id'])
g.user.name = github.get('user')["name"]
g.user.avatar = github.get('user')["avatar_url"]
db_session.add(g.user)
db_session.commit()
@app.after_request
#Register a function to be run after each request
def after_request(response):
db_session.remove()
return response
@app.route('/json')
#json api for list of all items
def catalogjson():
list = []
items = Item.query.all()
for item in items:
list.append({"name" : item.name,
"id" : item.id,
"description" : item.description,
"category" : item.category.name,
"image" : item.image,
"owner" : item.owner.name
})
return jsonify({"items":list})
# run flask server if script is started directly
if __name__ == '__main__':
app.debug = False
app.secret_key = app_secret
app.run(host = '0.0.0.0', port = 5000)