· 5 years ago · Jun 06, 2020, 08:10 PM
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
9
10from helpers import apology, login_required, lookup, usd
11
12# Configure application
13app = Flask(__name__)
14
15# Ensure templates are auto-reloaded
16app.config["TEMPLATES_AUTO_RELOAD"] = True
17
18# Ensure responses aren't cached
19@app.after_request
20def after_request(response):
21 response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
22 response.headers["Expires"] = 0
23 response.headers["Pragma"] = "no-cache"
24 return response
25
26# Custom filter
27app.jinja_env.filters["usd"] = usd
28
29# Configure session to use filesystem (instead of signed cookies)
30app.config["SESSION_FILE_DIR"] = mkdtemp()
31app.config["SESSION_PERMANENT"] = False
32app.config["SESSION_TYPE"] = "filesystem"
33Session(app)
34
35# Configure CS50 Library to use SQLite database
36db = SQL("sqlite:///finance.db")
37
38# Make sure API key is set
39if not os.environ.get("API_KEY"):
40 raise RuntimeError("API_KEY not set")
41
42
43@app.route("/")
44@login_required
45def index():
46 rows = db.execute("SELECT * FROM purchases WHERE id = ?", session["user_id"])
47 return render_template("index.html", rows = rows)
48
49@app.route("/buy", methods=["GET", "POST"])
50@login_required
51def buy():
52 if request.method == "GET":
53 return render_template("buy.html")
54 else:
55 symbol = request.form.get("symbol")
56 shares = request.form.get("share_number")
57 if lookup(symbol) == None:
58 return apology("Invalid Symbol")
59 data = lookup(symbol)
60 total_price = data["price"] * shares
61 his_cash = db.execute("SELECT cash FROM users WHERE id = ?", session["user_id"])
62 if his_cash >= total_price:
63 remaining = his_cash - total_price
64 db.execute("UPDATE users SET cash = ? WHERE id = ?", remaining, session["user_id"])
65 db.execute("INSERT INTO purchases (id, shares, stock) VALUES (?, ?, ?)", session["user_id"], shares, symbol)
66 else:
67 return apology("Not enough cash")
68
69@app.route("/history")
70@login_required
71def history():
72 """Show history of transactions"""
73 return apology("TODO")
74
75
76@app.route("/login", methods=["GET", "POST"])
77def login():
78 """Log user in"""
79
80 # Forget any user_id
81 session.clear()
82
83 # User reached route via POST (as by submitting a form via POST)
84 if request.method == "POST":
85
86 # Ensure username was submitted
87 if not request.form.get("username"):
88 return apology("must provide username", 403)
89
90 # Ensure password was submitted
91 elif not request.form.get("password"):
92 return apology("must provide password", 403)
93
94 # Query database for username
95 rows = db.execute("SELECT * FROM users WHERE username = :username",
96 username=request.form.get("username"))
97
98 # Ensure username exists and password is correct
99 if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
100 return apology("invalid username and/or password", 403)
101
102 # Remember which user has logged in
103 session["user_id"] = rows[0]["id"]
104
105 # Redirect user to home page
106 return redirect("/")
107
108 # User reached route via GET (as by clicking a link or via redirect)
109 else:
110 return render_template("login.html")
111
112
113@app.route("/logout")
114def logout():
115 """Log user out"""
116
117 # Forget any user_id
118 session.clear()
119
120 # Redirect user to login form
121 return redirect("/")
122
123@app.route("/quote", methods=["GET", "POST"])
124@login_required
125def quote():
126 if request.method == "GET":
127 return render_template("quote.html")
128 else:
129 lookup_data = lookup(request.form.get("symbol"))
130 if lookup_data == None:
131 return apology("Invalid Symbol")
132 else:
133 return render_template("quote_result.html", cost = lookup_data["price"], name_of_company = lookup_data["name"], symbol = lookup_data["symbol"])
134
135
136@app.route("/register", methods=["GET", "POST"])
137def register():
138 if request.method == "GET":
139 return render_template("register.html")
140 else:
141 if not request.form.get("username"):
142 return apology("You forgot to enter a username")
143 elif not request.form.get("password"):
144 return apology("You forgot to enter a password")
145 elif not request.form.get("password_again"):
146 return apology("You forgot to confirm your password")
147 elif request.form.get("password_again") != request.form.get("password"):
148 return apology("Password confirmation is wrong")
149 elif request.form.get("username") == db.execute("SELECT username FROM users WHERE username = ?", request.form.get("username")):
150 return apology("Username not available")
151 db.execute("INSERT INTO users (username, hash) VALUES (?, ?)", request.form.get("username"), generate_password_hash(request.form.get("password")))
152 return redirect("/")
153
154
155
156
157
158@app.route("/sell", methods=["GET", "POST"])
159@login_required
160def sell():
161 """Sell shares of stock"""
162 return apology("TODO")
163
164
165def errorhandler(e):
166 """Handle error"""
167 if not isinstance(e, HTTPException):
168 e = InternalServerError()
169 return apology(e.name, e.code)
170
171
172# Listen for errors
173for code in default_exceptions:
174 app.errorhandler(code)(errorhandler)