1
0
mirror of https://github.com/flarum/core.git synced 2025-08-14 04:14:06 +02:00

Compare commits

..

21 Commits

Author SHA1 Message Date
Ian Morland
82e08e3fa5 chore: prep 1.8.2 release 2023-09-22 20:01:59 +01:00
flarum-bot
2c4a2b8d9e Bundled output for commit 00866fbba9
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2023-09-22 18:51:39 +00:00
Ian Morland
00866fbba9 chore: bump version 2023-09-22 19:46:39 +01:00
IanM
0d1d4d46d1 fix: missing compat exports (#3888) 2023-09-22 19:38:59 +01:00
Sami Mazouz
b1383a955f fix(1.x,suspend): suspended users can abuse avatar upload (#3890)
* fix(1.x,suspend): suspended users can abuse avatar upload

* test: works as expected

* Apply fixes from StyleCI

---------

Co-authored-by: StyleCI Bot <bot@styleci.io>
2023-09-22 19:38:33 +01:00
Sami Mazouz
daeab48ae8 chore: turn on frontend build on 1.x branch 2023-09-20 21:12:54 +01:00
Ian Morland
e03ca4406d chore: build js 2023-07-06 12:03:30 +01:00
StyleCI Bot
7894c6a69b Apply fixes from StyleCI 2023-07-05 09:31:05 +00:00
Sami Mazouz
102e31754a chore: not 1.8.2 2023-07-04 11:19:15 +01:00
Sami Mazouz
8538f9c8f6 chore: prepare v1.8.2 release 2023-07-04 11:12:55 +01:00
Sami Mazouz
5a4bb7ccf2 fix: missing slug from post mention links 2023-07-04 11:00:45 +01:00
Sami Mazouz
d2a6329689 fix(mentions): cannot use mentionables extender (#3849) 2023-07-04 10:56:52 +01:00
Rafael Horvat
2bc2899a1d fix(mentions): missed post mentions UI changes (#3832)
Co-authored-by: Ian Morland <ian@morland.me>
2023-07-01 17:44:59 +01:00
Sami Mazouz
5437bf5c23 chore: prepare v1.8.1 release
Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
2023-05-23 19:24:51 +01:00
flarum-bot
717af13bb1 Bundled output for commit e72541e35d
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2023-05-22 21:58:15 +00:00
Sami Mazouz
e72541e35d fix: recover temporary solution for html entities in browser title
Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
2023-05-22 22:49:20 +01:00
Sami Mazouz
577890d89c fix: custom contrast color affected by parents
Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
2023-05-22 22:23:11 +01:00
Sami Mazouz
253a3d281d fix: reply placeholder wrong positioning
Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
2023-05-22 21:58:38 +01:00
flarum-bot
d27f952584 Bundled output for commit e5abffc75b
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2023-05-20 16:46:42 +00:00
Sami Mazouz
e5abffc75b chore: v1.8 preparations
Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
2023-05-20 16:08:42 +01:00
Sami Mazouz
d1059c1cc7 fix: improve avatar upload functionality
Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
2023-05-20 15:15:53 +01:00
60 changed files with 289 additions and 58 deletions

View File

@@ -10,7 +10,7 @@ jobs:
backend_directory: ./
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
main_git_branch: 1.x
enable_tests: true
# @TODO: fix bundlewatch
enable_bundlewatch: false

View File

@@ -1,5 +1,63 @@
# Changelog
## [v1.8.2](https://github.com/flarum/framework/compare/v1.8.1...v1.8.2)
### Fixed
* suspended users can abuse avatar upload [#3890]
* missing compat exports [#3888]
## [v1.8.1](https://github.com/flarum/framework/compare/v1.8.0...v1.8.1)
### Fixed
* recover temporary solution for html entities in browser title (e72541e35de4f71f9d870bbd9bb46ddf586bdf1d)
* custom contrast color affected by parents (577890d89c593ae5b6cb96083fab69e2f1ae600c)
* reply placeholder wrong positioning (253a3d281dbf5ce3fa712b629b80587cf67e7dbe)
* (mentions) missed post mentions UI changes with lazy loading [#3832]
* (mentions) cannot use newly introduced mentionables extender [#3849]
* (mentions) missing slug from post mention links ([5a4bb7c](5a4bb7ccf226f66dd44816cb69b3d7cfe4ad7f7c))
## [v1.8.0](https://github.com/flarum/framework/compare/v1.7.1...v1.8.0)
### Fixed
- (a11y) reply placeholder not accessible [#3793]
- (bbcode) highlight.js does not work after changing post content [#3817]
- (bbcode) localize quote `wrote` string [#3809]
- (mentions) mentions XHR fired even after mentioning is done [#3806]
- (package-manager) available core updates cause an error in the dashboard ([fab71f2](fab71f2d01fa20ce9b3002833339dc5ea3ea6301))
- (tags) not all tags are loaded in the permission grid [#3804]
- (tags) tag discussion modal filters with exact matches only after first index [#3786]
- (testing) always clear cache in integration test's tearDown [#3818]
- `UserSecurityPage` not exported ([232618a](232618aba604ab003425df38b895208c863d3260))
- `isDark()` utility can receive null value [#3774]
- approving a post does not bump user `comment_count` [#3790]
- circular dependencies disable all involved extensions [#3785]
- color input overflowing the input box [#3796]
- deleting a discussion from the profile does not visually remove it [#3799]
- discussion page showing horizontal scroll on iOS [#3821]
- empty string displayed as SelectDropdown title [#3773]
- filter values are not validated [#3795]
- infinite scroll not initialized for notifications on big screens [#3733]
- notification subject discussion eager loading fails [#3788]
- null as 2nd param in `preg_match` is deprecated [#3801]
- unread count in post stream not visible [#3791]
- unreadable badge icon on certain colors [#3810]
- integrity constraint violation [#3772]
### Changed
- (core,mentions) limit `mentionedBy` post relation results [#3780]
- (likes) limit `likes` relationship results [#3781]
- Change some methods from private to protected, to be able to extend the affected classes [#3802]
- Do not catch exceptions when testing Console commands [#3813]
- drop usage of jquery in `install` and `update` interfaces [#3797]
- extensibility improvements [#3729]
- major frontend JS cleanup [#3609]
- revert ineffective code for encoding of page title [#3768]
- speed up post creation time [#3808]
### Added
- (mentions,tags) tag mentions [#3769]
- add delete own posts permission [#3784]
- add a trait to flush the formatter cache in tests [#3811]
- add user creation to users list page [#3744]
- cli command for enabling or disabling an extension [#3816]
- conditional extenders [#3759]
- provide old content to `Revised` event [#3789]
## [v1.7.1](https://github.com/flarum/framework/compare/v1.7.0...v1.7.1)
### Fixed
- (tags) composer tag selection modal using wrong primary max & min numbers (abc9670659426b765274376945b818b70d84848c)

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7",
"flarum/core": "^1.8",
"flarum/approval": "^1.7"
},
"autoload": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7",
"flarum/core": "^1.8",
"flarum/flags": "^1.7"
},
"autoload": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"extra": {
"branch-alias": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"extra": {
"branch-alias": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"extra": {
"branch-alias": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -78,15 +78,17 @@ return [
->addInclude(['posts.mentionedBy', 'posts.mentionedBy.user', 'posts.mentionedBy.discussion'])
->load([
'posts.mentionsUsers', 'posts.mentionsPosts', 'posts.mentionsPosts.user',
'posts.mentionsGroups'
'posts.mentionsPosts.discussion', 'posts.mentionsGroups'
])
->loadWhere('posts.mentionedBy', [LoadMentionedByRelationship::class, 'mutateRelation'])
->prepareDataForSerialization([LoadMentionedByRelationship::class, 'countRelation']),
(new Extend\ApiController(Controller\ListDiscussionsController::class))
->load([
'firstPost.mentionsUsers', 'firstPost.mentionsPosts', 'firstPost.mentionsPosts.user', 'firstPost.mentionsGroups',
'lastPost.mentionsUsers', 'lastPost.mentionsPosts', 'lastPost.mentionsPosts.user', 'lastPost.mentionsGroups',
'firstPost.mentionsUsers', 'firstPost.mentionsPosts',
'firstPost.mentionsPosts.user', 'firstPost.mentionsPosts.discussion', 'firstPost.mentionsGroups',
'lastPost.mentionsUsers', 'lastPost.mentionsPosts',
'lastPost.mentionsPosts.user', 'lastPost.mentionsPosts.discussion', 'lastPost.mentionsGroups',
]),
(new Extend\ApiController(Controller\ShowPostController::class))
@@ -98,7 +100,7 @@ return [
(new Extend\ApiController(Controller\ListPostsController::class))
->addInclude(['mentionedBy', 'mentionedBy.user', 'mentionedBy.discussion'])
->load(['mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionsGroups'])
->load(['mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionsPosts.discussion', 'mentionsGroups'])
->loadWhere('mentionedBy', [LoadMentionedByRelationship::class, 'mutateRelation'])
->prepareDataForSerialization([LoadMentionedByRelationship::class, 'countRelation']),

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -5,12 +5,9 @@ import TextEditorButton from 'flarum/common/components/TextEditorButton';
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
import MentionFormats from './mentionables/formats/MentionFormats';
import MentionableModels from './mentionables/MentionableModels';
export default function addComposerAutocomplete() {
app.mentionFormats = new MentionFormats();
const $container = $('<div class="ComposerBody-mentionsDropdownContainer"></div>');
const dropdown = new AutocompleteDropdown();

View File

@@ -118,7 +118,7 @@ export default function addMentionedByList() {
});
const limit = 4;
const overLimit = repliers.length > limit;
const overLimit = post.mentionedByCount() > limit;
// Create a list of unique users who have replied. So even if a user has
// replied twice, they will only be in this array once.
@@ -136,7 +136,7 @@ export default function addMentionedByList() {
// others" name to the end of the list. Clicking on it will display a modal
// with a full list of names.
if (overLimit) {
const count = repliers.length - names.length;
const count = post.mentionedByCount() - names.length;
names.push(app.translator.trans('flarum-mentions.forum.post.others_text', { count }));
}

View File

@@ -5,7 +5,7 @@ import type MentionFormat from '../mentionables/formats/MentionFormat';
export default class Mentionables implements IExtender<ForumApplication> {
protected formats: (new () => MentionFormat)[] = [];
protected mentionables: Record<string, (new () => MentionableModel)[]> = {};
protected mentionables: Record<string, (new (...args: any[]) => MentionableModel)[]> = {};
/**
* Register a new mention format.
@@ -26,7 +26,7 @@ export default class Mentionables implements IExtender<ForumApplication> {
* @param mentionable The mentionable instance to register.
* Must extend MentionableModel.
*/
mentionable(symbol: string, mentionable: new () => MentionableModel): this {
mentionable(symbol: string, mentionable: new (...args: any[]) => MentionableModel): this {
if (!this.mentionables[symbol]) {
this.mentionables[symbol] = [];
}

View File

@@ -13,11 +13,14 @@ import addComposerAutocomplete from './addComposerAutocomplete';
import PostMentionedNotification from './components/PostMentionedNotification';
import UserMentionedNotification from './components/UserMentionedNotification';
import GroupMentionedNotification from './components/GroupMentionedNotification';
import MentionFormats from './mentionables/formats/MentionFormats';
import UserPage from 'flarum/forum/components/UserPage';
import LinkButton from 'flarum/common/components/LinkButton';
import User from 'flarum/common/models/User';
import Model from 'flarum/common/Model';
app.mentionFormats = new MentionFormats();
export { default as extend } from './extend';
app.initializers.add('flarum-mentions', function () {

View File

@@ -4,7 +4,7 @@ import TagMention from '../TagMention';
export default class HashMentionFormat extends MentionFormat {
public mentionables: (new (...args: any[]) => MentionableModel)[] = [TagMention];
protected extendable: boolean = false;
protected extendable: boolean = true;
public trigger(): string {
return '#';

View File

@@ -29,7 +29,7 @@ class LoadMentionedByRelationship
$actor = RequestUtil::getActor($request);
return $query
->with(['mentionsPosts', 'mentionsPosts.user', 'mentionsUsers'])
->with(['mentionsPosts', 'mentionsPosts.user', 'mentionsPosts.discussion', 'mentionsUsers'])
->whereVisibleTo($actor)
->oldest()
// Limiting a relationship results is only possible because
@@ -50,6 +50,16 @@ class LoadMentionedByRelationship
$loadable = $data->newCollection($data->posts)->filter(function ($post) {
return $post instanceof Post;
});
// firstPost and lastPost might have been included in the API response,
// so we have to make sure counts are also loaded for them.
if ($data->firstPost) {
$loadable->push($data->firstPost);
}
if ($data->lastPost) {
$loadable->push($data->lastPost);
}
} elseif ($data instanceof Collection) {
$loadable = $data;
} elseif ($data instanceof Post) {

View File

@@ -9,6 +9,8 @@
namespace Flarum\Mentions\Formatter;
use Flarum\Discussion\Discussion;
use Flarum\Http\SlugManager;
use Psr\Http\Message\ServerRequestInterface as Request;
use s9e\TextFormatter\Renderer;
use s9e\TextFormatter\Utils;
@@ -21,9 +23,15 @@ class FormatPostMentions
*/
private $translator;
public function __construct(TranslatorInterface $translator)
/**
* @var SlugManager
*/
private $slugManager;
public function __construct(TranslatorInterface $translator, SlugManager $slugManager)
{
$this->translator = $translator;
$this->slugManager = $slugManager;
}
/**
@@ -56,6 +64,12 @@ class FormatPostMentions
$attributes['displayname'] = $this->translator->trans('core.lib.username.deleted_text');
}
if ($post) {
$attributes['discussionid'] = $this->slugManager
->forResource(Discussion::class)
->toSlug($post->discussion);
}
return $attributes;
});
}

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -22,7 +22,7 @@
"source": "https://github.com/flarum/package-manager"
},
"require": {
"flarum/core": "^1.5.0",
"flarum/core": "^1.8",
"composer/composer": "^2.3"
},
"require-dev": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7",
"flarum/core": "^1.8",
"pusher/pusher-php-server": "^2.2"
},
"require-dev": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -25,4 +25,11 @@ class UserPolicy extends AbstractPolicy
return $this->deny();
}
}
public function uploadAvatar(User $actor, User $user)
{
if ($actor->suspended_until && $actor->suspended_until->isFuture()) {
return $this->deny();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -0,0 +1,103 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Suspend\Tests\integration\api\users;
use Carbon\Carbon;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Laminas\Diactoros\UploadedFile;
use Psr\Http\Message\ResponseInterface;
class UploadAvatarTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-suspend');
$this->prepareDatabase([
'users' => [
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
$this->normalUser(),
['id' => 3, 'username' => 'acme', 'email' => 'acme@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->addDay(), 'suspend_message' => 'You have been suspended.', 'suspend_reason' => 'Suspended for acme reasons.'],
['id' => 4, 'username' => 'acme4', 'email' => 'acme4@machine.local', 'is_email_confirmed' => 1],
['id' => 5, 'username' => 'acme5', 'email' => 'acme5@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->subDay(), 'suspend_message' => 'You have been suspended.', 'suspend_reason' => 'Suspended for acme reasons.'],
],
'groups' => [
['id' => 5, 'name_singular' => 'can_edit_users', 'name_plural' => 'can_edit_users', 'is_hidden' => 0]
],
'group_user' => [
['user_id' => 2, 'group_id' => 5]
],
'group_permission' => [
['permission' => 'user.edit', 'group_id' => 5],
]
]);
}
/**
* @dataProvider allowedToUploadAvatar
* @test
*/
public function can_suspend_user_if_allowed(?int $authenticatedAs, int $targetUserId, string $message)
{
$response = $this->sendUploadAvatarRequest($authenticatedAs, $targetUserId);
$this->assertEquals(200, $response->getStatusCode(), $response->getBody()->getContents());
}
/**
* @dataProvider unallowedToUploadAvatar
* @test
*/
public function cannot_suspend_user_if_not_allowed(?int $authenticatedAs, int $targetUserId, string $message)
{
$response = $this->sendUploadAvatarRequest($authenticatedAs, $targetUserId);
$this->assertEquals(403, $response->getStatusCode(), $response->getBody()->getContents());
}
public function allowedToUploadAvatar(): array
{
return [
[1, 2, 'Admin can upload avatar for any user'],
[2, 3, 'User with permission can upload avatar for suspended user'],
[2, 2, 'User with permission can upload avatar for self'],
[2, 4, 'User with permission can upload avatar for other user'],
[1, 1, 'Admin can upload avatar for self'],
[5, 5, 'Suspended user can upload avatar for self if suspension expired'],
];
}
public function unallowedToUploadAvatar(): array
{
return [
[3, 3, 'Suspended user cannot upload avatar for self'],
[3, 2, 'Suspended user cannot upload avatar for other user'],
[4, 3, 'User without permission cannot upload avatar for suspended user'],
[4, 2, 'User without permission cannot upload avatar for other user'],
[5, 2, 'Suspended user cannot upload avatar for other user if suspension expired'],
];
}
protected function sendUploadAvatarRequest(?int $authenticatedAs, int $targetUserId): ResponseInterface
{
return $this->send(
$this->request('POST', "/api/users/$targetUserId/avatar", [
'authenticatedAs' => $authenticatedAs,
])->withHeader('Content-Type', 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW')->withUploadedFiles([
'avatar' => new UploadedFile(__DIR__.'/../../../fixtures/avatar.png', 0, UPLOAD_ERR_OK, 'avatar.png', 'image/png')
])
);
}
}

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.7"
"flarum/core": "^1.8"
},
"autoload": {
"psr-4": {

View File

@@ -122,6 +122,7 @@ declare const _default: {
'components/TextEditorButton': typeof import("../common/components/TextEditorButton").default;
'components/Tooltip': typeof import("../common/components/Tooltip").default;
'components/EditUserModal': typeof import("../common/components/EditUserModal").default;
'components/LabelValue': typeof import("../common/components/LabelValue").default;
Model: typeof import("../common/Model").default;
Application: typeof import("../common/Application").default;
'helpers/fullTime': typeof import("../common/helpers/fullTime").default;

View File

@@ -86,6 +86,7 @@ import isObject from './utils/isObject';
import AlertManagerState from './states/AlertManagerState';
import ModalManagerState from './states/ModalManagerState';
import PageState from './states/PageState';
import LabelValue from './components/LabelValue';
declare const _default: {
extenders: {
Model: typeof import("./extenders/Model").default;
@@ -174,6 +175,7 @@ declare const _default: {
'components/TextEditorButton': typeof TextEditorButton;
'components/Tooltip': typeof Tooltip;
'components/EditUserModal': typeof EditUserModal;
'components/LabelValue': typeof LabelValue;
Model: typeof Model;
Application: typeof Application;
'helpers/fullTime': typeof fullTime;

View File

@@ -1 +1 @@
export default function textContrastClass(hexcolor: string | null): string;
export default function textContrastClass(hexcolor: string | null | undefined): string;

View File

@@ -71,6 +71,7 @@ import BasicEditorDriver from '../common/utils/BasicEditorDriver';
import routes from './routes';
import ForumApplication from './ForumApplication';
import isSafariMobile from './utils/isSafariMobile';
import AccessTokensList from './components/AccessTokensList';
declare const _default: {
extenders: {
Model: typeof import("../common/extenders/Model").default;
@@ -159,6 +160,7 @@ declare const _default: {
'components/TextEditorButton': typeof import("../common/components/TextEditorButton").default;
'components/Tooltip': typeof import("../common/components/Tooltip").default;
'components/EditUserModal': typeof import("../common/components/EditUserModal").default;
'components/LabelValue': typeof import("../common/components/LabelValue").default;
Model: typeof import("../common/Model").default;
Application: typeof import("../common/Application").default;
'helpers/fullTime': typeof import("../common/helpers/fullTime").default;
@@ -276,6 +278,7 @@ declare const _default: {
'components/DiscussionListItem': typeof DiscussionListItem;
'components/LoadingPost': typeof LoadingPost;
'components/PostsUserPage': typeof PostsUserPage;
'components/AccessTokensList': typeof AccessTokensList;
'resolvers/DiscussionPageResolver': typeof DiscussionPageResolver;
routes: typeof routes;
ForumApplication: typeof ForumApplication;

View File

@@ -72,7 +72,7 @@ export default class AvatarEditor extends Component<import("../../common/Compone
remove(): void;
/**
* After a successful upload/removal, push the updated user data into the
* store, and force a recomputation of the user's avatar color.
* store, and force a re-computation of the user's avatar color.
*
* @param {object} response
* @protected

2
framework/core/js/dist/admin.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
framework/core/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -411,12 +411,23 @@ export default class Application {
pageNumber: 1,
};
const title =
let title =
onHomepage || !this.title
? extractText(app.translator.trans('core.lib.meta_titles.without_page_title', params))
: extractText(app.translator.trans('core.lib.meta_titles.with_page_title', params));
document.title = count + title;
title = count + title;
// We pass the title through a DOMParser to allow HTML entities
// to be rendered correctly, while still preventing XSS attacks
// from user input by using a script-disabled environment.
// https://github.com/flarum/framework/issues/3514
// https://github.com/flarum/framework/pull/3684
// This is only a temporary solution for 1.x,
// and the actual source of the issue will be fixed in 2.x
// Actual source of the issue: https://github.com/flarum/framework/issues/3685
const parser = new DOMParser();
document.title = parser.parseFromString(title, 'text/html').body.innerText;
}
protected transformRequestOptions<ResponseType>(flarumOptions: FlarumRequestOptions<ResponseType>): InternalFlarumRequestOptions<ResponseType> {

View File

@@ -90,6 +90,7 @@ import isObject from './utils/isObject';
import AlertManagerState from './states/AlertManagerState';
import ModalManagerState from './states/ModalManagerState';
import PageState from './states/PageState';
import LabelValue from './components/LabelValue';
export default {
extenders,
@@ -167,6 +168,7 @@ export default {
'components/TextEditorButton': TextEditorButton,
'components/Tooltip': Tooltip,
'components/EditUserModal': EditUserModal,
'components/LabelValue': LabelValue,
Model: Model,
Application: Application,
'helpers/fullTime': fullTime,

View File

@@ -28,7 +28,7 @@ export default class Badge<CustomAttrs extends IBadgeAttrs = IBadgeAttrs> extend
view() {
const { type, icon: iconName, label, color, style = {}, ...attrs } = this.attrs;
const className = classList('Badge', [type && `Badge--${type}`], attrs.className, color && textContrastClass(color));
const className = classList('Badge', [type && `Badge--${type}`], attrs.className, textContrastClass(color));
const iconChild = iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust('&nbsp;');

View File

@@ -1,5 +1,7 @@
import isDark from '../utils/isDark';
export default function textContrastClass(hexcolor: string | null): string {
export default function textContrastClass(hexcolor: string | null | undefined): string {
if (!hexcolor) return 'text-contrast--unchanged';
return isDark(hexcolor) ? 'text-contrast--light' : 'text-contrast--dark';
}

View File

@@ -75,6 +75,7 @@ import BasicEditorDriver from '../common/utils/BasicEditorDriver';
import routes from './routes';
import ForumApplication from './ForumApplication';
import isSafariMobile from './utils/isSafariMobile';
import AccessTokensList from './components/AccessTokensList';
export default Object.assign(compat, {
'utils/PostControls': PostControls,
@@ -150,6 +151,7 @@ export default Object.assign(compat, {
'components/DiscussionListItem': DiscussionListItem,
'components/LoadingPost': LoadingPost,
'components/PostsUserPage': PostsUserPage,
'components/AccessTokensList': AccessTokensList,
'resolvers/DiscussionPageResolver': DiscussionPageResolver,
routes: routes,
ForumApplication: ForumApplication,

View File

@@ -204,7 +204,7 @@ export default class AvatarEditor extends Component {
/**
* After a successful upload/removal, push the updated user data into the
* store, and force a recomputation of the user's avatar color.
* store, and force a re-computation of the user's avatar color.
*
* @param {object} response
* @protected

View File

@@ -176,4 +176,10 @@ blockquote ol:last-child {
--contrast-color: var(--text-on-dark);
color: var(--contrast-color);
}
// This exists to prevent inheriting the contrast color from a parent element.
// Like when a badge is inside a tag hero.
&--unchanged {
--contrast-color: var(--unchanged-color);
}
}

View File

@@ -441,7 +441,7 @@
color: var(--muted-color);
border-radius: 10px;
background-color: transparent;
width: 100%;
width: calc(~"100% + 20px * 2");
display: flex;
.Post-header {

View File

@@ -62,7 +62,7 @@ class UploadFaviconController extends UploadImageController
]);
}
$encodedImage = $this->imageManager->make($file->getStream())->resize(64, 64, function ($constraint) {
$encodedImage = $this->imageManager->make($file->getStream()->getMetadata('uri'))->resize(64, 64, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->encode('png');

View File

@@ -38,7 +38,7 @@ class UploadLogoController extends UploadImageController
*/
protected function makeImage(UploadedFileInterface $file): Image
{
$encodedImage = $this->imageManager->make($file->getStream())->heighten(60, function ($constraint) {
$encodedImage = $this->imageManager->make($file->getStream()->getMetadata('uri'))->heighten(60, function ($constraint) {
$constraint->upsize();
})->encode('png');

View File

@@ -21,7 +21,7 @@ class Application
*
* @var string
*/
const VERSION = '1.8.0-dev';
const VERSION = '1.8.2';
/**
* The IoC container for the Flarum application.

View File

@@ -9,7 +9,6 @@
namespace Flarum\Queue;
use Exception;
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling;
use Psr\Log\LoggerInterface;
use Throwable;

View File

@@ -39,4 +39,15 @@ class UserPolicy extends AbstractPolicy
return $this->allow();
}
}
public function uploadAvatar(User $actor, User $user)
{
if ($actor->id === $user->id) {
return $this->allow();
}
if ($actor->id !== $user->id) {
return $actor->can('edit', $user);
}
}
}

View File

@@ -87,7 +87,7 @@ class AvatarValidator extends AbstractValidator
}
try {
$this->imageManager->make($file->getStream());
$this->imageManager->make($file->getStream()->getMetadata('uri'));
} catch (NotReadableException $_e) {
$this->raise('image');
}

View File

@@ -68,13 +68,11 @@ class UploadAvatarHandler
$user = $this->users->findOrFail($command->userId);
if ($actor->id !== $user->id) {
$actor->assertCan('edit', $user);
}
$actor->assertCan('uploadAvatar', $user);
$this->validator->assertValid(['avatar' => $command->file]);
$image = $this->imageManager->make($command->file->getStream());
$image = $this->imageManager->make($command->file->getStream()->getMetadata('uri'));
$this->events->dispatch(
new AvatarSaving($user, $actor, $image)

View File

@@ -1,6 +1,6 @@
{
"name": "flarum-webpack-config",
"version": "2.0.1",
"version": "2.0.2",
"description": "Webpack config for Flarum JS and TS transpilation.",
"main": "index.js",
"author": "Flarum Team",