Skip to content
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
36 changes: 36 additions & 0 deletions alembic/versions/74e63e0c8e89_add_name_and_year_to_users_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""add name and year to users table

Revision ID: 74e63e0c8e89
Revises: 2df915a8c6ec
Create Date: 2025-10-27 20:46:29.628712

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '74e63e0c8e89'
down_revision: Union[str, None] = '2df915a8c6ec'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('display_name', sa.String(length=255), nullable=True))
op.add_column('users', sa.Column('year', sa.String(length=255), nullable=True))
op.add_column('usersdaily', sa.Column('display_name', sa.String(length=255), nullable=True))
op.add_column('usersdaily', sa.Column('year', sa.String(length=255), nullable=True))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('usersdaily', 'year')
op.drop_column('usersdaily', 'display_name')
op.drop_column('users', 'year')
op.drop_column('users', 'display_name')
# ### end Alembic commands ###
86 changes: 63 additions & 23 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,16 @@ def index():
# Home page after user logs in through Princeton's CAS
@app.route("/menu", methods=["GET"])
def menu():
username = auth.authenticate()
user_insert = user_database.insert_player(username)
daily_insert = daily_user_database.insert_player_daily(username)

# YUBI: update authenticate to return dictionary of user information
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]

# YUBI: update database functions!!!
user_insert = user_database.insert_player(username, display_name, year)
daily_insert = daily_user_database.insert_player_daily(username, display_name, year)
played_date = daily_user_database.get_last_played_date(username)
current_date = pictures_database.get_current_date()

Expand Down Expand Up @@ -111,7 +118,11 @@ def menu():
@app.route("/requests", methods=["GET"])
def requests():
username = flask.request.args.get("username")
username_auth = auth.authenticate()
user_info = auth.authenticate()
username_auth = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]

last_date = daily_user_database.get_last_versus_date(username_auth)
current_date = pictures_database.get_current_date()

Expand Down Expand Up @@ -157,7 +168,10 @@ def game():

id = pictures_database.pic_of_day()

username = auth.authenticate()
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]

user_played = daily_user_database.player_played(username)
today_points = daily_user_database.get_daily_points(username)
Expand Down Expand Up @@ -198,7 +212,10 @@ def game():
@app.route("/submit", methods=["POST"])
def submit():
id = pictures_database.pic_of_day()
username = auth.authenticate()
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]

user_played = daily_user_database.player_played(username)
today_points = daily_user_database.get_daily_points(username)
Expand Down Expand Up @@ -262,7 +279,10 @@ def submit():
@app.route("/rules", methods=["GET"])
def rules():
# user must be logged in to access page
auth.authenticate()
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]
html_code = flask.render_template("rules.html")
response = flask.make_response(html_code)
return response
Expand All @@ -274,7 +294,10 @@ def rules():
# Congratulations page easter egg
@app.route("/congrats", methods=["GET"])
def congrats():
username = auth.authenticate()
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]
top_player = user_database.get_top_player()

check = database_check([top_player])
Expand Down Expand Up @@ -309,7 +332,10 @@ def congrats():
@app.route("/team", methods=["GET"])
def team():
# user must be logged in to access page
username = auth.authenticate()
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]
top_player = user_database.get_top_player()

check = database_check([top_player])
Expand All @@ -333,7 +359,11 @@ def team():
@app.route("/totalboard", methods=["GET"])
def leaderboard():
top_players = user_database.get_top_players()
username = auth.authenticate()
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]

points = user_database.get_points(username)
daily_points = daily_user_database.get_daily_points(username)
rank = user_database.get_rank(username)
Expand Down Expand Up @@ -368,7 +398,11 @@ def leaderboard():
@app.route("/leaderboard", methods=["GET"])
def totalleaderboard():
top_players = daily_user_database.get_daily_top_players()
username = auth.authenticate()
user_info = auth.authenticate()
username = user_info["username"]
display_name = user_info["displayName"]
year = user_info["year"]

points = user_database.get_points(username)
daily_points = daily_user_database.get_daily_points(username)
rank = user_database.get_rank(username)
Expand Down Expand Up @@ -434,16 +468,18 @@ def create_challenge_route():
if (
challengee_id == None
or challengee_id not in users
or challengee_id == auth.authenticate()
or challengee_id == (auth.authenticate()["username"])
):
response = {
"status": "error",
"message": "Invalid Opponent NetID -- Must enter a valid NetID and Opponent must have logged into Tiger Spot before",
}
return flask.jsonify(response), 400 # Including a 400 Bad Request status code
else:
user_info = auth.authenticate()
username = user_info["username"]
result = challenges_database.create_challenge(
auth.authenticate(), challengee_id
username, challengee_id
)

check = database_check([result])
Expand Down Expand Up @@ -521,7 +557,9 @@ def decline_challenge_route():
@app.route("/play_button", methods=["POST"])
def play_button():
challenge_id = flask.request.form.get("challenge_id")
user = auth.authenticate()
user_info = auth.authenticate()
user = user_info["username"]

status = challenges_database.get_playbutton_status(challenge_id, user)
check = database_check([status])
if check is False:
Expand Down Expand Up @@ -625,7 +663,9 @@ def start_challenge(challenge_id=None, index=None):
@app.route("/end_challenge", methods=["POST"])
def end_challenge():
challenge_id = flask.request.form.get("challenge_id")
user = auth.authenticate()
user_info = auth.authenticate()
user = user_info["username"]

finish = challenges_database.update_finish_status(challenge_id, user)
check = database_check([finish])
if check is False:
Expand Down Expand Up @@ -675,7 +715,7 @@ def submit2():
return flask.make_response(html_code)
if not currLat or not currLon:
pic_status = versus_database.get_versus_pic_status(
challenge_id, auth.authenticate(), index + 1
challenge_id, (auth.authenticate()["username"]), index + 1
)
check = database_check([pic_status])
if check is False:
Expand All @@ -685,17 +725,17 @@ def submit2():
return flask.redirect(flask.url_for("requests"))
if pic_status is False:
fin1 = versus_database.update_versus_pic_status(
challenge_id, auth.authenticate(), index + 1
challenge_id, (auth.authenticate()["username"]), index + 1
)
if fin1 is None:
return flask.redirect(flask.url_for("requests"))
fin2 = versus_database.store_versus_pic_points(
challenge_id, auth.authenticate(), index + 1, points
challenge_id, (auth.authenticate()["username"]), index + 1, points
)
if fin2 is None:
return flask.redirect(flask.url_for("requests"))
fin3 = versus_database.update_versus_points(
challenge_id, auth.authenticate(), points
challenge_id, (auth.authenticate()["username"]), points
)
if fin3 is None:
return flask.redirect(flask.url_for("requests"))
Expand Down Expand Up @@ -725,7 +765,7 @@ def submit2():
return flask.redirect(flask.url_for("requests"))
distance = round(distance_func.calc_distance(currLat, currLon, coor))
pic_status = versus_database.get_versus_pic_status(
challenge_id, auth.authenticate(), index + 1
challenge_id, (auth.authenticate()["username"]), index + 1
)
check = database_check([pic_status])
if check is False:
Expand All @@ -736,17 +776,17 @@ def submit2():
if pic_status is False:
points = round(versus_database.calculate_versus(distance, time))
fin1 = versus_database.store_versus_pic_points(
challenge_id, auth.authenticate(), index + 1, points
challenge_id, (auth.authenticate()["username"]), index + 1, points
)
if fin1 is None:
return flask.redirect(flask.url_for("requests"))
fin2 = versus_database.update_versus_points(
challenge_id, auth.authenticate(), points
challenge_id, (auth.authenticate()["username"]), points
)
if fin2 is None:
return flask.redirect(flask.url_for("requests"))
fin3 = versus_database.update_versus_pic_status(
challenge_id, auth.authenticate(), index + 1
challenge_id, (auth.authenticate()["username"]), index + 1
)
if fin3 is None:
return flask.redirect(flask.url_for("requests"))
Expand Down
73 changes: 47 additions & 26 deletions src/CAS/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import urllib.parse
import re
import flask
import json

# -----------------------------------------------------------------------

Expand All @@ -32,24 +33,49 @@ def strip_ticket(url):


def validate(ticket):

# YUBI: updated using v3
val_url = (
_CAS_URL
+ "validate"
+ "p3/serviceValidate"
+ "?service="
+ urllib.parse.quote(strip_ticket(flask.request.url))
+ "&ticket="
+ urllib.parse.quote(ticket)
+ "&format=json"
)
lines = []
with urllib.request.urlopen(val_url) as flo:
lines = flo.readlines() # Should return 2 lines.
if len(lines) != 2:
return None
first_line = lines[0].decode("utf-8")
second_line = lines[1].decode("utf-8")
if not first_line.startswith("yes"):

with urllib.request.urlopen(val_url) as response:
data = json.load(response)

# Check if authentication was successful
service_response = data.get("serviceResponse", {})
auth_success = service_response.get("authenticationSuccess")
if not auth_success:
return None
return second_line

username = auth_success.get("user", "").strip()
attributes = auth_success.get("attributes", {})

# Extract displayName
display_name = ""
if "displayName" in attributes:
# Could be a list
if isinstance(attributes["displayName"], list):
display_name = attributes["displayName"][0]
else:
display_name = attributes["displayName"]

# Extract class year from grouperGroups
year = "Graduate"
grouper_groups = attributes.get("grouperGroups", [])
if isinstance(grouper_groups, list):
for g in grouper_groups:
if "PU:basis:classyear:" in g:
year = g.split(":")[-1]
break

return {"username": username, "displayName": display_name or username, "year": year}


# -----------------------------------------------------------------------
Expand All @@ -59,35 +85,29 @@ def validate(ticket):


def authenticate():
# If already authenticated, return cached info
if "user_info" in flask.session:
return flask.session.get("user_info")

# If the username is in the session, then the user was
# authenticated previously. So return the username.
if "username" in flask.session:
return flask.session.get("username")

# If the request does not contain a login ticket, then redirect
# the browser to the login page to get one.
# If no ticket, redirect to CAS login
ticket = flask.request.args.get("ticket")
if ticket is None:
login_url = _CAS_URL + "login?service=" + urllib.parse.quote(flask.request.url)
flask.abort(flask.redirect(login_url))

# If the login ticket is invalid, then redirect the browser
# to the login page to get a new one.
username = validate(ticket)
if username is None:
# Validate ticket
user_info = validate(ticket)
if user_info is None:
login_url = (
_CAS_URL
+ "login?service="
+ urllib.parse.quote(strip_ticket(flask.request.url))
)
flask.abort(flask.redirect(login_url))

# The user is authenticated, so store the username in
# the session.
username = username.strip()
flask.session["username"] = username
return username
# Store in session
flask.session["user_info"] = user_info
return user_info


# -----------------------------------------------------------------------
Expand All @@ -107,6 +127,7 @@ def logoutapp():

def logoutcas():

# YUBI: ASK, does this correctly logout of cas?
# Log out of the CAS session, and then the application.
logout_url = (
_CAS_URL
Expand Down
Loading