# app.py
from flask import (
Flask,
request,
redirect,
render_template,
session,
url_for,
flash,
Response,
)
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from authlib.integrations.flask_client import OAuth
from dotenv import load_dotenv
from sqlalchemy import create_engine, text, insert, select, MetaData, Table
import os
import string
import random
import uuid
import csv
import json
import gspread
from io import StringIO
from google.oauth2.service_account import Credentials
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import pickle
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
# Load environment variables from .env file
load_dotenv()
app = Flask(__name__)
app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY") or "your_secret_key"
app.config["SQLALCHEMY_DATABASE_URI"] = (
os.environ.get("DATABASE_URI") or "postgresql://localhost/sunolinks"
)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# app.config['SERVER_NAME'] = os.environ.get('SERVER_NAME') or 'localhost:5000' # Set your server name here
db = SQLAlchemy(app)
migrate = Migrate(app, db)
oauth = OAuth(app)
oauth.register(
name="google",
client_id=os.environ.get("GOOGLE_CLIENT_ID"),
client_secret=os.environ.get("GOOGLE_CLIENT_SECRET"),
server_metadata_url="https://accounts.google.com/.well-known/openid-configuration",
client_kwargs={"scope": "openid email profile"},
)
# Template filters
@app.template_filter("eastern_time")
def eastern_time_filter(utc_dt):
"""Convert UTC datetime to Eastern Time"""
if utc_dt is None:
return None
# The datetime from prod database is in UTC
if utc_dt.tzinfo is None:
utc_dt = utc_dt.replace(tzinfo=ZoneInfo("UTC"))
# Convert to Eastern Time
eastern_dt = utc_dt.astimezone(ZoneInfo("America/New_York"))
return eastern_dt
# SMTP Configuration
SMTP_SERVER = os.getenv("SMTP_SERVER", "smtp.gmail.com")
SMTP_PORT = int(os.getenv("SMTP_PORT", "587"))
SMTP_USERNAME = os.getenv("SMTP_USERNAME")
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD")
FROM_EMAIL = os.getenv("FROM_EMAIL")
def send_hackmit_token_email(
email: str,
hacker_name: str,
token: str,
team_name: str = "N/A",
university: str = "N/A",
is_existing: bool = False,
):
"""Send HackMIT token email to participant"""
# Update message based on whether it's a new or existing token
if is_existing:
token_message = "Here's your existing token for the Suno HackMIT event:"
else:
token_message = "Here's your new token for the Suno HackMIT event:"
# Extract first name from hacker_name
first_name = hacker_name.split()[0] if hacker_name else "there"
# Create HTML body
body = f"""
Hey {first_name}! 👋
Thanks for opting in to the Suno HackMIT track! 🎶
{token_message}
Token: \"{token}\"
This is YOUR team's token to access the Suno API during the hackathon. Please don't share it with anyone not on your team. 🔒
For Suno's full API documentation, please visit suno.com/hackmit 🚀
Happy hacking! 🔥
- The Suno Team 🎶
"""
try:
# Create message
msg = MIMEMultipart("alternative")
msg["Subject"] = "Your Suno HackMIT Token!"
msg["From"] = f"Suno Hackathons <{FROM_EMAIL}>"
msg["To"] = email
# Create HTML part
html_part = MIMEText(body, "html")
msg.attach(html_part)
# Connect to server and send email
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
server.starttls() # Enable TLS encryption
if SMTP_USERNAME and SMTP_PASSWORD:
server.login(SMTP_USERNAME, SMTP_PASSWORD)
# Send email
text = msg.as_string()
server.sendmail(FROM_EMAIL, email, text)
server.quit()
print(f"✅ Email sent successfully to {email}")
return {"success": True, "message": "Email sent successfully"}
except Exception as e:
print(f"❌ Failed to send email to {email}: {str(e)}")
return {"success": False, "error": str(e)}
# Define file paths for pickled data
EMPS_FILE = "emps_data.pkl"
TEAMS_FILE = "teams_data.pkl"
CACHE_DURATION = timedelta(hours=24) # Cache data for 24 hours
def load_or_fetch_data(override_cache=False):
current_time = datetime.now()
# Check if cached data exists and is fresh
if os.path.exists(EMPS_FILE) and os.path.exists(TEAMS_FILE) and not override_cache:
emps_mtime = datetime.fromtimestamp(os.path.getmtime(EMPS_FILE))
teams_mtime = datetime.fromtimestamp(os.path.getmtime(TEAMS_FILE))
if current_time - emps_mtime < CACHE_DURATION and current_time - teams_mtime < CACHE_DURATION:
try:
with open(EMPS_FILE, "rb") as f:
emps = pickle.load(f)
with open(TEAMS_FILE, "rb") as f:
teams = pickle.load(f)
print("Loaded employee data from cache")
return emps, teams
except Exception as e:
print(f"Error loading cached data: {e}")
# If cache doesn't exist or is stale, fetch fresh data
try:
creds_dict = json.loads(os.getenv("GOOGLE_CREDENTIALS_JSON"))
# Set scopes
SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"]
# Load credentials from dict
credentials = Credentials.from_service_account_info(creds_dict, scopes=SCOPES)
# Create gspread client
gc = gspread.authorize(credentials)
sheet = gc.open_by_url(
"https://docs.google.com/spreadsheets/d/1jZqj4UyTTWqt3RsvjWG1Ifhi_pnNwUPhVnK8IcnN2_I/edit"
).worksheet("emps")
emps = sheet.get_all_records()
sheet = gc.open_by_url(
"https://docs.google.com/spreadsheets/d/1jZqj4UyTTWqt3RsvjWG1Ifhi_pnNwUPhVnK8IcnN2_I/edit"
).worksheet("teams")
teams = sheet.get_all_records()
for emp in emps:
emp["ldap"] = emp["Email"].split("@")[0]
emp["profile_url"] = f"employees/{emp['ldap']}"
# Save to cache
with open(EMPS_FILE, "wb") as f:
pickle.dump(emps, f)
with open(TEAMS_FILE, "wb") as f:
pickle.dump(teams, f)
print("Fetched and cached fresh employee data")
return emps, teams
except Exception as e:
print(f"Error fetching data: {e}")
# If fetch fails and cache exists, try to use stale cache
if os.path.exists(EMPS_FILE) and os.path.exists(TEAMS_FILE):
with open(EMPS_FILE, "rb") as f:
emps = pickle.load(f)
with open(TEAMS_FILE, "rb") as f:
teams = pickle.load(f)
print("Using stale cached data due to fetch error")
return emps, teams
raise
# Load the data
emps, teams = load_or_fetch_data()
# Initialize global variables
emps_lookup = None
managers_with_reports = None
emp_dict = None
ceo = None
def process_employee_data():
global emps_lookup, managers_with_reports, emp_dict, ceo
emps_lookup = {emp["Name"]: emp["Email"] for emp in emps}
managers_with_reports = {}
emp_dict = {emp["Email"]: emp for emp in emps}
ceo = None
for emp in emp_dict.values():
emp["Reports"] = []
for emp in emp_dict.values():
if emp["Name"] == "Mikey Shulman":
ceo = emp
continue
manager_name = emp.get("Corrected Manager")
if manager_name and manager_name in emps_lookup:
manager_email = emps_lookup[manager_name]
if manager_email:
emp_dict[manager_email]["Reports"].append(emp)
# Process the initial data
process_employee_data()
def count_all_reports(emp):
"""Recursively count all reports under an employee"""
direct_count = len(emp["Reports"])
total_count = direct_count
for report in emp["Reports"]:
total_count += count_all_reports(report)
return total_count
# Add cumulative report counts to each employee
for emp in emp_dict.values():
emp["CumulativeReports"] = count_all_reports(emp)
# Database models
class URL(db.Model):
id = db.Column(db.Integer, primary_key=True)
short_code = db.Column(db.String(10), unique=True, nullable=False)
original_url = db.Column(db.Text, nullable=False)
user_email = db.Column(db.String(255), nullable=False)
count = db.Column(db.Integer, default=0)
class Event(db.Model):
id = db.Column(db.Integer, primary_key=True)
event_type = db.Column(db.String(50), nullable=False)
datetime = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
user_email = db.Column(db.String(255), nullable=False)
url_id = db.Column(db.Integer, nullable=True)
note = db.Column(db.Text, nullable=True)
# Ensure the database is created within the application context
with app.app_context():
db.create_all()
# Helper function to generate a short code
def generate_short_code(length=6):
return "".join(random.choices(string.ascii_letters + string.digits, k=length))
# Google OAuth login
@app.route("/login")
def login():
redirect_uri = url_for("authorized", _external=True)
nonce = str(uuid.uuid4())
session["nonce"] = nonce
return oauth.google.authorize_redirect(redirect_uri, nonce=nonce)
@app.route("/logout")
def logout():
session.pop("user_email", None)
flash("You have been logged out.", "info")
return redirect(url_for("index"))
@app.route("/login/authorized")
def authorized():
token = oauth.google.authorize_access_token()
nonce = session.pop("nonce", None)
try:
user_info = oauth.google.parse_id_token(token, nonce=nonce)
session["user_email"] = user_info["email"]
flash("You have been logged in.", "success")
except Exception as e:
flash(f"Login failed: {str(e)}", "error")
return redirect(url_for("index"))
# Add a new URL
@app.route("/add_url", methods=["POST"])
def add_url():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
original_url = request.form.get("original_url")
short_code = request.form.get("short_code") or generate_short_code()
if URL.query.filter_by(short_code=short_code).first():
flash("Short code already exists. Please choose another.", "error")
return redirect(url_for("index"))
url_entry = URL(
short_code=short_code,
original_url=original_url,
user_email=session["user_email"],
)
db.session.add(url_entry)
db.session.commit()
flash("URL added successfully!", "success")
return redirect(url_for("index"))
# Delete a URL
@app.route("/delete_url/", methods=["POST"])
def delete_url(url_id):
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
url_entry = URL.query.get(url_id)
if url_entry and url_entry.user_email == session["user_email"]:
# Create a delete event
delete_event = Event(
event_type="delete",
user_email=session["user_email"],
url_id=url_entry.id,
note=f"{url_entry.short_code},{url_entry.original_url}",
)
db.session.add(delete_event)
db.session.delete(url_entry)
db.session.commit()
flash("URL deleted successfully!", "success")
else:
flash("Unauthorized action.", "error")
return redirect(url_for("index"))
# Display all URLs
@app.route("/")
def index():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("login"))
# Sort emps by surname (last word in Name field)
def get_surname(emp):
name = emp.get("Name", "").strip()
if name:
return name.split()[-1].lower()
return ""
sorted_emps = sorted(emps, key=get_surname)
# Get all unique teams for the filter dropdown
all_teams = set()
for emp in emps:
if emp.get("Teams"):
teams = emp["Teams"].split(",")
for team in teams:
all_teams.add(team.strip())
# Get all unique offices for the filter dropdown
all_offices = set()
for emp in emps:
if emp.get("Office"):
all_offices.add(emp["Office"].strip())
return render_template(
"club47/employees_list.html",
employees=sorted_emps,
all_teams=sorted(all_teams),
all_offices=sorted(all_offices),
)
# Display all URLs
@app.route("/golinks")
def golinks():
if "user_email" in session:
urls = URL.query.all()
else:
flash("You need to login first.", "error")
urls = []
return render_template("golinks.html", urls=urls)
# Redirect short URL to original URL
@app.route("/")
def redirect_url(short_code):
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
url_entry = URL.query.filter_by(short_code=short_code).first()
if url_entry:
url_entry.count += 1
click_event = Event(event_type="click", user_email=session["user_email"], url_id=url_entry.id)
db.session.add(click_event)
db.session.commit()
return redirect(url_entry.original_url)
return "URL not found", 404
@app.route("/download_csv")
def download_csv():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
# Create a StringIO object to write the CSV data
si = StringIO()
cw = csv.writer(si)
# Write the header
cw.writerow(["id", "short_code", "original_url", "user_email", "count"])
# Query all URLs and write them to the CSV
urls = URL.query.all()
for url in urls:
cw.writerow([url.id, url.short_code, url.original_url, url.user_email, url.count])
# Seek to the start of the StringIO object
si.seek(0)
# Create a response with the CSV data
response = Response(si.getvalue(), mimetype="text/csv")
response.headers["Content-Disposition"] = "attachment; filename=data.csv"
click_event = Event(event_type="download", user_email=session["user_email"], url_id=None)
db.session.add(click_event)
db.commit()
return response
def _copy_song(direction, clip_id, user_email):
print(f"Copying song {clip_id} from {direction} to {user_email}")
staging_engine = create_engine(os.getenv("STAGING_DATABASE"))
prod_engine = create_engine(os.getenv("PROD_DATABASE"))
if direction == "staging_to_prod":
print("Copying from staging to prod")
source_engine = staging_engine
target_engine = prod_engine
elif direction == "prod_to_staging":
print("Copying from prod to staging")
source_engine = prod_engine
target_engine = staging_engine
else:
print("Invalid direction")
return False
try:
metadata = MetaData()
clip_table = Table("bots_generatedclip", metadata, autoload_with=source_engine)
# Get row from source
with source_engine.connect() as conn:
result = conn.execute(select(clip_table).where(clip_table.c.id == clip_id))
row = result.fetchone()
if not row:
print(f"No clip found with ID {clip_id}")
return False
# Convert row to dictionary using column names
clip_data = {column.name: getattr(row, column.name) for column in clip_table.columns}
clip_data["request_id"] = None
clip_data["model_name"] = "copy-tool"
# Insert into target
with target_engine.connect() as conn:
# Get user ID for brad@suno.com
user_result = conn.execute(text(f"select id from auth_user where email='{user_email}'"))
user_id = user_result.fetchone()[0]
print(f"User ID: {user_id}")
# Update clip_data with user_id
clip_data["user_id"] = user_id
# Insert the clip with updated user_id
conn.execute(insert(clip_table), clip_data)
conn.commit()
print(f"Successfully copied clip {clip_id}")
except Exception as e:
print(f"Error: {e}")
return False
return True
@app.route("/tools/copy-song", methods=["GET", "POST"])
def copy_song():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
if request.method == "POST":
direction = request.form.get("direction")
clip_id = request.form.get("clip_id")
user_email = request.form.get("user_email")
print("Form submitted with values:")
print(f"Direction: {direction}")
print(f"Clip ID: {clip_id}")
print(f"User Email: {user_email}")
status = _copy_song(direction, clip_id, user_email)
if status:
return redirect(url_for("success", clip_id=clip_id))
else:
flash("Failed to copy song", "error")
return redirect(url_for("copy_song"))
return render_template("copy_song.html")
@app.route("/tools/copy-song/success")
def success():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
clip_id = request.args.get("clip_id")
return render_template("success.html", clip_id=clip_id)
@app.route("/employees/")
def employee_detail(ldap):
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
employee = next((emp for emp in emps if emp["Email"] == ldap + "@suno.com"), None)
print(employee)
if not employee:
return "Employee not found", 404
# Find manager info
manager_info = None
if employee.get("Corrected Manager") and employee["Corrected Manager"] in emps_lookup:
manager_email = emps_lookup[employee["Corrected Manager"]]
manager_info = emp_dict.get(manager_email)
manager_name = employee.get("Corrected Manager")
manager_email = emps_lookup.get(manager_name)
return render_template(
"club47/employee_profile.html",
emp=employee,
reports=emp_dict[employee["Email"]]["Reports"],
manager_name=manager_name,
manager_email=manager_email,
)
@app.route("/employees/list")
def employees_list():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
# Get all unique teams for the filter dropdown
all_teams = set()
for emp in emps:
if emp.get("Teams"):
teams = emp["Teams"].split(",")
for team in teams:
all_teams.add(team.strip())
# Get all unique offices for the filter dropdown
all_offices = set()
for emp in emps:
if emp.get("Office"):
all_offices.add(emp["Office"].strip())
return render_template(
"club47/employees_list.html",
employees=emps,
all_teams=sorted(all_teams),
all_offices=sorted(all_offices),
)
@app.route("/home")
def home():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
employee = next((emp for emp in emps if emp["Email"] == session["user_email"]), None)
employee["Handle"] = "buno"
return render_template(
"club47/base.html", emp=employee, reports=emp_dict[employee["Email"]]["Reports"]
)
@app.route("/org")
def fullorg():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
return render_template("club47/org.html", org=emp_dict, ceo=emp_dict["mikey@suno.com"])
@app.route("/reload")
def reload():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
print("Refreshing employee data...")
# Fetch fresh data from Google Sheets
global emps, teams
emps, teams = load_or_fetch_data(override_cache=True)
# Reprocess all the derived data structures
process_employee_data()
# Recalculate cumulative report counts
for emp in emp_dict.values():
emp["CumulativeReports"] = count_all_reports(emp)
print("Employee data refreshed successfully")
flash("Employee data has been refreshed from Google Sheets", "success")
return redirect(url_for("fullorg"))
@app.route("/hack")
def hack():
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("index"))
prod_engine = create_engine(os.getenv("PROD_DATABASE"))
with prod_engine.connect() as conn:
result = conn.execute(
text(
f"select token from clips_usertoken ut where ut.user_id=(select id from auth_user where email='{session['user_email']}')"
)
)
tokens = result.fetchall()
print(f"Tokens: {tokens}")
# If no tokens found, generate a new one
if not tokens:
# Generate UUID v4 and remove dashes
new_token = str(uuid.uuid4()).replace("-", "")
# Get user ID
user_result = conn.execute(
text(f"select id from auth_user where email='{session['user_email']}'")
)
user_id = user_result.fetchone()[0]
# Insert the new token
conn.execute(
text(
f"INSERT INTO clips_usertoken (user_id, token, is_active) VALUES ({user_id}, '{new_token}', true)"
)
)
conn.commit()
# Return the newly created token
tokens.append((new_token,))
print(f"Generated new token: {new_token}")
return render_template("hack.html", email=session["user_email"], tokens=tokens)
# HackMIT Token Management Routes
@app.route("/hackmit")
def hackmit_dashboard():
"""HackMIT token booth dashboard"""
# Check staff authorization
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("login"))
try:
engine = create_engine(os.getenv("PROD_DATABASE"))
with engine.connect() as conn:
# Get stats
total_tokens_result = conn.execute(text("SELECT COUNT(*) FROM hackmit_tokens"))
total_tokens = total_tokens_result.scalar()
active_tokens_result = conn.execute(
text("""
SELECT COUNT(*) FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
WHERE ut.is_active = true
""")
)
active_tokens = active_tokens_result.scalar()
# Get recent tokens (last 10)
recent_tokens_result = conn.execute(
text("""
SELECT ht.id, ht.hacker_name, ht.email_address, ht.team_name,
ht.university, ht.created_at, ht.updated_at, ut.is_active,
ut.token, au.email as user_email
FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
JOIN auth_user au ON ut.user_id = au.id
ORDER BY ht.created_at DESC
LIMIT 10
""")
)
recent_tokens = recent_tokens_result.fetchall()
# Get recent activity (last 24 hours) - use created_at since tracking is commented out
recent_activity_result = conn.execute(
text("""
SELECT COUNT(*) FROM hackmit_tokens
WHERE created_at >= NOW() - INTERVAL '24 hours'
""")
)
recent_activity = recent_activity_result.scalar()
stats = {
"total_tokens": total_tokens,
"active_tokens": active_tokens,
"revoked_tokens": total_tokens - active_tokens,
"recent_activity": recent_activity,
}
# Get staff name
if "user_email" in session:
staff_name = session["user_email"].split("@")[0]
else:
staff_name = "api-staff"
return render_template(
"hackmit/dashboard.html",
stats=stats,
recent_tokens=recent_tokens,
staff_name=staff_name,
)
except Exception as e:
flash(f"Database error: {str(e)}", "error")
# Get staff name even if database fails
staff_name = (
session.get("user_email", "api-staff").split("@")[0]
if session.get("user_email")
else "api-staff"
)
return render_template(
"hackmit/dashboard.html", stats={}, recent_tokens=[], staff_name=staff_name
)
@app.route("/hackmit/issue", methods=["GET", "POST"])
def hackmit_issue_token():
"""Issue a new HackMIT token"""
# Check staff authorization
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("login"))
if request.method == "POST":
hacker_name = request.form.get("hacker_name", "").strip()
email_address = request.form.get("email_address", "").strip()
team_name = request.form.get("team_name", "").strip()
university = request.form.get("university", "").strip()
notes = request.form.get("notes", "").strip()
# Validate required fields
if not hacker_name:
flash("Hacker name is required.", "error")
return render_template("hackmit/issue_token.html")
if not email_address:
flash("Email address is required.", "error")
return render_template("hackmit/issue_token.html")
if not team_name:
flash("Team name is required.", "error")
return render_template("hackmit/issue_token.html")
try:
engine = create_engine(os.getenv("PROD_DATABASE"))
with engine.connect() as conn:
# Check if user exists in Suno system
user_check = conn.execute(
text("""
SELECT id FROM auth_user WHERE email = :email
"""),
{"email": email_address},
)
user_row = user_check.fetchone()
if not user_row:
flash(
f"❌ {email_address} does not have a Suno account. "
f"Please sign up at https://accounts.suno.com/sign-up first, "
f"then return to get an API token for HackMIT!",
"error",
)
return render_template("hackmit/issue_token.html")
user_id = user_row[0]
# Check for existing active token
existing_token_check = conn.execute(
text("""
SELECT ht.id, ut.token FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
WHERE ut.user_id = :user_id AND ut.is_active = true
"""),
{"user_id": user_id},
)
existing_token = existing_token_check.fetchone()
if existing_token:
# Send email with existing token
email_result = send_hackmit_token_email(
email=email_address,
hacker_name=hacker_name,
token=existing_token[1],
team_name=team_name,
university=university,
is_existing=True,
)
if email_result["success"]:
flash(
f"🎵 {email_address} already has an active HackMIT token: {existing_token[1][:8]}... "
f"Your songs are already linked to your Suno account! 📧 Reminder email sent to {email_address}",
"warning",
)
else:
flash(
f"🎵 {email_address} already has an active HackMIT token: {existing_token[1][:8]}... "
f"Your songs are already linked to your Suno account! ⚠️ Email failed to send: {email_result.get('error', 'Unknown error')}",
"warning",
)
return redirect(url_for("hackmit_token_details", token_id=existing_token[0]))
# Create UserToken first
new_token = str(uuid.uuid4()).replace("-", "")
user_token_result = conn.execute(
text("""
INSERT INTO clips_usertoken (user_id, token, is_active)
VALUES (:user_id, :token, true)
RETURNING id
"""),
{"user_id": user_id, "token": new_token},
)
user_token_id = user_token_result.scalar()
# Create HackMIT token
hackmit_token_uuid = str(uuid.uuid4())
hackmit_result = conn.execute(
text("""
INSERT INTO hackmit_tokens
(id, user_token_id, hacker_name, email_address, team_name, university, notes,
generations_used, created_at, updated_at)
VALUES (:id, :user_token_id, :hacker_name, :email_address, :team_name, :university, :notes,
0, NOW(), NOW())
RETURNING id
"""),
{
"id": hackmit_token_uuid,
"user_token_id": user_token_id,
"hacker_name": hacker_name,
"email_address": email_address,
"team_name": team_name,
"university": university or None,
"notes": notes or None,
},
)
hackmit_token_id = hackmit_result.scalar()
conn.commit()
# Send email notification to the participant
email_result = send_hackmit_token_email(
email=email_address,
hacker_name=hacker_name,
token=new_token,
team_name=team_name,
university=university,
is_existing=False,
)
if email_result["success"]:
flash(
f"🎉 Token issued successfully! Token: {new_token[:8]}... "
f"✨ {email_address} is a Suno user, so all API-generated songs will appear in your regular Suno dashboard! "
f"📧 Email sent to {email_address}",
"success",
)
else:
flash(
f"🎉 Token issued successfully! Token: {new_token[:8]}... "
f"✨ {email_address} is a Suno user, so all API-generated songs will appear in your regular Suno dashboard! "
f"⚠️ Email failed to send: {email_result.get('error', 'Unknown error')}",
"warning",
)
return redirect(url_for("hackmit_token_details", token_id=hackmit_token_id))
except Exception as e:
flash(f"Error creating token: {str(e)}", "error")
return render_template("hackmit/issue_token.html")
@app.route("/hackmit/tokens")
def hackmit_list_tokens():
"""List all HackMIT tokens with search and filtering"""
# Check staff authorization
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("login"))
try:
engine = create_engine(os.getenv("PROD_DATABASE"))
with engine.connect() as conn:
# Base query
query = """
SELECT ht.id, ht.hacker_name, ht.email_address, ht.team_name,
ht.university, ht.created_at, ht.updated_at, ht.generations_used,
ut.is_active, ut.token, au.email as user_email
FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
JOIN auth_user au ON ut.user_id = au.id
"""
# Apply filters
conditions = []
params = {}
status_filter = request.args.get("status")
if status_filter == "active":
conditions.append("ut.is_active = true")
elif status_filter == "revoked":
conditions.append("ut.is_active = false")
search = request.args.get("search")
if search:
conditions.append("""
(ht.email_address ILIKE :search OR
ht.hacker_name ILIKE :search OR
ht.team_name ILIKE :search)
""")
params["search"] = f"%{search}%"
if conditions:
query += " WHERE " + " AND ".join(conditions)
query += " ORDER BY ht.created_at DESC LIMIT 50"
tokens_result = conn.execute(text(query), params)
tokens = tokens_result.fetchall()
# Get summary stats
stats_result = conn.execute(
text("""
SELECT
COUNT(*) as total_tokens,
COUNT(CASE WHEN ut.is_active = true THEN 1 END) as active_tokens
FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
""")
)
stats_row = stats_result.fetchone()
stats = {
"total_tokens": stats_row[0],
"active_tokens": stats_row[1],
"revoked_tokens": stats_row[0] - stats_row[1],
}
return render_template(
"hackmit/token_list.html",
tokens=tokens,
stats=stats,
status_filter=status_filter,
search=search or "",
)
except Exception as e:
flash(f"Database error: {str(e)}", "error")
return render_template(
"hackmit/token_list.html", tokens=[], stats={}, status_filter="", search=""
)
@app.route("/hackmit/tokens/")
def hackmit_token_details(token_id):
"""Show details for a specific token"""
# Check staff authorization
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("login"))
try:
engine = create_engine(os.getenv("PROD_DATABASE"))
with engine.connect() as conn:
token_result = conn.execute(
text("""
SELECT ht.id, ht.hacker_name, ht.email_address, ht.team_name,
ht.university, ht.notes, ht.created_at, ht.updated_at, ht.generations_used,
ut.is_active, ut.token, au.email as user_email, au.id as user_id
FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
JOIN auth_user au ON ut.user_id = au.id
WHERE ht.id = :token_id
"""),
{"token_id": token_id},
)
token = token_result.fetchone()
if not token:
flash("Token not found.", "error")
return redirect(url_for("hackmit_dashboard"))
return render_template("hackmit/token_details.html", token=token)
except Exception as e:
flash(f"Database error: {str(e)}", "error")
return redirect(url_for("hackmit_dashboard"))
@app.route("/hackmit/tokens/revoke-all", methods=["POST"])
def hackmit_revoke_all_tokens():
"""Revoke all active tokens"""
# Check staff authorization
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("login"))
try:
engine = create_engine(os.getenv("PROD_DATABASE"))
with engine.connect() as conn:
# Get count of active tokens first
active_count_result = conn.execute(
text("""
SELECT COUNT(*) FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
WHERE ut.is_active = true
""")
)
active_count = active_count_result.scalar()
if active_count == 0:
flash("No active tokens to revoke.", "info")
return redirect(url_for("hackmit_dashboard"))
# Get the user_token_ids that are currently active (before revoking)
active_token_ids_result = conn.execute(
text("""
SELECT ht.user_token_id FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
WHERE ut.is_active = true
""")
)
active_token_ids = [row[0] for row in active_token_ids_result.fetchall()]
if not active_token_ids:
flash("No active tokens to revoke.", "info")
return redirect(url_for("hackmit_dashboard"))
# Revoke those specific active tokens
conn.execute(
text("""
UPDATE clips_usertoken
SET is_active = false
WHERE id = ANY(:token_ids)
"""),
{"token_ids": active_token_ids},
)
# Update the HackMIT tokens we just revoked
conn.execute(
text("""
UPDATE hackmit_tokens
SET updated_at = NOW()
WHERE user_token_id = ANY(:token_ids)
"""),
{"token_ids": active_token_ids},
)
conn.commit()
flash(
f"🚨 Revoke all successful! {active_count} active tokens revoked.",
"success",
)
except Exception as e:
flash(f"Error revoking all tokens: {str(e)}", "error")
return redirect(url_for("hackmit_dashboard"))
@app.route("/hackmit/tokens//revoke", methods=["POST"])
def hackmit_revoke_token(token_id):
"""Revoke a token"""
# Check staff authorization
if "user_email" not in session:
flash("You need to login first.", "error")
return redirect(url_for("login"))
try:
engine = create_engine(os.getenv("PROD_DATABASE"))
with engine.connect() as conn:
# Get token info first
token_check = conn.execute(
text("""
SELECT ht.id, ut.token, ut.is_active FROM hackmit_tokens ht
JOIN clips_usertoken ut ON ht.user_token_id = ut.id
WHERE ht.id = :token_id
"""),
{"token_id": token_id},
)
token = token_check.fetchone()
if not token:
flash("Token not found.", "error")
return redirect(url_for("hackmit_dashboard"))
if not token[2]: # is_active
flash("Token is already revoked.", "warning")
else:
# Revoke the token
conn.execute(
text("""
UPDATE clips_usertoken
SET is_active = false
WHERE id = (SELECT user_token_id FROM hackmit_tokens WHERE id = :token_id)
"""),
{"token_id": token_id},
)
# Update HackMIT token updated_at timestamp
conn.execute(
text("""
UPDATE hackmit_tokens
SET updated_at = NOW()
WHERE id = :token_id
"""),
{"token_id": token_id},
)
conn.commit()
flash(f"Token {token[1][:8]}... revoked successfully.", "success")
next_url = request.form.get("next") or url_for("hackmit_dashboard")
return redirect(next_url)
except Exception as e:
flash(f"Error revoking token: {str(e)}", "error")
return redirect(url_for("hackmit_dashboard"))
@app.route("/hello")
def hello():
return "Hello, World!"
if __name__ == "__main__":
app.run(debug=False)