4 Commits

Author SHA1 Message Date
matthias@matsewe.de
e227792f08 Incorporate Choriosity CI 2024-07-02 11:59:10 +02:00
matthias@matsewe.de
ff92ff3020 Fix voting if ajax request fails 2024-06-27 21:18:01 +02:00
matthias@matsewe.de
78d964455c fix 2024-06-25 13:20:55 +02:00
matthias@matsewe.de
6cd1064f1d Adapt for oauth by traefik 2024-06-25 11:46:31 +02:00
7 changed files with 136 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
from typing import Annotated
from fastapi import HTTPException, Cookie, status
from fastapi import HTTPException, Cookie, status, Request
from fastapi.security import SecurityScopes
from jose import JWTError, jwt
from pydantic import ValidationError
@@ -10,9 +10,6 @@ import os
# to get a string like this run:
# openssl rand -hex 32
ALGORITHM = "HS512"
SECRET_KEY = os.environ['SECRET_KEY']
scopes_db = {
os.environ['ADMIN_EMAIL'] : ["admin"]
}
@@ -23,18 +20,17 @@ credentials_exception = HTTPException(
)
async def get_current_user(
security_scopes: SecurityScopes, access_token: Annotated[str, Cookie()] = ""
):
security_scopes: SecurityScopes, request: Request
):
try:
payload = jwt.decode(access_token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub") # type: ignore
username: str = request.headers.get("x-auth-request-user") # type: ignore
if username is None:
raise credentials_exception
email: str = payload.get("email") # type: ignore
email: str = request.headers.get("x-auth-request-email") # type: ignore
except (JWTError, ValidationError):
raise credentials_exception
scopes = scopes_db.get(email)
scopes = scopes_db.get(email, [])
for scope in security_scopes.scopes:
if scope not in scopes:
raise credentials_exception
return payload | {"internal_scopes" : scopes}
return {"sub" : username, "email" : email, "internal_scopes" : scopes}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,8 +1,55 @@
:root {
--color-white-100: white;
--color-white-90: #e6e6e6;
--color-white-80: #cccccc;
--color-white-70: #b3b3b3;
--color-white-10: #191919;
--color-choriosity-red: #be0519;
--color-choriosity-red--medium: #990514;
--color-choriosity-red--darker: #66030d;
--color-choriosity-red--rgba: 190, 5, 25;
--color-choriosity-red--light: #faeaea;
--color-background: #fffffa;
--color-tap: var(--color-choriosity-red--darker);
--color-callout-bg: var(--color-background);
}
@font-face {
font-family: 'Fira Sans';
src: url(FiraSans-Regular.woff2) format("woff2");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Fira Sans';
src: url(FiraSans-Italic.woff2) format("woff2");
font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'Fira Sans';
src: url(FiraSans-Medium.woff2) format("woff2");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: 'Fira Sans';
src: url(FiraSans-SemiBold.woff2) format("woff2");
font-weight: 600;
font-style: normal;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: sans-serif;
font-family: Fira Sans, Helvetica, Arial, sans-serif;
}
.vote-buttons,
@@ -31,6 +78,7 @@
padding: 0.3em;
margin-bottom: 0.7em;
display: inline-block;
font-size: 1.25rem;
}
.clear {
@@ -38,13 +86,13 @@
}
.song {
background-color: #f0f0f0;
background-color: var(--color-choriosity-red--light);
padding: 0.4em;
border-radius: 0.5em;
width: 30em;
font-family: sans-serif;
margin-bottom: 1rem;
margin-left: 0.5em;
float: left;
}
@@ -225,21 +273,28 @@
}
h1 {
font-family: sans-serif;
padding: 0.1em;
padding-left: 0.2em;
margin-bottom: 1rem;
font-size: 1.5em;
font-size: 1.25rem;
background-color: var(--color-choriosity-red);
color: white;
/*border-bottom: 0.3rem solid var(--color-choriosity-red--light);*/
clear: both;
}
#songs h1 .color {
border: 0.2rem solid color-mix(in srgb, hsl(calc(var(--hue) * 360), 100%, 40%) 50%, white);
background-color: hsl(calc(var(--hue) * 360), 100%, 40%);
border-radius: 0.5em;
margin-right: 1em;
}
#songs h1 {
background-color: color-mix(in srgb, hsl(calc(var(--hue) * 360), 100%, 40%) 50%, transparent);
border-bottom: 0.3rem solid hsl(calc(var(--hue) * 360), 100%, 40%);
}
body>h1 {
background-color: color-mix(in srgb, hsl(0, 0%, 40%) 50%, transparent);
border-bottom: 0.3rem solid hsl(0, 0%, 40%);
border-left: 0.3em solid white;
box-shadow: -1em 0px 0px 0px hsl(calc(var(--hue) * 360), 100%, 40%);
margin-left: 1em;
padding-left: 0.3em;
}
#yt-player,
@@ -278,4 +333,19 @@ body>h1 {
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
width: 1.5em;
}
#title {
margin-top: 1em;
font-size: 2rem;
/*line-height: 2rem;*/
}
#title-logo {
margin-top: -0.7em;
margin-bottom: -0.8em;
vertical-align: middle;
height: 3em;
filter: drop-shadow(0 0 1px var(--color-choriosity-red--medium));
margin-right: 1em;
}

View File

@@ -19,6 +19,7 @@
border-radius: 0.2em;
padding: 0.1em;
}
.not_singable {
background-color: color-mix(in srgb, #e1412f 30%, #f0f0f0);
}
@@ -124,41 +125,49 @@
}
function vote(song_id, vote) {
no_button = $("#song-" + song_id).find(".button-no")
yes_button = $("#song-" + song_id).find(".button-yes")
neutral_button = $("#song-" + song_id).find(".button-neutral")
no_button.removeClass("selected")
yes_button.removeClass("selected")
neutral_button.removeClass("selected")
switch (vote) {
case 0:
neutral_button.addClass("selected")
{% if veto_mode %}
$("#song-" + song_id).removeClass("not_singable")
{% endif %}
break;
case 1:
yes_button.addClass("selected")
{% if veto_mode %}
$("#song-" + song_id).removeClass("not_singable")
{% endif %}
break;
case -1:
no_button.addClass("selected")
{% if veto_mode %}
$("#song-" + song_id).addClass("not_singable")
{% endif %}
break;
default:
break;
}
$.ajax({
url: "/songs/" + song_id + "/vote?" + $.param({ session_id: session_id, vote: vote }),
method: "POST"
})
method: "POST",
success: function (data, textStatus) {
no_button = $("#song-" + song_id).find(".button-no")
yes_button = $("#song-" + song_id).find(".button-yes")
neutral_button = $("#song-" + song_id).find(".button-neutral")
no_button.removeClass("selected")
yes_button.removeClass("selected")
neutral_button.removeClass("selected")
switch (vote) {
case 0:
neutral_button.addClass("selected")
{% if veto_mode %}
$("#song-" + song_id).removeClass("not_singable")
{% endif %}
break;
case 1:
yes_button.addClass("selected")
{% if veto_mode %}
$("#song-" + song_id).removeClass("not_singable")
{% endif %}
break;
case -1:
no_button.addClass("selected")
{% if veto_mode %}
$("#song-" + song_id).addClass("not_singable")
{% endif %}
break;
default:
break;
}
}
});
}
{% if veto_mode %}
@@ -176,11 +185,12 @@
<body>
{% if veto_mode %}
<h1>Vorschau Modus</h1>
<div class="text">Du kannst ungeeignete Vorschläge durch eine Nein-Stimme markieren und Kommentare zu allen Liedern abgeben.
<div class="text">Du kannst ungeeignete Vorschläge durch eine Nein-Stimme markieren und Kommentare zu allen Liedern
abgeben.
</div>
{% else %}
<h1>Hallo :)</h1>
<div class="text">Du kannst die Liederwahl jederzeit unterbrechen und zu einem späteren Zeitpunkt weitermachen.
<h1 id="title"><img id="title-logo" src="https://choriosity.de/assets/images/logo-choriosity_weiss.svg"> Liederwahl</h1>
<div class="text">Du kannst die Liederwahl jederzeit unterbrechen und zu einem späteren Zeitpunkt weitermachen. Mit einem Klick auf das Thumbnail kannst du das Lied abspielen.
</div>
{% endif %}
<div id="songs">
@@ -222,7 +232,8 @@
{% if veto_mode %}
<input type="text" class="comment"
value="{% if song.vote_comment %}{{ song.vote_comment }}{% else %}{% endif %}"
placeholder="{% if song.comment %}{{ song.comment }}{% else %}Kommentar{% endif %}" onchange="updateComment({{ song.id }}, this);">
placeholder="{% if song.comment %}{{ song.comment }}{% else %}Kommentar{% endif %}"
onchange="updateComment({{ song.id }}, this);">
{% endif %}
</div>
{% endfor %}