Tighter client side integrations for uploads.

This commit is contained in:
flash 2025-03-27 21:27:49 +00:00
parent 41e27cdffa
commit 12d40e69a5
Signed by: flash
GPG key ID: 2C9C2C574D47FE3E
17 changed files with 277 additions and 220 deletions

View file

@ -1,6 +1,7 @@
#include array.js
#include csrf.js
#include html.js
#include meta.js
#include uniqstr.js
#include xhr.js

36
assets/common.js/meta.js Normal file
View file

@ -0,0 +1,36 @@
#include html.js
const $meta = (() => {
return {
get(name, prefixed=true) {
if(!name) return;
if(prefixed) name = `msz-${name}`;
const elem = $query(`meta[name="${name}"]`);
if(elem instanceof HTMLMetaElement && typeof elem.content === 'string')
return elem.content;
return null;
},
set(name, value, prefixed=true) {
if(!name) return;
if(prefixed) name = `msz-${name}`;
let elem = $query(`meta[name="${name}"]`);
if(elem instanceof HTMLMetaElement) {
if(typeof value === 'string')
elem.content = value;
else
elem.remove();
} else {
if(typeof value !== 'string')
return;
elem = document.createElement('meta');
elem.name = name;
elem.content = value;
document.head.appendChild(elem);
}
},
};
})();

View file

@ -1,8 +1,6 @@
const MszEEPROM = function(appId, endPoint) {
const MszEEPROM = function(appId) {
if(typeof appId !== 'string')
throw 'appId must be a string';
if(typeof endPoint !== 'string')
throw 'endPoint must be a string';
return {
create: fileInput => {
@ -42,7 +40,7 @@ const MszEEPROM = function(appId, endPoint) {
formData.append('src', appId);
formData.append('file', fileInput);
const { status, body } = await $xhr.post(`${endPoint}/uploads`, {
const { status, body } = await $xhr.post('/uploads', {
type: 'json',
authed: true,
upload: reportProgress,

View file

@ -19,9 +19,10 @@ const MszForumEditor = function(form) {
let lastPostText = '';
let lastPostParser;
const eepromClient = new MszEEPROM(peepApp, peepPath);
const storagePool = $meta.get('forum-storage-pool');
if(storagePool) {
const eepromClient = new MszEEPROM(storagePool);
const eepromHistory = <div class="eeprom-widget-history-items"/>;
const eepromHandleFileUpload = async file => {
const uploadElemNameValue = <div class="eeprom-widget-file-name-value" title={file.name}>{file.name}</div>;
const uploadElemName = <a class="eeprom-widget-file-name" target="_blank">{uploadElemNameValue}</a>;
@ -155,6 +156,7 @@ const MszForumEditor = function(form) {
eepromHandleFileUpload(file);
}
});
}
// hack: don't prompt user when hitting submit, really need to make this not stupid.
buttonsElem.firstChild.addEventListener('click', () => MszForumEditorAllowClose = true);

View file

@ -65,7 +65,9 @@ const MszMessagesReply = function(element) {
// this implementation is godawful but it'll do for now lol
// need to make it easier to share the forum's implementation
const eepromClient = new MszEEPROM(peepApp, peepPath);
const storagePool = $meta.get('messages-storage-pool');
if(storagePool) {
const eepromClient = new MszEEPROM(storagePool);
const eepromHandleFileUpload = async file => {
const uploadTask = eepromClient.create(file);
@ -132,6 +134,7 @@ const MszMessagesReply = function(element) {
eepromHandleFileUpload(file);
}
});
}
return {
get element() { return element; },

View file

@ -8,7 +8,6 @@ Below are a number of links to source code repositories related to Flashii.net a
- [Futami](https://patchii.net/flashii/futami): Common data shared between the chat clients.
- [Mami](https://patchii.net/flashii/mami): Web client for chat.
- [Ami](https://patchii.net/flashii/ami): Web client for chat for older browsers.
- [EEPROM](https://patchii.net/flashii/eeprom): Service for file uploading.
- [Uiharu](https://patchii.net/flashii/uiharu): Service for looking up URL metadata.
- [Seria](https://patchii.net/flashii/seria): Software used by the downloads tracker.
- [Mince](https://patchii.net/flashii/mince): Source code for the Minecraft servers subwebsite.

View file

@ -2,6 +2,7 @@
namespace Misuzu\Forum;
use stdClass;
use Index\Config\Config;
use Index\Db\DbConnection;
use Misuzu\Parsers\TextFormat;
use Misuzu\Users\UserInfo;
@ -22,7 +23,14 @@ class ForumContext {
/** @var array<string, ForumSignatureInfo> */
private array $cachedSignatures = [];
public function __construct(DbConnection $dbConn) {
public string $storagePoolName {
get => $this->config->getString('storage_pool');
}
public function __construct(
DbConnection $dbConn,
public private(set) Config $config,
) {
$this->categories = new ForumCategoriesData($dbConn);
$this->topics = new ForumTopicsData($dbConn);
$this->topicRedirects = new ForumTopicRedirectsData($dbConn);

View file

@ -1,12 +1,20 @@
<?php
namespace Misuzu\Messages;
use Index\Config\Config;
use Index\Db\DbConnection;
class MessagesContext {
public private(set) MessagesData $database;
public function __construct(DbConnection $dbConn) {
public string $storagePoolName {
get => $this->config->getString('storage_pool');
}
public function __construct(
DbConnection $dbConn,
public private(set) Config $config,
) {
$this->database = new MessagesData($dbConn);
}
}

View file

@ -94,8 +94,14 @@ class MisuzuContext {
config: $this->config->scopeTo('auth'),
));
$this->deps->register($this->commentsCtx = $this->deps->constructLazy(Comments\CommentsContext::class));
$this->deps->register($this->forumCtx = $this->deps->constructLazy(Forum\ForumContext::class));
$this->deps->register($this->messagesCtx = $this->deps->constructLazy(Messages\MessagesContext::class));
$this->deps->register($this->forumCtx = $this->deps->constructLazy(
Forum\ForumContext::class,
config: $this->config->scopeTo('forum'),
));
$this->deps->register($this->messagesCtx = $this->deps->constructLazy(
Messages\MessagesContext::class,
config: $this->config->scopeTo('messages'),
));
$this->deps->register($this->oauth2Ctx = $this->deps->constructLazy(
OAuth2\OAuth2Context::class,
config: $this->config->scopeTo('oauth2'),
@ -153,17 +159,17 @@ class MisuzuContext {
}
public function startTemplating(bool $cache = true): void {
$globals = $this->config->getValues([
['eeprom.path:s', '', 'eeprom_path'],
['eeprom.app:s', '', 'eeprom_app'],
['eeprom.appmsgs:s', '', 'eeprom_app_messages'],
]);
$isDebug = Misuzu::debug();
$globals['site_info'] = $this->siteInfo;
$globals['auth_info'] = $this->authInfo;
$globals['active_ban_info'] = $this->usersCtx->tryGetActiveBan($this->authInfo->userInfo);
$globals['display_timings_info'] = $isDebug || $this->authInfo->getPerms('global')->check(Perm::G_TIMINGS_VIEW);
$globals = [
'site_info' => $this->siteInfo,
'auth_info' => $this->authInfo,
'active_ban_info' => $this->usersCtx->tryGetActiveBan($this->authInfo->userInfo),
'display_timings_info' => $isDebug || $this->authInfo->getPerms('global')->check(Perm::G_TIMINGS_VIEW),
'meta' => [
'forum-storage-pool' => $this->forumCtx->storagePoolName,
'messages-storage-pool' => $this->messagesCtx->storagePoolName,
],
];
$this->templating = new TplEnvironment(
Misuzu::PATH_TEMPLATES,

View file

@ -146,7 +146,7 @@ class FilesContext {
throw new InvalidArgumentException('$format is not a supported format');
$type = 'application/octet-stream';
$path = tempnam(sys_get_temp_dir(), 'eeprom-thumbnail-');
$path = tempnam(sys_get_temp_dir(), 'msz-thumbnail-');
$imagick = new Imagick;
try {
$this->readIntoImagick($imagick, $original);
@ -174,7 +174,7 @@ class FilesContext {
if(!is_file($sourcePath))
throw new RuntimeException('local data for provided $original does not exist');
$targetPath = tempnam(sys_get_temp_dir(), sprintf('eeprom-crop-%d-', $dimensions));
$targetPath = tempnam(sys_get_temp_dir(), sprintf('msz-crop-%d-', $dimensions));
$imagick = new Imagick;
try {
if($original->isImage)

View file

@ -5,4 +5,5 @@ enum PoolInfoGetField {
case Id;
case Name;
case UploadId;
case IdOrName;
}

View file

@ -49,6 +49,7 @@ class PoolsData {
$field = match($field) {
PoolInfoGetField::Id => 'pool_id = ?',
PoolInfoGetField::Name => 'pool_name = ?',
PoolInfoGetField::IdOrName => sprintf('pool_%s = ?', ctype_digit($value) ? 'id' : 'name'),
PoolInfoGetField::UploadId => 'pool_id = (SELECT pool_id FROM msz_storage_uploads WHERE upload_id = ?)',
};

View file

@ -29,6 +29,6 @@ class TasksContext {
if($taskInfo instanceof TaskInfo)
$taskInfo = $taskInfo->id;
return implode(DIRECTORY_SEPARATOR, [sys_get_temp_dir(), sprintf('eeprom-upload-%s', $taskInfo)]);
return implode(DIRECTORY_SEPARATOR, [sys_get_temp_dir(), sprintf('msz-upload-%s', $taskInfo)]);
}
}

View file

@ -14,7 +14,7 @@ use Index\Urls\{UrlFormat,UrlSource,UrlSourceCommon};
use Misuzu\Perm;
use Misuzu\Auth\AuthInfo;
use Misuzu\Storage\Denylist\{DenylistContext,DenylistReason};
use Misuzu\Storage\Pools\PoolsContext;
use Misuzu\Storage\Pools\{PoolsContext,PoolInfoGetField};
use Misuzu\Storage\Pools\Rules\{ConstrainSizeRule,EnsureVariantRule,EnsureVariantRuleThumb};
use Misuzu\Storage\Files\{FilesContext,FileImportMode,FileInfoGetFileField};
use Misuzu\Users\UsersContext;
@ -180,7 +180,10 @@ class UploadsLegacyRoutes implements RouteHandler, UrlSource {
}
try {
$poolInfo = $this->poolsCtx->pools->getPool((string)$content->getFilteredParam('src', FILTER_VALIDATE_INT));
$poolInfo = $this->poolsCtx->pools->getPool(
(string)$content->getParam('src'),
PoolInfoGetField::IdOrName,
);
if($poolInfo->protected) {
$response->statusCode = 404;
return [
@ -227,7 +230,7 @@ class UploadsLegacyRoutes implements RouteHandler, UrlSource {
];
}
$tmpFile = tempnam(sys_get_temp_dir(), 'eeprom-upload-');
$tmpFile = tempnam(sys_get_temp_dir(), 'msz-upload-');
$file->moveTo($tmpFile);
$hash = hash_file('sha256', $tmpFile, true);

View file

@ -109,10 +109,4 @@
</div>
</div>
</form>
{% if globals.eeprom_path is not empty and globals.eeprom_app is not empty %}
<script>
const peepPath = '{{ globals.eeprom_path }}', peepApp = '{{ globals.eeprom_app }}';
</script>
{% endif %}
{% endblock %}

View file

@ -5,6 +5,9 @@
<link href="/vendor/fontawesome/css/all.min.css" rel="stylesheet">
<link href="{{ asset('common.css') }}" rel="stylesheet">
<link href="{{ asset('misuzu.css') }}" rel="stylesheet">
{% for name, value in globals.meta %}
{% if value is not empty %}<meta name="msz-{{ name }}" content="{{ value }}">{% endif %}
{% endfor %}
{% if main_css_vars is defined and main_css_vars is iterable and main_css_vars is not empty %}
<style>
:root {

View file

@ -3,10 +3,4 @@
{% block content %}
{% block messages_content %}
{% endblock %}
{% if globals.eeprom_path is not empty and globals.eeprom_app_messages is not empty %}
<script>
const peepPath = '{{ globals.eeprom_path }}', peepApp = '{{ globals.eeprom_app_messages }}';
</script>
{% endif %}
{% endblock %}