Skip to content

Commit

Permalink
Merge pull request #397 from Shikkanime/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Ziedelth authored Apr 20, 2024
2 parents eececec + 9386e45 commit abc426b
Show file tree
Hide file tree
Showing 16 changed files with 53 additions and 31 deletions.
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
FROM mcr.microsoft.com/playwright:v1.43.1-jammy
ARG version=21.0.2.13-1
ARG version=21.0.3.9-1
ENV LANG C.UTF-8
ENV JAVA_HOME /usr/lib/jvm/java-21-amazon-corretto
ENV TZ Europe/Paris

# Install Java and necessary packages
RUN set -eux; \
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends curl ca-certificates gnupg software-properties-common fontconfig java-common tzdata libopencv-dev fonts-dejavu \
RUN set -eux \
&& apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends curl ca-certificates gnupg software-properties-common fontconfig java-common tzdata libopencv-dev fonts-dejavu \
&& curl -fL https://apt.corretto.aws/corretto.key | apt-key add - \
&& add-apt-repository 'deb https://apt.corretto.aws stable main' \
&& mkdir -p /usr/share/man/man1 || true \
&& apt-get update; apt-get install -y java-21-amazon-corretto-jdk=1:"$version" \
&& apt-get update; apt-get install -y java-21-amazon-corretto-jdk=1:$version \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false curl gnupg software-properties-common \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* \
&& ln -snf /usr/share/zoneinfo/"$TZ" /etc/localtime && echo "$TZ" > /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata
Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,11 @@ services:
DATABASE_URL: jdbc:postgresql://shikkanime-db:5432/shikkanime
DATABASE_USERNAME: postgres
DATABASE_PASSWORD: "mysecretpassword"
JWT_SECRET: "mysecretkey"
JWT_DOMAIN: "http://localhost:37100"
JWT_REALM: "Access to '/admin'"
JWT_AUDIENCE: "http://localhost:37100/admin"
BASE_URL: "http://localhost:37100"
API_URL: "http://localhost:37100/api"
volumes:
- ./data:/app/data/
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ class AnimeController : HasPageableRoute() {

@Path("/{uuid}")
@Get
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun animeDetails(
@PathParam("uuid") uuid: UUID,
): Response {
return Response.ok(animeService.find(uuid))
return Response.ok(AbstractConverter.convert(animeService.find(uuid), AnimeDto::class.java))
}

@Path("/{uuid}")
@Put
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun updateAnime(@PathParam("uuid") uuid: UUID, @BodyParam animeDto: AnimeDto): Response {
val updated = animeService.update(uuid, animeDto)
Expand All @@ -108,7 +108,7 @@ class AnimeController : HasPageableRoute() {

@Path("/{uuid}")
@Delete
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun deleteAnime(@PathParam("uuid") uuid: UUID): Response {
animeService.delete(animeService.find(uuid) ?: return Response.notFound())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import fr.shikkanime.converters.AbstractConverter
import fr.shikkanime.dtos.ConfigDto
import fr.shikkanime.services.ConfigService
import fr.shikkanime.utils.Constant
import fr.shikkanime.utils.routes.AdminSessionAuthenticated
import fr.shikkanime.utils.routes.Controller
import fr.shikkanime.utils.routes.JWTAuthenticated
import fr.shikkanime.utils.routes.Path
import fr.shikkanime.utils.routes.Response
import fr.shikkanime.utils.routes.method.Get
Expand All @@ -24,7 +24,7 @@ class ConfigController {

@Path
@Get
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun getConfigs(
@QueryParam("name") nameParam: String?,
Expand All @@ -40,7 +40,7 @@ class ConfigController {

@Path("/{uuid}")
@Put
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun updateConfig(@PathParam("uuid") uuid: UUID, @BodyParam configDto: ConfigDto): Response {
configService.update(uuid, configDto)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ class EpisodeMappingController : HasPageableRoute() {

@Path("/{uuid}")
@Get
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun read(@PathParam("uuid") uuid: UUID): Response {
return Response.ok(episodeMappingService.find(uuid))
return Response.ok(AbstractConverter.convert(episodeMappingService.find(uuid), EpisodeMappingDto::class.java))
}

@Path("/{uuid}")
@Put
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun updateEpisode(
@PathParam("uuid") uuid: UUID,
Expand All @@ -93,7 +93,7 @@ class EpisodeMappingController : HasPageableRoute() {

@Path("/{uuid}")
@Delete
@AdminSessionAuthenticated
@JWTAuthenticated
@OpenAPI(hidden = true)
private fun deleteEpisode(@PathParam("uuid") uuid: UUID): Response {
episodeMappingService.delete(episodeMappingService.find(uuid) ?: return Response.notFound())
Expand Down
11 changes: 7 additions & 4 deletions src/main/kotlin/fr/shikkanime/modules/Routing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ private fun setSecurityHeaders(call: ApplicationCall, configCacheService: Config

context.response.header(
"Content-Security-Policy",
"default-src 'self'; font-src 'self';" +
"style-src 'self' 'unsafe-inline' 'unsafe-eval';" +
"script-src 'self' 'unsafe-inline' 'unsafe-eval';" +
"img-src data: 'self' ${Constant.apiUrl} ${Constant.baseUrl};" +
"default-src 'self';" +
"style-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net;" +
"font-src 'self' https://cdn.jsdelivr.net; " +
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net;" +
"img-src data: 'self' 'unsafe-inline' 'unsafe-eval' ${Constant.apiUrl} ${Constant.baseUrl};" +
"connect-src 'self' ${Constant.apiUrl} ${configCacheService.getValueAsString(ConfigPropertyKey.ANALYTICS_API) ?: ""};"
)

Expand Down Expand Up @@ -199,6 +200,8 @@ private suspend fun handleTemplateResponse(
val map = response.data as Map<String, Any> // NOSONAR
val modelMap = (map["model"] as Map<String, Any?>).toMutableMap() // NOSONAR
setGlobalAttributes(modelMap, controller, replacedPath, map["title"] as String?)
call.principal<TokenDto>()?.token?.let { modelMap["token"] = it }

call.respond(response.status, FreeMarkerContent(map["template"] as String, modelMap, "", response.contentType))
}

Expand Down
8 changes: 7 additions & 1 deletion src/main/kotlin/fr/shikkanime/modules/Security.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,18 @@ private fun setupJWTVerifier(): JWTVerifier = JWT
.build()

private fun AuthenticationConfig.setupJWTAuthentication(jwtVerifier: JWTVerifier) {
jwt {
jwt("auth-jwt") {
realm = Constant.jwtRealm
verifier(jwtVerifier)
validate { credential ->
if (credential.payload.audience.contains(Constant.jwtAudience)) JWTPrincipal(credential.payload) else null
}
challenge { _, _ ->
call.respond(
HttpStatusCode.Unauthorized,
MessageDto(MessageDto.Type.ERROR, "You are not authorized to access this page")
)
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/assets/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ function copyToClipboard(content) {
}

async function callApi(url, options = {}) {
const {abortSignal, method = 'GET', body = null} = options;
const {abortSignal, method = 'GET', authorization = null, body = null} = options;
const headers = {'Content-Type': 'application/json'};
if (authorization) headers['Authorization'] = 'Bearer ' + authorization;
const fetchOptions = {headers, signal: abortSignal, method};
if (method !== 'GET') fetchOptions.body = JSON.stringify(body);

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/templates/_freemarker_implicit.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
[#-- @ftlvariable name="selectedSimulcast" type="fr.shikkanime.dtos.SimulcastDto" --]
[#-- @ftlvariable name="googleSiteVerification" type="java.lang.String" --]
[#-- @ftlvariable name="seoDescription" type="java.lang.String" --]
[#-- @ftlvariable name="token" type="java.lang.String" --]
[#-- @ftlvariable name="currentSimulcast" type="fr.shikkanime.dtos.SimulcastDto" --]
[#-- @ftlvariable name="footerLinks" type="kotlin.collections.AbstractList<fr.shikkanime.entities.LinkObject>" --]
[#-- @ftlvariable name="seoLinks" type="kotlin.collections.AbstractList<fr.shikkanime.entities.enums.Link>" --]
Expand Down
6 changes: 4 additions & 2 deletions src/main/resources/templates/admin/animes/edit.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,15 @@
async function loadAnime() {
const uuid = getUuid();
return await callApi('/api/v1/animes/' + uuid);
return await callApi('/api/v1/animes/' + uuid, {authorization: '${token}'});
}
async function updateAnime(anime) {
const uuid = getUuid();
await callApi('/api/v1/animes/' + uuid, {
method: 'PUT',
authorization: '${token}',
body: anime
})
.then(() => {
Expand All @@ -234,7 +235,8 @@
const uuid = getUuid();
await callApi('/api/v1/animes/' + uuid, {
method: 'DELETE'
method: 'DELETE',
authorization: '${token}'
}).catch(() => {
const toastEl = document.getElementById('errorToast');
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastEl)
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/templates/admin/configs.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,13 @@
params = '?name=' + name;
}
return await callApi('/api/config' + params);
return await callApi('/api/config' + params, {authorization: '${token}'});
}
async function updateConfig(config) {
await callApi('/api/config/' + config.uuid, {
method: 'PUT',
authorization: '${token}',
body: config
})
.then(() => {
Expand Down
6 changes: 4 additions & 2 deletions src/main/resources/templates/admin/episodes/edit.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,15 @@
async function loadEpisode() {
const uuid = getUuid();
return await callApi('/api/v1/episode-mappings/' + uuid);
return await callApi('/api/v1/episode-mappings/' + uuid, {authorization: '${token}'});
}
async function updateEpisode(episode) {
const uuid = getUuid();
await callApi('/api/v1/episode-mappings/' + uuid, {
method: 'PUT',
authorization: '${token}',
body: episode
})
.then(() => {
Expand All @@ -243,7 +244,8 @@
const uuid = getUuid();
await callApi('/api/v1/episode-mappings/' + uuid, {
method: 'DELETE'
method: 'DELETE',
authorization: '${token}'
}).catch(() => {
const toastEl = document.getElementById('errorToast');
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastEl)
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/templates/site/_layout.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
<link rel="icon" type="image/png" sizes="32x32" href="/assets/img/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/img/favicons/favicon-16x16.png">

<link rel="stylesheet" href="/assets/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="/assets/css/main.css" crossorigin="anonymous">
<link rel="stylesheet" href="/assets/css/purged/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="/assets/css/purged/main.min.css" crossorigin="anonymous">
<script defer src="/assets/js/alpinejs.min.js" crossorigin="anonymous"></script>

<#if (analyticsDomain?? && analyticsDomain?length != 0) && (analyticsApi?? && analyticsApi?length != 0) && (analyticsScript?? && analyticsScript?length != 0)>
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/templates/site/catalog.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</div>
</div>

<div class="row mt-3 justify-content-center">
<div class="row g-3 mt-3 justify-content-center">
<#list animes as anime>
<@animeComponent.display anime=anime />
</#list>
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/templates/site/home.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
</div>

<#if animes?? && animes?size != 0>
<div class="row">
<div class="row g-3">
<#list animes as anime>
<@animeComponent.display anime=anime />
</#list>
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/templates/site/search.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
placeholder="Rechercher" autofocus @input="animes = (await search($event.target.value)).data">
</div>

<div class="row justify-content-center" style="min-height: 50vh;">
<div class="row g-3 justify-content-center" style="min-height: 50vh;">
<template x-for="anime in animes">
<div class="col-md-2 col-6 mt-0">
<article x-data="{hover:false}" class="shikk-element">
Expand Down

0 comments on commit abc426b

Please sign in to comment.