-
Notifications
You must be signed in to change notification settings - Fork 2
/
frontend.py
255 lines (208 loc) · 8.48 KB
/
frontend.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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
"""This file defines the front-end part of the service.
It elaborates how the services should handle different
http requests from the client (browser) through templating.
The html templates are stored in the 'templates' folder.
"""
from flask import render_template, request, session, redirect, flash
from qa327 import app
from qa327.login_format import (
is_valid_password, is_valid_username, is_valid_email
)
from qa327.ticket_format import (
is_valid_ticket_name, is_valid_quantity, is_valid_price, is_valid_date
)
import qa327.backend as bn
from qa327.authenticate import authenticate
@app.route('/register', methods=['GET'])
def register_get():
"""
If a user is logged in redirect to the home page, otherwise redirect to register
:return: home page if logged in, register page if not logged in
"""
if 'logged_in' in session:
return redirect('/', code=303)
# templates are stored in the templates folder
return render_template('register.html', message='')
@app.route('/register', methods=['POST'])
def register_post():
"""
Intake register form information and validate that all entered information follows
requirements R1 (login) and R2 (register).
:return: if requirement not met, error page with specific error message
:return: if requirements met, redirect to login page
"""
email = request.form.get('email')
name = request.form.get('name')
password = request.form.get('password')
password2 = request.form.get('password2')
def error_page(msg):
"""
Render error message on register page.
:param msg: text of the error message
:return: register page with error message
"""
flash(msg)
return redirect('/login', code=303)
if not is_valid_email(email):
return error_page("Email format is incorrect")
if not is_valid_password(password):
return error_page("Password format is incorrect")
if not is_valid_password(password2):
return error_page("Password2 format is incorrect")
if not is_valid_username(name):
return error_page("Username format is incorrect")
if password != password2:
return error_page("The passwords do not match")
user = bn.get_user(email)
if user:
return render_template('register.html', message="User exists")
if not bn.register_user(email, name, password, password2):
return error_page("Failed to store user info.")
flash('User registered successfully')
return redirect('/login', code=303)
@app.route('/login', methods=['GET'])
def login_get():
"""If user is logged in, redirect to home page, otherwise redirect to login"""
if 'logged_in' in session:
# success! go back to the home page
# code 303 is to force a 'GET' request
return redirect('/', code=303)
return render_template('login.html', message='Please Login')
@app.route('/login', methods=['POST'])
def login_post():
'''Intake all login form information and validate using login_user then redirect to home'''
email = request.form.get('email')
password = request.form.get('password')
user = bn.login_user(email, password)
if user:
session['logged_in'] = user.email
'''
Session is an object that contains sharing information
between browser and the end server. Typically it is encrypted
and stored in the browser cookies. They will be past
along between every request the browser made to this services.
Here we store the user object into the session, so we can tell
if the client has already login in the following sessions.
'''
# success! go back to the home page
# code 303 is to force a 'GET' request
return redirect('/', code=303)
flash('email/password combination incorrect')
return redirect('/login', code=303)
#return render_template('login.html', message='Please Login')
@app.route('/buy', methods=['POST'])
def buy_post(user):
'''
Intake all information from the buying ticket form and ensure it meets all requirements
outlined in R6.
:return: if invalid information, redirect to user page with error
:return: if valid information, decrease quantity of tickets and user's balance
'''
def error_page(msg):
'''
Render error message on home page.
:param msg: text of the error message
:return: home page with error message
'''
flash(msg)
return redirect('/', 303)
name = request.form.get('buy-ticket-name')
quantity = request.form.get('buy-ticket-quantity')
if not is_valid_ticket_name(name):
return error_page('Invalid ticket name')
if not is_valid_quantity(quantity):
return error_page('Invalid ticket quantity')
flash(bn.buy_ticket(user, request.form))
return redirect('/', 303)
@app.route('/sell', methods=['POST'])
@authenticate
def sell_post(user):
'''
Intake all information from ticket selling form and validate it meets requirements
:return: if requirements are not met, redirect to user page with error
:return: if requirements are met, post ticket information to user page
'''
name = request.form.get('sell-ticket-name')
quantity = request.form.get('sell-ticket-quantity')
price = request.form.get('sell-ticket-price')
expiration = request.form.get('sell-ticket-expiration-date')
def error_page(msg):
"""
Render error message on register page.
:param msg: text of the error message
:return: register page with error message
"""
flash(msg)
return redirect('/', code=303)
if not is_valid_ticket_name(name):
return error_page('Invalid ticket name')
if not is_valid_quantity(quantity):
return error_page('Invalid ticket quantity')
if not is_valid_price(price):
return error_page('Invalid ticket price')
if not is_valid_date(expiration):
return error_page('Invalid ticket date')
flash(bn.sell_ticket(user, request.form))
return redirect('/', 303)
@app.route('/update', methods=['POST'])
def update_post(user):
'''update a ticket using the HTML form'''
def error_page(msg):
"""
Render error message on index page.
:param msg: text of the error message
:return: default page with error message
"""
flash(msg)
return redirect('/', code=303)
prev_ticket_name = request.form.get('update-prev-ticket-name')
upt_ticket_name = request.form.get('update-upt-ticket-name')
ticket_quantity = request.form.get('update-ticket-quantity')
ticket_price = request.form.get('update-ticket-price')
ticket_expiration_date = request.form.get('update-ticket-expiration-date')
is_blank = {
'name': len(upt_ticket_name) == 0,
'quantity' : len(ticket_quantity) == 0,
'price' : len(ticket_price) == 0,
'exp-date' : len(ticket_expiration_date) == 0
}
if not bn.get_ticket(user.id, prev_ticket_name):
error_page("Ticket doesn't exist")
if is_blank['name'] and not is_valid_ticket_name(upt_ticket_name):
error_page("Ticket name format is inccorrect")
if is_blank['quantity'] and not is_valid_quantity(ticket_quantity):
error_page("Ticket quantity format is inccorrect")
if is_blank['price'] and not is_valid_price(ticket_price):
error_page("Ticket price format is inccorrect")
if is_blank['exp-date'] and not is_valid_date(ticket_expiration_date):
error_page("Ticket expiration date format is inccorrect")
if not bn.update_ticket(user.id, request.form, is_blank):
error_page("Error updating your ticket, please try again")
flash('User updated ticket successfully')
return redirect('/', 303)
@app.route('/logout')
def logout():
"""When user logs out, remove logged in user and redirect to home page
:return: redirect to home page
"""
if 'logged_in' in session:
session.pop('logged_in', None)
return redirect('/')
@app.route('/')
@authenticate
def profile(user):
"""authentication is done in the wrapper function see above.
by using @authenticate, we don't need to re-write
the login checking code all the time for other
front-end portals
"""
tickets = bn.get_all_tickets()
return render_template('index.html', user=user, tickets=tickets)
@app.errorhandler(404)
def page_not_found(error):
"""
Handle 404 errors
:param error: error message
:return: display a 404 error page
"""
return render_template('404.html')