commit 64bc06455732abcb7f987707b02deff4d636392a Author: Brandon4466 Date: Sat Jul 1 23:39:34 2023 -0700 old project, new git. welcome to echo diff --git a/.deployment b/.deployment new file mode 100644 index 0000000..6278331 --- /dev/null +++ b/.deployment @@ -0,0 +1,2 @@ +[config] +SCM_DO_BUILD_DURING_DEPLOYMENT=true \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8f03554 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + "appService.zipIgnorePattern": [ + "__pycache__{,/**}", + "*.py[cod]", + "*$py.class", + ".Python{,/**}", + "build{,/**}", + "develop-eggs{,/**}", + "dist{,/**}", + "downloads{,/**}", + "eggs{,/**}", + ".eggs{,/**}", + "lib{,/**}", + "lib64{,/**}", + "parts{,/**}", + "sdist{,/**}", + "var{,/**}", + "wheels{,/**}", + "share/python-wheels{,/**}", + "*.egg-info{,/**}", + ".installed.cfg", + "*.egg", + "MANIFEST", + ".env{,/**}", + ".venv{,/**}", + "env{,/**}", + "venv{,/**}", + "ENV{,/**}", + "env.bak{,/**}", + "venv.bak{,/**}", + ".vscode{,/**}" + ], + "appService.defaultWebAppToDeploy": "/subscriptions/9d8af010-9453-475c-94bf-57ddced940ff/resourceGroups/theEcho_group/providers/Microsoft.Web/sites/theEcho", + "appService.deploySubpath": "." +} \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..e63e25b --- /dev/null +++ b/app.py @@ -0,0 +1,173 @@ +from flask import Flask, Blueprint, render_template, redirect, url_for, request, flash +from flask_sqlalchemy import SQLAlchemy +from flask_login import UserMixin, LoginManager, login_user, login_required, logout_user, current_user +import datetime +import urllib.parse +import save_azure + +db = SQLAlchemy() + +params = urllib.parse.quote_plus("Driver={ODBC Driver 18 for SQL Server};Server=tcp:theecho.database.windows.net,1433;Database=echo;Uid=echoDB;Pwd=Mariposa2502mARIPOSA2502$$2502$$;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;") + +app = Flask(__name__) + +app.config['SECRET_KEY'] = 'alpha-echo-testing' +app.config['SQLALCHEMY_DATABASE_URI'] = "mssql+pyodbc:///?odbc_connect=%s" % params +app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True + +# app.config['SECRET_KEY'] = 'echo-alpha-testing' +# app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite' + +db.init_app(app) + +class User(UserMixin, db.Model): + id = db.Column(db.Integer, primary_key=True) + handle = db.Column(db.String(25)) + email = db.Column(db.String(100), unique=True) + password = db.Column(db.String(100)) + name = db.Column(db.String(1000)) + pp = db.Column(db.String(1000)) + echos = db.relationship('Echo', backref='user', lazy=True) + +class Echo(db.Model): + id = db.Column(db.Integer, primary_key=True) + handle = db.Column(db.String(25)) + name = db.Column(db.String(1000)) + echo = db.Column(db.String(2000)) + date = db.Column(db.DateTime, default=datetime.datetime.utcnow, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + replies = db.relationship('Reply', backref='echo', lazy=True) + +class Reply(db.Model): + id = db.Column(db.Integer, primary_key=True) + handle = db.Column(db.String(25)) + name = db.Column(db.String(1000)) + reply = db.Column(db.String(2000)) + date = db.Column(db.DateTime, default=datetime.datetime.utcnow, nullable=False) + echo_id = db.Column(db.Integer, db.ForeignKey('echo.id'), nullable=False) + +with app.app_context(): + db.create_all() + +login_manager = LoginManager() +login_manager.login_view = 'login' +login_manager.init_app(app) + +@login_manager.user_loader +def load_user(user_id): + # since the user_id is just the primary key of our user table, use it in the query for the user + return User.query.get(int(user_id)) + +@app.route("/") +def index(): + return render_template('index.html', echos=Echo.query.all(), replies=Reply.query.all()) + +@app.route('/profile') +@login_required +def profile(): + return render_template('profile.html', name=current_user.name, echos=current_user.echos) + +@app.route('/echo', methods=['POST']) +@login_required +def echo(): + echo = request.form.get('echo') + + db.session.add(Echo(echo=echo, user_id=current_user.id, handle=current_user.handle, name=current_user.name)) + db.session.commit() + return redirect(url_for('profile')) + +@app.route('/reply', methods=['POST']) +@login_required +def reply(): + reply = request.form.get('reply') + echo_id = request.form.get('echo_id') + + db.session.add(Reply(reply=reply, echo_id=echo_id, handle=current_user.handle, name=current_user.name)) + db.session.commit() + return redirect(url_for('index')) + +@app.route('/login') +def login(): + return render_template('login.html') + +@app.route('/login', methods=['POST']) +def login_post(): + # login code goes here + email = request.form.get('email') + password = request.form.get('password') + remember = True if request.form.get('remember') else False + + user = User.query.filter_by(email=email).first() + + # check if the user actually exists + # take the user-supplied password, hash it, and compare it to the hashed password in the database + if not user or not (user.password, password): + flash('Please check your login details and try again.') + return redirect(url_for('login')) # if the user doesn't exist or password is wrong, reload the page + login_user(user, remember=remember) + return redirect(url_for('profile')) + +@app.route('/signup') +def signup(): + return render_template('signup.html') + +@app.route('/signup', methods=['POST']) +def signup_post(): + # code to validate and add user to database goes here + handle = request.form.get('handle') + email = request.form.get('email') + name = request.form.get('name') + password = request.form.get('password') + + # email = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database + # handle = User.query.filter_by(handle=handle).first() # if this returns a user, then the handle already exists in database + + if User.query.filter_by(email=email).first() or User.query.filter_by(handle=handle).first(): # if a user is found, we want to redirect back to signup page so user can try again + flash('Email address already exists') + return redirect(url_for('signup')) + + # create a new user with the form data. Hash the password so the plaintext version isn't saved. + new_user = User(handle=handle, email=email, name=name, password=password) + + # add the new user to the database + db.session.add(new_user) + db.session.commit() + return redirect(url_for('login')) + +@app.route('/') +@login_required +def user(handle): + return render_template('user.html', handle=handle , echos=Echo.query.filter_by(handle=handle).all()) + +# upload a profile picture +@app.route('/pp', methods=['POST']) +@login_required +def pp(): + pp = request.files['file'] + dir = 'static/pp/' + if pp.filename.endswith('.jpg'): + pp.save(dir + current_user.handle + '.jpg') + filename = current_user.handle + '.jpg' + elif pp.filename.endswith('.png'): + pp.save(dir + current_user.handle + '.png') + filename = current_user.handle + '.png' + path = dir + filename + print(path) + db.session.add(User(pp=save_azure.save(path, filename), id=current_user.id)) + + return redirect(url_for('profile')) + +# @app.route('//') +# @login_required +# def echo_page(handle, echo_id): +# return render_template('echo.html', handle=handle, echo=Echo.query.get(echo_id), replies=Reply.query.filter_by(echo_id=echo_id).all()) + +@app.route('/logout') +@login_required +def logout(): + logout_user() + return redirect(url_for('index')) + +# if __name__ == "__main__": +# app.run(debug=True) +# # app.run(host='0.0.0.0', port=443, ssl_context=('cert.pem', 'privkey.pem')) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b4d7004 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +Flask +Flask_Login +flask_sqlalchemy +pyodbc +azure-storage-blob +azure-identity \ No newline at end of file diff --git a/save_azure.py b/save_azure.py new file mode 100644 index 0000000..7ecb4ea --- /dev/null +++ b/save_azure.py @@ -0,0 +1,21 @@ +from azure.identity import DefaultAzureCredential +from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient + + +def save(path, filename): + account_url = "https://theecho.blob.core.windows.net" + default_credential = DefaultAzureCredential() + + # Create the BlobServiceClient object + blob_service_client = BlobServiceClient(account_url, credential=default_credential) + + container_name = "ppics" + + # Create a blob client using the local file name as the name for the blob + blob_client = blob_service_client.get_blob_client(container=container_name, blob=filename) + + # Upload the created file + with open(file=path, mode="rb") as data: + blob_client.upload_blob(data) + url = account_url + "/" + container_name + "/" + filename + return url \ No newline at end of file diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..87d2d0c Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/icon.png b/static/icon.png new file mode 100644 index 0000000..7919016 Binary files /dev/null and b/static/icon.png differ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..63b5439 Binary files /dev/null and b/static/logo.png differ diff --git a/static/pp/placeholder.jpg b/static/pp/placeholder.jpg new file mode 100644 index 0000000..e69de29 diff --git a/static/robots.txt b/static/robots.txt new file mode 100644 index 0000000..8b76442 --- /dev/null +++ b/static/robots.txt @@ -0,0 +1,5 @@ +User-agent: * +Allow: /generate + +User-agent: * +Allow: / \ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..2eef7a4 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,156 @@ + + + + + + + + + Echo + + + + + + + + + + + +
+
+ +
+ +
+
+ {% block content %} + {% endblock %} +
+
+
+ + + + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..5c17fa0 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,112 @@ +{% extends "base.html" %} + +{% block content %} + +

+ Echo +

+

+ How far does your voice go? +

+ + {% for echo in echos|reverse %} +
+
+
+

+ +

+
+
+
+

+ {{echo.name}} @{{echo.handle}} {{echo.date}} +
+ {{echo.echo}} +

+
+ + {% for reply in replies|reverse %} +
+
+

+ +

+
+
+
+

+ {{reply.name}} @{{reply.handle}} {{reply.date}} +
+ {{reply.reply}} +

+
+ +
+
+ +
+
+ {% endfor %} +
+
+ +
+
+{% endfor %} + + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..b789e4b --- /dev/null +++ b/templates/login.html @@ -0,0 +1,36 @@ +{% extends "base.html" %} + +{% block content %} +
+

Login

+
+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+ {{ messages[0] }} +
+ {% endif %} + {% endwith %} +
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/profile.html b/templates/profile.html new file mode 100644 index 0000000..ee7ad17 --- /dev/null +++ b/templates/profile.html @@ -0,0 +1,94 @@ +{% extends "base.html" %} + +{% block content %} + +
+

+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+
+ {{ messages[0] }} +
+
+ {% endif %} + {% endwith %} + Welcome, {{ name }}!
+

Upload your profile picture:

+
+ + +
+


+
+
+
+ +
+
+ +
+
+ +{% for echo in echos|reverse %} +
+
+
+

+ +

+
+
+
+

+ {{echo.name}} @{{echo.handle}} {{echo.date}} +
+ {{echo.echo}} +

+
+ +
+
+ +
+
+{% endfor %} +
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/signup.html b/templates/signup.html new file mode 100644 index 0000000..4733106 --- /dev/null +++ b/templates/signup.html @@ -0,0 +1,43 @@ +{% extends "base.html" %} + +{% block content %} +
+

Sign Up

+
+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+ {{ messages[0] }}. Go to login page. +
+ {% endif %} + {% endwith %} +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/user.html b/templates/user.html new file mode 100644 index 0000000..ce25972 --- /dev/null +++ b/templates/user.html @@ -0,0 +1,89 @@ +{% extends "base.html" %} + +{% block content %} + +
+

+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+
+ {{ messages[0] }} +
+
+ {% endif %} + {% endwith %} + {{ handle }}'s echos!


+ +
+

+{% for echo in echos|reverse %} +
+
+
+

+ +

+
+
+
+

+ {{echo.name}} @{{echo.handle}} {{echo.date}} +
+ {{echo.echo}} +

+
+ +
+
+ +
+
+{% endfor %} +
+ + + +{% endblock %} \ No newline at end of file