From b3ecbbbbc265b5384dcf45b910422f5a32322839 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 11 Nov 2018 17:30:33 +1000 Subject: [PATCH] updated database schema (hopefully for the last time now), started work on home page and login functions --- templates/create_password.html | 2 +- templates/home.html | 12 ++++-- web.py | 75 +++++++++++++++++++++++++++------- 3 files changed, 70 insertions(+), 19 deletions(-) diff --git a/templates/create_password.html b/templates/create_password.html index 1a94997..05625c3 100644 --- a/templates/create_password.html +++ b/templates/create_password.html @@ -9,7 +9,7 @@

Please enter a password for your new Curious Greg account.

-
+
{{ session['acct'] }}



diff --git a/templates/home.html b/templates/home.html index 1f7ded7..da51c06 100644 --- a/templates/home.html +++ b/templates/home.html @@ -6,10 +6,16 @@

Welcome

-

You're all set up and ready to go.

-
- You haven't posted to Curious Cat in a while, so we'll wait 14 minutes until we check for new answers. +
+
Mastodon
+
+ {{ session['acct'] }}

+
+
+
Curious Cat
+
+ {{ session['cc'] }}

{% include 'footer.html' %} diff --git a/web.py b/web.py index a881565..00efda2 100755 --- a/web.py +++ b/web.py @@ -4,7 +4,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -import requests, json, hashlib, urllib +import requests, json, hashlib, urllib, time from mastodon import Mastodon from flask import Flask, render_template, request, session, redirect, url_for import mysql.connector @@ -15,7 +15,24 @@ scopes = ["read:accounts", "write:statuses"] db = mysql.connector.connect(user=cfg['dbuser'], password=cfg['dbpass'], database=cfg['dbname']) c = db.cursor() -c.execute("CREATE TABLE IF NOT EXISTS `data` (username TINYTEXT NOT NULL, instance TINYTEXT NOT NULL, password TINYTEXT NOT NULL, avi TEXT NOT NULL, secret TINYTEXT NOT NULL, client_id TINYTEXT NOT NULL, client_secret TINYTEXT NOT NULL, cc TINYTEXT, latest_post TINYTEXT, latest_timestamp TIMESTAMP, time_between_checks INT)") +# MariaDB [curiousgreg]> DESCRIBE data; +# +---------------------+--------------+------+-----+-------------------------------------------+-----------------------------+ +# | Field | Type | Null | Key | Default | Extra | +# +---------------------+--------------+------+-----+-------------------------------------------+-----------------------------+ +# | username | varchar(64) | NO | PRI | NULL | | +# | instance | varchar(128) | NO | PRI | NULL | | +# | password | tinytext | NO | | NULL | | +# | avi | text | NO | | NULL | | +# | secret | tinytext | NO | | NULL | | +# | client_id | varchar(128) | NO | | NULL | | +# | client_secret | tinytext | NO | | NULL | | +# | cc | tinytext | YES | | NULL | | +# | ccavi | varchar(128) | YES | | https://lynnesbian.space/res/ceres/cc.png | | +# | latest_post | tinytext | YES | | NULL | | +# | latest_timestamp | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +# | time_between_checks | int(11) | YES | | NULL | | +# +---------------------+--------------+------+-----+-------------------------------------------+-----------------------------+ +c.execute("CREATE TABLE IF NOT EXISTS `data` (username VARCHAR(64) NOT NULL, instance VARCHAR(128) NOT NULL, password TINYTEXT NOT NULL, avi TEXT NOT NULL, secret TINYTEXT NOT NULL, client_id VARCHAR(128) NOT NULL, client_secret TINYTEXT NOT NULL, cc TINYTEXT, ccavi VARCHAR(128) DEFAULT 'https://lynnesbian.space/res/ceres/cc.png', latest_post TINYTEXT, latest_timestamp TIMESTAMP, time_between_checks INT, PRIMARY KEY(username, instance))") app = Flask(cfg['name']) app.secret_key = cfg['flask_key'] @@ -30,8 +47,29 @@ def main(): @app.route('/home') def home(): if 'acct' in session: - acct = session['acct'] - return render_template("home.html", acct=acct) + if 'cc' not in session: + session['cc'] = "None" + if session['cc'] == "None": + #every time home is rendered without cc being set + cc = c.execute("SELECT cc FROM `data` WHERE client_id LIKE ? AND instance LIKE ?", (session['client_id'], session['instance'])).fetchone()[0] + if cc != '': + session['cc'] = cc + + if 'last_avi_update' not in session or session['last_avi_update'] + (24 * 60 * 60) < time.time(): + #avatars haven't been updated for over 24 hours + # avis = c.execute("SELECT avi, ccavi FROM `data` WHERE client_id LIKE ?", (session['client_id'],)).fetchone() + client = Mastodon(client_id=session['client_id'], client_secret=session['client_secret'], api_base_url=session['instance']) + + session['avi'] = client.account_verify_credentials()['avatar'] + if session['cc'] != None: + #update cc avi too + r = requests.get("https://curiouscat.me/api/v2/profile?username={}".format(session['cc'])) + j = r.json() + session['ccavi'] = j['userData']['avatar'] + c.execute("UPDATE data SET avi = ?, ccavi = ? WHERE client_id LIKE ? AND instance LIKE ?", (session['avi'], session['ccavi'], session['client_id'], session['instance'])) + else: + c.execute("UPDATE data SET avi = ? WHERE client_id LIKE ? AND instance LIKE ?", (session['avi'], session['client_id'], session['instance'])) + return render_template("home.html") else: return redirect(url_for('main')) @@ -54,18 +92,18 @@ def log_in(): @app.route('/internal/auth_a') def internal_auth_a(): #TODO: prevent these endpoints from being spammed somehow - session['instance_url'] = request.args.get('instance', default='mastodon.social', type=str) - if not session['instance_url'].startswith("https://"): - session['instance_url'] = "https://{}".format(session['instance_url']) + session['instance'] = request.args.get('instance', default='mastodon.social', type=str) + if not session['instance'].startswith("https://"): + session['instance'] = "https://{}".format(session['instance']) session['client_id'], session['client_secret'] = Mastodon.create_app(cfg['name'], - api_base_url=session['instance_url'], + api_base_url=session['instance'], scopes=scopes, website=cfg['website'], redirect_uris=['https://cg.lynnesbian.space/internal/auth_b', 'http://localhost:5000/internal/auth_b'] ) - client = Mastodon(client_id=session['client_id'], client_secret=session['client_secret'], api_base_url=session['instance_url']) + client = Mastodon(client_id=session['client_id'], client_secret=session['client_secret'], api_base_url=session['instance']) url = client.auth_request_url(client_id=session['client_id'], redirect_uris='http://localhost:5000/internal/auth_b', scopes=scopes) return redirect(url, code=307) @@ -73,14 +111,16 @@ def internal_auth_a(): #TODO: prevent these endpoints from being spammed somehow @app.route('/internal/auth_b') def internal_auth_b(): #write details to DB - client = Mastodon(client_id=session['client_id'], client_secret=session['client_secret'], api_base_url=session['instance_url']) + client = Mastodon(client_id=session['client_id'], client_secret=session['client_secret'], api_base_url=session['instance']) session['secret'] = client.log_in(code = request.args.get('code'), scopes=scopes, redirect_uri='http://localhost:5000/internal/auth_b') acct_info = client.account_verify_credentials() session['username'] = acct_info['username'] session['avi'] = acct_info['avatar'] - session['acct'] = "@{}@{}".format(session['username'], session['instance_url'].replace("https://", "")) - if c.execute("SELECT COUNT(*) FROM data WHERE username LIKE ? AND instance LIKE ?", (session['username'], session['instance_url'])).fetchone()[0] > 0: + session['acct'] = "@{}@{}".format(session['username'], session['instance'].replace("https://", "")) + if c.execute("SELECT COUNT(*) FROM data WHERE username LIKE ? AND instance LIKE ?", (session['username'], session['instance'])).fetchone()[0] > 0: #user already has an account with CG + #update the user's info to use the new info we just got, then redirect them to the login page + c.execute("UPDATE data SET client_id = ?, client_secret = ?, secret = ?, avi = ? WHERE username LIKE ? AND instance LIKE ?", (session['client_id'], session['client_secret'], session['secret'], session['avi'], session['username'], session['instance'])) return redirect(url_for('log_in')) else: return redirect(url_for('home')) @@ -91,10 +131,15 @@ def do_login(): @app.route('/create_password') def create_password(): - return render_template("create_password.html") + return render_template("create_password.html", bg = "\"background-image:url('{}')\"".format(session['avi'])) @app.route('/internal/create_account', methods=['POST']) def create_account(): - pw = bcrypt.hashpw(request.form['pw'], bcrypt.gensalt(15)) - c.execute("INSERT INTO data (username, instance, avi, password, secret, client_id, client_secret) VALUES (?, ?, ?, ?, ?)", (session['username'], pw, session['instance_url'], session['secret'], session['client_id'], session['client_secret'])) + pw_in = request.form['pw'] + if len(pw_in < 6) or pw_in == 'password': + return redirect('/create_password?invalid') + pw_hashed = hashlib.sha256(pw_in.encode('utf-8')) + pw = bcrypt.hashpw(pw_hashed, bcrypt.gensalt(15)) + c.execute("INSERT INTO data (username, instance, avi, password, secret, client_id, client_secret) VALUES (?, ?, ?, ?, ?)", (session['username'], pw, session['instance'], session['secret'], session['client_id'], session['client_secret'])) db.commit() + return redirect(url_for('home'))