-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8452953
commit 3598bd9
Showing
7 changed files
with
188 additions
and
4 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import secrets | ||
from spotipy.oauth2 import SpotifyOAuth | ||
from dotenv import load_dotenv | ||
import os | ||
from fastapi import FastAPI, Form, Request, Depends | ||
from fastapi.responses import RedirectResponse | ||
from fastapi.middleware.cors import CORSMiddleware | ||
from starlette.middleware.sessions import SessionMiddleware | ||
from session_cache_handler import SessionCacheHandler | ||
from fastapi.templating import Jinja2Templates | ||
from typing import Annotated | ||
|
||
# Jinja2 template engine | ||
templates = Jinja2Templates(directory="templates") | ||
|
||
|
||
load_dotenv("../.env") | ||
CLIENT_SECRET = os.environ.get("CLIENT_SECRET") | ||
CLIENT_ID = os.environ.get("CLIENT_ID") | ||
REDIRECT_URI = os.environ.get("REDIRECT_URI") | ||
|
||
app = FastAPI() # FastAPI instance | ||
# Middlewares | ||
app.add_middleware(SessionMiddleware, secret_key=secrets.token_urlsafe(32)) | ||
# For more info on CORS: https://fastapi.tiangolo.com/tutorial/cors/?h=cors | ||
origins = [ | ||
"http://localhost:3000", | ||
"http://localhost:8000", | ||
] | ||
app.add_middleware( | ||
CORSMiddleware, | ||
allow_origins=origins, | ||
allow_credentials=True, | ||
allow_methods=["*"], | ||
allow_headers=["*"], | ||
) | ||
|
||
|
||
# Dependencies | ||
def get_spotify_oauth(request: Request): | ||
return SpotifyOAuth( | ||
scope="user-library-modify", | ||
client_id=CLIENT_ID, | ||
client_secret=CLIENT_SECRET, | ||
redirect_uri=REDIRECT_URI, | ||
cache_handler=SessionCacheHandler(request.session), | ||
) | ||
|
||
|
||
@app.get("/") | ||
def index( | ||
auth_manager: Annotated[SpotifyOAuth, Depends(get_spotify_oauth)], request: Request | ||
): | ||
# Check if we have a cached token | ||
is_authenticated = bool(auth_manager.get_cached_token()) | ||
# Render index.html template | ||
return templates.TemplateResponse( | ||
"index.html", {"request": request, "is_authenticated": is_authenticated} | ||
) | ||
|
||
|
||
@app.get("/login") | ||
def login(auth_manager: Annotated[SpotifyOAuth, Depends(get_spotify_oauth)]): | ||
return RedirectResponse(auth_manager.get_authorize_url()) | ||
|
||
|
||
@app.get("/callback") | ||
async def callback( | ||
auth_manager: Annotated[SpotifyOAuth, Depends(get_spotify_oauth)], request: Request | ||
): | ||
# Authorization code that spotify sends back https://developer.spotify.com/documentation/web-api/tutorials/code-flow | ||
code = request.query_params.get("code") | ||
if not code: | ||
return {"Error": "No code provided"} | ||
|
||
# Exchange code for an access token | ||
token_info = auth_manager.get_access_token(code) | ||
|
||
if not token_info: | ||
return {"Error": "Could not retrieve token"} | ||
|
||
# Finally redirect to the index page | ||
return RedirectResponse("/") | ||
|
||
|
||
@app.post("/playlist") | ||
def playlist(sentence: str = Form(...)): | ||
return {"status": "ok"} | ||
|
||
|
||
# Healthcheck endpoint to make sure the server is running | ||
@app.get("/healthcheck") | ||
def healthcheck(): | ||
return {"status": "ok"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet"> | ||
</head> | ||
<body class="bg-gray-100 h-screen"> | ||
<div class="container mx-auto p-8"> | ||
<div class="max-w-md mx-auto bg-white rounded-lg overflow-hidden md:max-w-lg"> | ||
<div class="md:flex"> | ||
<div class="w-full p-4"> | ||
<div class="relative"> | ||
<h1 class="text-2xl font-bold text-gray-700 mb-2">Welcome to the Home Page</h1> | ||
{% if is_authenticated %} | ||
<form action="/playlist" method="post" class="pt-2"> | ||
{% else %} | ||
<form action="/login" method="get" class="pt-2"> | ||
{% endif %} | ||
<div class="mb-4"> | ||
<label class="block text-gray-700 text-sm font-bold mb-2" for="text_field"> | ||
Enter a sentence | ||
</label> | ||
<input type="text" name="sentence" id="text_field" | ||
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" | ||
placeholder="Enter text"> | ||
</div> | ||
<div class="flex justify-end"> | ||
<button type="submit" | ||
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"> | ||
{% if is_authenticated %} | ||
Submit | ||
{% else %} | ||
Log in with Spotify | ||
{% endif %} | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from fastapi.testclient import TestClient | ||
from spotipy.oauth2 import SpotifyOAuth | ||
from unittest.mock import Mock | ||
from main import get_spotify_oauth | ||
|
||
from main import app | ||
|
||
client = TestClient(app, follow_redirects=False) | ||
|
||
|
||
def test_login(): | ||
mock_auth_manager = Mock(spec=SpotifyOAuth) | ||
expected_url = ( | ||
mock_auth_manager.get_authorize_url.return_value | ||
) = "http://example.com" | ||
app.dependency_overrides[get_spotify_oauth] = lambda: mock_auth_manager | ||
|
||
response = client.get("/login") | ||
assert response.status_code == 307 | ||
assert response.headers["location"] == expected_url | ||
|
||
|
||
def test_healthcheck(): | ||
response = client.get("/healthcheck") | ||
assert response.status_code == 200 | ||
assert response.json() == {"status": "ok"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters