use Sasae for templating.

This commit is contained in:
flash 2023-08-24 23:13:29 +00:00
parent a16c206764
commit aa78d5f695
10 changed files with 553 additions and 94 deletions

View file

@ -3,8 +3,8 @@
"prefer-stable": true,
"require": {
"flashwave/index": "*",
"twig/twig": "^3.7",
"ramsey/uuid": "^4.7"
"ramsey/uuid": "^4.7",
"flashwave/sasae": "dev-master"
},
"autoload": {
"classmap": [

508
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "e106ca43064ca7a0d1859825175fce72",
"content-hash": "ff9d0183468159f0604580b95bf65a01",
"packages": [
{
"name": "brick/math",
@ -107,6 +107,46 @@
"homepage": "https://railgun.sh/index",
"time": "2023-08-22T00:04:20+00:00"
},
{
"name": "flashwave/sasae",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://git.flash.moe/flash/sasae.git",
"reference": "f16e361bece2ebe62d12f71324d9d4f02cdaa6ee"
},
"require": {
"flashwave/index": "dev-master",
"php": ">=8.2",
"twig/html-extra": "^3.7",
"twig/twig": "^3.7"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.2"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
"Sasae\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"bsd-3-clause-clear"
],
"authors": [
{
"name": "flashwave",
"email": "packagist@flash.moe",
"homepage": "https://flash.moe",
"role": "mom"
}
],
"description": "A wrapper for Twig with added common functionality.",
"time": "2023-08-24T23:00:41+00:00"
},
{
"name": "ramsey/collection",
"version": "2.0.0",
@ -288,6 +328,157 @@
],
"time": "2023-04-15T23:01:58+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-05-23T14:45:45+00:00"
},
{
"name": "symfony/mime",
"version": "v6.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "9a0cbd52baa5ba5a5b1f0cacc59466f194730f98"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/9a0cbd52baa5ba5a5b1f0cacc59466f194730f98",
"reference": "9a0cbd52baa5ba5a5b1f0cacc59466f194730f98",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
"conflict": {
"egulias/email-validator": "~3.0.0",
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
"symfony/mailer": "<5.4",
"symfony/serializer": "<6.2.13|>=6.3,<6.3.2"
},
"require-dev": {
"egulias/email-validator": "^2.1.10|^3.1|^4",
"league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/property-access": "^5.4|^6.0",
"symfony/property-info": "^5.4|^6.0",
"symfony/serializer": "~6.2.13|^6.3.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Mime\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Allows manipulating MIME messages",
"homepage": "https://symfony.com",
"keywords": [
"mime",
"mime-type"
],
"support": {
"source": "https://github.com/symfony/mime/tree/v6.3.3"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-07-31T07:08:24+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
@ -370,6 +561,177 @@
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
"shasum": ""
},
"require": {
"php": ">=7.1",
"symfony/polyfill-intl-normalizer": "^1.10",
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Trevor Rowbotham",
"email": "trevor.rowbotham@pm.me"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
@ -453,6 +815,146 @@
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "twig/html-extra",
"version": "v3.7.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/html-extra.git",
"reference": "af5b336a13122d28d405714b6f2abe840632251b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/html-extra/zipball/af5b336a13122d28d405714b6f2abe840632251b",
"reference": "af5b336a13122d28d405714b6f2abe840632251b",
"shasum": ""
},
"require": {
"php": ">=7.1.3",
"symfony/mime": "^4.4|^5.0|^6.0",
"twig/twig": "^2.7|^3.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Twig\\Extra\\Html\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
}
],
"description": "A Twig extension for HTML",
"homepage": "https://twig.symfony.com",
"keywords": [
"html",
"twig"
],
"support": {
"source": "https://github.com/twigphp/html-extra/tree/v3.7.0"
},
"funding": [
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
"type": "tidelift"
}
],
"time": "2023-02-09T06:45:16+00:00"
},
{
"name": "twig/twig",
"version": "v3.7.0",
@ -528,7 +1030,9 @@
"packages-dev": [],
"aliases": [],
"minimum-stability": "dev",
"stability-flags": [],
"stability-flags": {
"flashwave/sasae": 20
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": [],

View file

@ -3,6 +3,7 @@ namespace Mince;
use Index\Http\HttpFx;
use Index\Security\CSRFP;
use Sasae\SasaeEnvironment;
require_once __DIR__ . '/../mince.php';
@ -21,13 +22,9 @@ $csrfp = new CSRFP(
$authInfo->success ? $authToken : $_SERVER['REMOTE_ADDR']
);
$templating = new Templating;
$templating->addPath(MCR_DIR_TPL);
$templating->addVars([
'global' => [
'title' => 'Flashii Minecraft Servers',
],
$templating = new SasaeEnvironment(MCR_DIR_TPL, ['Mince'], debug: MCR_DEBUG);
$templating->addGlobal('globals', [
'title' => 'Flashii Minecraft Servers',
'is_authed' => $userInfo !== null,
'user' => $userInfo,
'csrfp' => $csrfp->createToken(),
@ -54,7 +51,7 @@ $router->setDefaultErrorHandler(function($response, $request, $code, $text) use
});
(new RpcRoutes($users, $accountLinks, $authorisations, $verifications, $config['rpc_secret'], $config['clients_url']))->register($router);
(new HomeRoutes(new Servers($db), $templating, $authInfo, $config['login_url']))->register($router);
(new HomeRoutes($templating, new Servers($db), $authInfo, $config['login_url']))->register($router);
(new ClientsRoutes($templating, $accountLinks, $authorisations, $verifications, $csrfp, $authInfo))->register($router);
(new SkinsRoutes($templating, $accountLinks, new Skins($db), new Capes($db), $csrfp, $authInfo, $config['skins_base_url']))->register($router);

View file

@ -6,10 +6,11 @@ use RuntimeException;
use Index\Routing\IRouter;
use Index\Security\CSRFP;
use Ramsey\Uuid\Uuid;
use Sasae\SasaeEnvironment;
class ClientsRoutes {
public function __construct(
private Templating $templating,
private SasaeEnvironment $templating,
private AccountLinks $accountLinks,
private Authorisations $authorisations,
private Verifications $verifications,
@ -49,13 +50,15 @@ class ClientsRoutes {
];
public function getClients($response, $request) {
$template = $this->templating->load('clients/index');
$errorCode = (string)$request->getParam('error');
if($errorCode !== '') {
$errorCode = explode(':', $errorCode, 2);
if(count($errorCode) === 2
&& array_key_exists($errorCode[0], self::CLIENTS_ERRORS)
&& array_key_exists($errorCode[1], self::CLIENTS_ERRORS[$errorCode[0]]))
$this->templating->addVars([
$template->setVars([
'error' => [
'section' => $errorCode[0],
'code' => $errorCode[1],
@ -68,13 +71,13 @@ class ClientsRoutes {
$linkInfo = $this->accountLinks->getLink(userInfo: $this->authInfo->user_id);
$clients = $this->authorisations->getAuthorisations($linkInfo);
$this->templating->addVars([
$template->setVars([
'link' => $linkInfo,
'clients' => $clients,
]);
} catch(RuntimeException $ex) {}
return $this->templating->render('clients/index');
return $template;
}
public function postLink($response, $request) {

View file

@ -2,11 +2,12 @@
namespace Mince;
use Index\Routing\IRouter;
use Sasae\SasaeEnvironment;
class HomeRoutes {
public function __construct(
private SasaeEnvironment $templating,
private Servers $servers,
private Templating $templating,
private object $userInfo,
private string $loginUrl
) {}

View file

@ -10,6 +10,7 @@ use Index\XString;
use Index\Routing\IRouter;
use Index\Security\CSRFP;
use Ramsey\Uuid\Uuid;
use Sasae\SasaeEnvironment;
class SkinsRoutes {
private const TEXTURES_DIR = '/textures';
@ -18,7 +19,7 @@ class SkinsRoutes {
private AccountLinkInfo $linkInfo;
public function __construct(
private Templating $templating,
private SasaeEnvironment $templating,
private AccountLinks $accountLinks,
private Skins $skins,
private Capes $capes,
@ -97,13 +98,26 @@ class SkinsRoutes {
];
public function getSkins($response, $request) {
$skinInfo = $this->skins->getSkin($this->linkInfo);
$skinPath = $skinInfo === null ? null : $this->getRemotePath($skinInfo->getHash(), false);
$capeInfo = $this->capes->getCape($this->linkInfo);
$capePath = $capeInfo === null ? null : $this->getRemotePath($capeInfo->getHash(), false);
$template = $this->templating->load('skins/index', [
'skin' => $skinInfo,
'skin_path' => $skinPath,
'cape' => $capeInfo,
'cape_path' => $capePath,
'link_info' => $this->linkInfo,
]);
$errorCode = (string)$request->getParam('error');
if($errorCode !== '') {
$errorCode = explode(':', $errorCode, 2);
if(count($errorCode) === 2
&& array_key_exists($errorCode[0], self::SKINS_ERRORS)
&& array_key_exists($errorCode[1], self::SKINS_ERRORS[$errorCode[0]]))
$this->templating->addVars([
$template->setVars([
'error' => [
'section' => $errorCode[0],
'code' => $errorCode[1],
@ -112,18 +126,7 @@ class SkinsRoutes {
]);
}
$skinInfo = $this->skins->getSkin($this->linkInfo);
$skinPath = $skinInfo === null ? null : $this->getRemotePath($skinInfo->getHash(), false);
$capeInfo = $this->capes->getCape($this->linkInfo);
$capePath = $capeInfo === null ? null : $this->getRemotePath($capeInfo->getHash(), false);
return $this->templating->render('skins/index', [
'skin' => $skinInfo,
'skin_path' => $skinPath,
'cape' => $capeInfo,
'cape_path' => $capePath,
'link_info' => $this->linkInfo,
]);
return $template;
}
public function postUploadSkin($response, $request) {

View file

@ -1,49 +0,0 @@
<?php
namespace Mince;
use Twig\Environment as TwigEnvironment;
use Twig\Loader\FilesystemLoader as TwigLoaderFilesystem;
class Templating {
private const FILE_EXT = '.twig';
private TwigEnvironment $env;
private TwigLoaderFilesystem $loader;
private array $vars = [];
public function __construct() {
$this->loader = new TwigLoaderFilesystem;
$this->env = new TwigEnvironment($this->loader, [
//'cache' => $cache ?? false,
'debug' => MCR_DEBUG,
'strict_variables' => true,
]);
}
public function addPath(string $path): void {
$this->loader->addPath($path);
}
public function setVar(string $path, $value): void {
$path = array_reverse(explode('.', $path));
$target = &$this->vars;
$targetName = array_pop($path);
if(!empty($path))
while(($name = array_pop($path)) !== null) {
if(!array_key_exists($name, $target))
$target[$name] = [];
$target = &$target[$name];
}
$target[$targetName] = $value;
}
public function addVars(array $vars): void {
$this->vars = array_merge($this->vars, $vars);
}
public function render(string $path, array $vars = []): string {
return $this->env->render($path . self::FILE_EXT, array_merge($this->vars, $vars));
}
}

View file

@ -18,7 +18,7 @@
{% endif %}
<form method="post" action="/clients/link">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<label>
<div class="label-header">Link code</div>
<div class="label-input"><input type="text" name="code" value="" minlength="10" maxlength="10" pattern="^[A-Za-z0-9]*$" spellcheck="false"></div>
@ -70,13 +70,13 @@
<td class="actions">
{% if client.isPending %}
<form method="post" action="/clients/authorise">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<input type="hidden" name="auth" value="{{ client.id }}">
<input class="action action-authorise js-authorise-button" type="submit" value="Approve" disabled onclick="return confirm('Are you sure?');">
</form>
{% endif %}
<form method="post" action="/clients/deauthorise">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<input type="hidden" name="auth" value="{{ client.id }}">
<input class="action action-deauthorise" type="submit" value="{% if client.isPending %}Deny{% else %}Deauthorise{% endif %}">
</form>
@ -93,7 +93,7 @@
<h2>Crowd Control</h2>
<p>Provided for those who prefer the nuclear option. Pressing the first button will deauthorise all clients, the other one will only remove pending ones.</p>
<form method="post" action="/clients/deauthorise">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<button class="form-btn-red" name="auth" value="all">Deauthorise all clients</button>
<button class="form-btn-green" name="auth" value="pending">Deny pending clients</button>
</form>
@ -104,7 +104,7 @@
<p>This is the Minecraft account currently associated with your Flashii ID. Revoking revoke your access to the servers. <strong>If you're planning on changing your username, please keep in mind that your stats and inventory on the servers WILL NOT carry over automatically.</strong></p>
<p>Your account has been linked with <b>{{ link.name }}</b> since <b>{{ link.createdTime|date('Y-m-d H:i:s T') }}</b>.</p>
<form method="post" action="/clients/unlink">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<input type="submit" value="Unlink account">
</form>
</div>

View file

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<title>{{ title|default(global.title) }}</title>
<title>{{ title|default(globals.title) }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/mince.css" type="text/css" rel="stylesheet">
</head>
@ -17,14 +17,14 @@
<a href="/">Home</a>
<a href="/downloads">Downloads</a>
<a href="/guide">Guide</a>
{% if is_authed %}
{% if globals.is_authed %}
<a href="/clients">Clients</a>
<a href="/skins">Skins</a>
{% endif %}
</div>
<div class="header-user">
{% if is_authed %}
Logged in as <span style="color: {{ user.colour }}">{{ user.name }}</span>
{% if globals.is_authed %}
Logged in as <span style="color: {{ globals.user.colour }}">{{ globals.user.name }}</span>
{% else %}
<a href="/login">Log in</a>
{% endif %}

View file

@ -18,7 +18,7 @@
<div class="skins-form">
<form method="post" action="/skins/upload-skin" enctype="multipart/form-data">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<input type="file" name="texture">
<select name="model">
{% set selected_model = skin.model|default() %}
@ -29,7 +29,7 @@
</form>
{% if skin is not null %}
<form method="post" action="/skins/delete-skin">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<input type="submit" value="Delete Skin" class="skins-form-delete">
</form>
{% endif %}
@ -52,13 +52,13 @@
<div class="skins-form">
<form method="post" action="/skins/upload-cape" enctype="multipart/form-data">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<input type="file" name="texture">
<input type="submit" value="Upload Cape" class="skins-form-upload">
</form>
{% if cape is not null %}
<form method="post" action="/skins/delete-cape">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<input type="submit" value="Delete Cape" class="skins-form-delete">
</form>
{% endif %}
@ -75,7 +75,7 @@
<h2>Import from Mojang account</h2>
<p>Import skin and cape textures from a Mojang Minecraft account. If you linked the same username as your actual Minecraft account, you can just press Import without anything.</p>
<form method="post" action="/skins/import">
<input type="hidden" name="csrfp" value="{{ csrfp }}">
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
<label>
<div class="label-header">Minecraft Username</div>
<div class="label-input"><input type="text" name="username" spellcheck="false" placeholder="{{ link_info.name }}"></div>