· 5 years ago · Jun 07, 2020, 03:32 AM
1import os
2
3from cs50 import SQL
4from flask import Flask, flash, jsonify, redirect, render_template, request, session
5from flask_session import Session
6from tempfile import mkdtemp
7from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError
8from werkzeug.security import check_password_hash, generate_password_hash
9import datetime
10
11from helpers import apology, login_required, lookup, usd
12
13# Configure application
14app = Flask(__name__)
15
16# Ensure templates are auto-reloaded
17app.config["TEMPLATES_AUTO_RELOAD"] = True
18
19# Ensure responses aren't cached
20@app.after_request
21def after_request(response):
22 response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
23 response.headers["Expires"] = 0
24 response.headers["Pragma"] = "no-cache"
25 return response
26
27# Custom filter
28app.jinja_env.filters["usd"] = usd
29
30# Configure session to use filesystem (instead of signed cookies)
31app.config["SESSION_FILE_DIR"] = mkdtemp()
32app.config["SESSION_PERMANENT"] = False
33app.config["SESSION_TYPE"] = "filesystem"
34Session(app)
35
36# Configure CS50 Library to use SQLite database
37db = SQL("sqlite:///finance.db")
38
39# Make sure API key is set
40if not os.environ.get("API_KEY"):
41 raise RuntimeError("API_KEY not set")
42
43
44@app.route("/")
45@login_required
46def index():
47 """Show portfolio of stocks"""
48 return apology("TODO")
49
50
51@app.route("/buy", methods=["GET", "POST"])
52@login_required
53def buy():
54 """Buy shares of stock"""
55 if request.method == "GET":
56 return render_template("buy.html")
57
58 else:
59
60 #fields must have inputs
61 if not request.form.get("symbol"):
62 return apology("Please enter symbol", 403)
63 elif not request.form.get("quantity"):
64 return apology("Please enter quantity", 403)
65
66 time = datetime.datetime.now()
67 symbol = request.form.get("symbol")
68 info = lookup(symbol)
69 quantity = int(request.form.get("quantity"))
70 cost = int(info["price"]) * quantity
71 cash = db.execute("SELECT cash FROM users WHERE id = :user_id",
72 session["user_id"])
73 print(cash)
74 print(session["user_id"])
75 balance = cash - cost
76
77 # if symbol doesn't exist return apology
78 if lookup(symbol) == None:
79 return apology("Could not find symbol")
80
81 # quantity must be at least 1 share
82 elif quantity < 1:
83 return apology ("Must purchase at least 1 share")
84
85 elif balance < 0:
86 return apology("Not enough money honey")
87
88 return render_template("quote.html")
89
90
91
92
93
94
95
96
97
98@app.route("/history")
99@login_required
100def history():
101 """Show history of transactions"""
102 return apology("TODO")
103
104
105@app.route("/login", methods=["GET", "POST"])
106def login():
107 """Log user in"""
108
109 # Forget any user_id
110 session.clear()
111
112 # User reached route via POST (as by submitting a form via POST)
113 if request.method == "POST":
114
115 # Ensure username was submitted
116 if not request.form.get("username"):
117 return apology("must provide username", 403)
118
119 # Ensure password was submitted
120 elif not request.form.get("password"):
121 return apology("must provide password", 403)
122
123 # Query database for username
124 rows = db.execute("SELECT * FROM users WHERE username = :username",
125 username=request.form.get("username"))
126
127 # Ensure username exists and password is correct
128 if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
129 return apology("invalid username and/or password", 403)
130
131 # Remember which user has logged in
132 session["user_id"] = rows[0]["id"]
133
134 # Redirect user to home page
135 return redirect("/")
136
137 # User reached route via GET (as by clicking a link or via redirect)
138 else:
139 return render_template("login.html")
140
141
142@app.route("/logout")
143def logout():
144 """Log user out"""
145
146 # Forget any user_id
147 session.clear()
148
149 # Redirect user to login form
150 return redirect("/")
151
152
153@app.route("/quote", methods=["GET", "POST"])
154@login_required
155def quote():
156 if request.method == "GET":
157 return render_template("quote.html")
158 else:
159 # Check to see if symbol exists. If it doesn't give an error message. If it does take them to quoted.html and display info
160 symbol = request.form.get("symbol")
161 if lookup(symbol) == None:
162 return apology("Could not find symbol")
163 else:
164 info = lookup(symbol)
165 return render_template("quoted.html", info=info)
166
167
168
169@app.route("/register", methods=["GET", "POST"])
170def register():
171 """Register user"""
172 if request.method == "GET":
173 return render_template("register.html")
174 else:
175 # Ensure username was submitted
176 if not request.form.get("username"):
177 return apology("must provide username", 403)
178
179 # Ensure password was submitted
180 elif not request.form.get("password"):
181 return apology("must provide password", 403)
182
183 # Ensure password matches confirmation password
184 password = request.form.get("password")
185 confirmation = request.form.get("confirmation")
186
187 if password != confirmation:
188 return apology("passwords must match", 403)
189
190 # Ensure username doesn't already exist (loop over every username...names = db.select(SELECT...))
191 rows = db.execute("SELECT * FROM users WHERE username = :username",
192 username=request.form.get("username"))
193
194 # Ensure username exists and password is correct
195 if len(rows) != 0:
196 return apology("username already exists", 403)
197
198 else:
199 # hash compliments to CS50 link
200 username = request.form.get("username")
201 p_hash = generate_password_hash(request.form.get("password"), method='pbkdf2:sha256', salt_length=8)
202 db.execute("INSERT INTO users (username, hash) VALUES(:username, :hash)", username=username, hash=p_hash)
203 return render_template("login.html")
204
205
206
207
208@app.route("/sell", methods=["GET", "POST"])
209@login_required
210def sell():
211 """Sell shares of stock"""
212 return apology("TODO")
213
214
215def errorhandler(e):
216 """Handle error"""
217 if not isinstance(e, HTTPException):
218 e = InternalServerError()
219 return apology(e.name, e.code)
220
221
222# Listen for errors
223for code in default_exceptions:
224 app.errorhandler(code)(errorhandler)