Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log in/out #75

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 93 additions & 6 deletions src/recommenderapp/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import json
import sys

from flask import Flask, jsonify, render_template, request
from flask import Flask, jsonify, render_template, request, session, redirect
from flask_cors import CORS
from search import Search
from utils import beautify_feedback_data, send_email_to_user
Expand All @@ -17,29 +17,116 @@
#pylint: disable=wrong-import-position
from src.prediction_scripts.item_based import recommend_for_new_user
#pylint: enable=wrong-import-position

import db

app = Flask(__name__)
app.secret_key = "secret key"

cors = CORS(app, resources={r"/*": {"origins": "*"}})

# Connect to the database
db.connect()
# Initialize the database for users
db.mutation_query('''
CREATE TABLE IF NOT EXISTS users (
email varchar(500),
password varchar(500)
)
''')

def get_user():
"""
Returns the user's email if a user is logged in, otherwise returns none
"""
ret = 'None'
if 'email' in session:
# An email is in the session
ret = session['email']
return ret

@app.route("/")
def landing_page():
"""
Renders the landing page.
Renders the landing page with the user.
"""
return render_template("landing_page.html")
return render_template("landing_page.html", user=get_user())

@app.route("/login")
def login_page():
"""
Renders the login page.
"""
return render_template("login.html", user=get_user())

@app.route("/signup")
def signup_page():
"""
Renders the signup page.
"""
return render_template("signup.html", user=get_user())

@app.route("/search_page")
def search_page():
"""
Renders the search page.
"""
return render_template("search_page.html")
return render_template("search_page.html", user=get_user())

@app.route('/processSignup', methods = ["POST","GET"])
def processSignup():
"""
Queries the database to see if the user already exists. If so it lets the javascript know
If not, the new user is added to the database
"""
ret = {}
# Below is how we create a dictionary of the data sent from the input form
form_fields = dict((key, request.form.getlist(key)[0]) for key in list(request.form.keys()))
# query to see if user in the database already
user_query = f"SELECT * FROM users where email=?"
result = db.select_query(user_query, (form_fields["email"],))
result = result.fetchone() # get the first row
if result is None:
# if email is not in the database then we add it
add_user_query = f"INSERT INTO users (email, password) VALUES (?,?)"
db.mutation_query(add_user_query, (form_fields["email"], form_fields["password"]))
ret["success"] = 1 # send a success indicator back to the javascript side
# If user is in database, then send a failure indicator
else:
ret["success"] = 0

return ret

@app.route('/processLogin', methods = ["POST","GET"])
def processLogin():
"""
Checks to see if the username name and password are valid
If so, the user is logged in via adding their email to the session data
Otherwise the javascript is told there was a mistake.
"""
ret = {}
# Below is how we create a dictionary of the data sent from the input form
form_fields = dict((key, request.form.getlist(key)[0]) for key in list(request.form.keys()))
# query to see if user in the database
user_query = f"SELECT * FROM users where email=? and password=?"
result = db.select_query(user_query, (form_fields["email"], form_fields["password"]))
result = result.fetchone() # get the first row
if result is None:
# if email and password is not in the database then we add it then send failure indicator
ret["success"] = 0

# If email and password is in the database we log the user in
else:
session['email'] = form_fields["email"] # add the email to the users session
ret["success"] = 1
return ret

@app.route('/logout')
def logout():
"""
Logs the current user out by poping their email from current session
"""
session.pop('email', default=None)
return redirect('/')

@app.route("/predict", methods=["POST"])
def predict():
Expand Down Expand Up @@ -97,7 +184,7 @@ def success():
"""
Renders the success page.
"""
return render_template("success.html")
return render_template("success.html", user=get_user())


if __name__ == "__main__":
Expand Down
29 changes: 29 additions & 0 deletions src/recommenderapp/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Reused code from previous project
import sqlite3
from sqlite3 import Error
import os

CON = None
def connect():
''' connect program to database file db.sqlite '''
global CON
db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'db.sqlite')
print(db_path)
try:
CON = sqlite3.connect(db_path, check_same_thread=False)
print("Connection to SQLite DB successful")
except Error as err:
print(f"The error '{err}' occurred when trying to connect to SQLite database")


def select_query(sql, args=()):
''' select query to return items from database '''
cur = CON.cursor()
return cur.execute(sql, args)


def mutation_query(sql, args=()):
''' do a mutation on the database '''
cur = CON.cursor()
cur.execute(sql, args)
CON.commit()
16 changes: 16 additions & 0 deletions src/recommenderapp/static/login.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#login-form {
margin: auto; /*so the form is in the center of it's container */
}

#Signup_text {
margin: auto;
}

#login_alert {
margin: 0 auto;
padding-bottom: 5px;
padding-top: 5px;
margin-bottom: 10px;
margin-top: 10px;
display: none;
}
22 changes: 22 additions & 0 deletions src/recommenderapp/static/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//Function for login in
function Login(){
email = document.getElementById("inputemail").value
pass = document.getElementById("inputpassword").value
login_alert = document.getElementById("login_alert")
console.log(email) /* just for us to see outputs on the console for testing */
console.log(pass)
$.ajax({
url: "/processLogin",
type: 'POST',
data: {'email': email, 'password': pass, 'role': "user"},
success:function(returned_data){
if (returned_data['success'] === 1){
window.location.href = "/"
}
else{
login_alert.style.display = "flex";
}
}

})
}
3 changes: 2 additions & 1 deletion src/recommenderapp/static/script.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
$(document).ready(function () {

console.log('hello')
$(function () {
$("#searchBox").autocomplete({
source: function (request, response) {
Expand Down Expand Up @@ -127,6 +127,7 @@ $(document).ready(function () {

// Function to handle Get Started button click
function getStarted() {
console.log("Made it to this function!")
// Navigate to the search page
$("#loaderLanding").attr("class", "d-flex justify-content-center");
$("#centralDivLanding").hide();
Expand Down
12 changes: 12 additions & 0 deletions src/recommenderapp/static/signup.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#signup-form {
margin: auto; /*so the form is in the center of it's container */
}

#failed_sign_in {
margin: 0 auto;
padding-bottom: 5px;
padding-top: 5px;
margin-bottom: 10px;
margin-top: 10px;
display: none;
}
24 changes: 24 additions & 0 deletions src/recommenderapp/static/signup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//Function for sign out
function Signup(){
email = document.getElementById("inputemail").value
pass = document.getElementById("inputpassword").value
sign_alert = document.getElementById("failed_sign_in")
console.log(email) /* just for us to see outputs on the console for testing */
console.log(pass)
$.ajax({
url: "/processSignup",
type: 'POST',
data: {'email': email, 'password': pass, 'role': "user"}, // role will matter later
success:function(returned_data){
if (returned_data['success'] === 1){
// happens if the signup is valid
window.location.href = "/login"
}
else{
// happens if the signup is not valid
//window.location.href = "/signup"
sign_alert.style.display = "flex";
}
}
})
}
75 changes: 24 additions & 51 deletions src/recommenderapp/templates/landing_page.html
Original file line number Diff line number Diff line change
@@ -1,54 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='stylesheet.css') }}">
<title>PopcornPicks</title>
<link rel="icon" href="{{ url_for('static', filename='Popcorn-icon.png') }}" />
<script src="{{ url_for('static', filename='script.js') }}"></script>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
{% extends 'shared/layout.html' %}

<body class="landing-page">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark topNavBar fixed-top" id="landingTopNav">
<div class="container-fluid">
<a class="navbar-brand" href="#">PopcornPicks🍿</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>

<div class="container" style="margin-top: 60px;" id="centralDivLanding">
<div class="heading1"><br><br><br><br>
<h2><center>🎬 PopcornPicks🍿: Pick a Movie! 🎬</center></h2>
<p style="text-align: center; color: azure; font-size: 18px;"><br>
Discover personalized movie recommendations by selecting up to 5 of your favorite films.
<br>
Create a watchlist and have it conveniently sent to your email.
<br>
Enjoy movies at your own pace, on your terms.
</p><br>
<button id="getStartedButton" onclick="getStarted()" class="btn btn-primary mx-auto">Get Started!</button><br><br>
<div class="highlighted-section">
<p>Made with ❤️ by <a href="https://github.com/adipai/PopcornPicks" target="_blank"> PopcornPicks</a></p>
<a href="https://github.com/adipai/PopcornPicks/blob/master/LICENSE.md" target="_blank">MIT License Copyright (c) 2023 PopcornPicks</a>
</div>
</div>
</div>
<div class="d-none" id="loaderLanding">
<div class="spinner-border" role="status">
<span class="sr-only"></span>
</div>
{% block maincontent %}
<div class="container" style="margin-top: 60px;" id="centralDivLanding">
<div class="heading1"><br><br><br><br>
<h2><center>🎬 PopcornPicks🍿: Pick a Movie! 🎬</center></h2>
<p style="text-align: center; color: azure; font-size: 18px;"><br>
Discover personalized movie recommendations by selecting up to 5 of your favorite films.
<br>
Create a watchlist and have it conveniently sent to your email.
<br>
Enjoy movies at your own pace, on your terms.
</p><br>
<button id="getStartedButton" onclick="getStarted()" class="btn btn-primary mx-auto">Get Started!</button><br><br>
<div class="highlighted-section">
<p>Made with ❤️ by <a href="https://github.com/tanmaypardeshi/CSC-510-Project3-PopcornPicks" target="_blank"> PopcornPicks</a></p>
<a href="https://github.com/tanmaypardeshi/CSC-510-Project3-PopcornPicks/blob/master/LICENSE" target="_blank">MIT License Copyright (c) 2023 PopcornPicks</a>
</div>
</div>
</div>
<div class="d-none" id="loaderLanding">
<div class="spinner-border" role="status">
<span class="sr-only"></span>
</div>
</div>
{% endblock %}

</body>

<script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" crossorigin="anonymous"></script>
<script src="{{ url_for('static', filename='script.js') }}"></script>
</html>
40 changes: 40 additions & 0 deletions src/recommenderapp/templates/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{% extends 'shared/layout.html' %}

{% block extracss %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='login.css') }}">
{% endblock %}

{% block extrajs %}
<script defer src="{{ url_for('static', filename='login.js') }}"></script>
{% endblock %}

{% block maincontent %}
<div class="container" style="margin-top: 60px;" id="centralDivLanding">
<div class="heading1"><br><br><br><br>
<h2><center>🎬 PopcornPicks🍿: Login to Your Account! 🎬</center></h2>
<div class="alert alert-danger" role="alert" id="login_alert">
Error, wrong username or password. Please try again.
</div>
<form id="login-form">
<div class="form-group">
<label for="InputEmail">Email address</label>
<input type="email" class="form-control" id="inputemail" aria-describedby="emailHelp" placeholder="Enter email">
</div>
<br>
<div class="form-group">
<label for="InputPassword">Password</label>
<input type="password" class="form-control" id="inputpassword" placeholder="Password">
</div>
<br>
<button type="submit" class="btn btn-primary" onclick="Login()">Login</button>
</form>
<small id="Signup_text" class="form-text text-muted">Don't have an account with us? Click <a href="/signup">here</a> to sign up.</small>
</div>
</div>
</div>
<div class="d-none" id="loaderLanding">
<div class="spinner-border" role="status">
<span class="sr-only"></span>
</div>
</div>
{% endblock %}
Loading