改进组配置,修复bug

This commit is contained in:
Wisp X
2022-01-17 22:45:18 +08:00
parent 9718871610
commit 82ec6c6ac6
16 changed files with 131 additions and 39 deletions
-3
View File
@@ -31,9 +31,6 @@ final class ConfigKey
/** @var string 账户是否需要验证 */
const IsUserNeedVerify = 'is_user_need_verify';
/** @var string 是否启用缩略图功能 */
const IsEnableThumbnail = 'is_enable_thumbnail';
/** @var string 邮件配置 */
const MailConfigs = 'mail_configs';
+10 -1
View File
@@ -11,7 +11,16 @@ final class GroupConfigKey
const ConcurrentUploadNum = 'concurrent_upload_num';
/** @var string 上传是否需要审查 */
const IsUploadNeedsReview = 'is_upload_needs_review';
const IsEnableReview = 'is_enable_review';
/** @var string 是否启用原图保护功能 */
const IsEnableOriginalProtection = 'is_enable_original_protection';
/** @var string 上传是否启用水印功能 */
const IsEnableWatermark = 'is_enable_watermark';
/** @var string 水印配置 */
const WatermarkConfigs = 'watermark_configs';
/** @var string 每分钟上传限制 */
const LimitPerMinute = 'limit_per_minute';
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace App\Enums;
final class GroupWatermarkConfigKey
{
}
-3
View File
@@ -15,7 +15,4 @@ final class KodoOption
/** @var string Bucket */
const Bucket = 'bucket';
/** @var string 是否启用获取原始 url 功能 */
const IsEnableOriginalProtection = 'is_enable_origin_url';
}
-3
View File
@@ -9,7 +9,4 @@ final class LocalOption
/** @var string 根目录 */
const Root = 'root';
/** @var string 是否启用原图保护功能 */
const IsEnableOriginalProtection = 'is_enable_original_protection';
}
+11 -1
View File
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\User;
use App\Enums\GroupConfigKey;
use App\Enums\ImagePermission;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageRenameRequest;
@@ -30,7 +31,7 @@ class ImageController extends Controller
/** @var User $user */
$user = Auth::user();
$images = Image::with('strategy')
$images = Image::with('group')
->where('user_id', $user->id)
->when($request->query('order') ?: 'newest', function (Builder $builder, $order) {
switch ($order) {
@@ -93,14 +94,23 @@ class ImageController extends Controller
{
/** @var Image $image */
$image = Image::query()
->with('group')
->where('key', $request->route('key'))
->where('extension', $request->route('extension'))
->firstOr(fn() => abort(404));
if (! $image->group->configs->get(GroupConfigKey::IsEnableOriginalProtection)) {
abort(404);
}
try {
$contents = $image->filesystem()->read($image->pathname);
} catch (FilesystemException $e) {
abort(404);
}
// 是否启用了水印功能
if ($image->group->configs->get(GroupConfigKey::IsEnableWatermark)) {
// GroupConfigKey::WatermarkConfigs
// TODO 动态生成水印并缓存
}
return \response()->stream(function () use ($contents) {
echo $contents;
}, headers: ['Content-type' => $image->mimetype]);
+3 -13
View File
@@ -2,7 +2,9 @@
namespace App\Models;
use App\Enums\ConfigKey;
use App\Enums\GroupConfigKey;
use App\Utils;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@@ -41,19 +43,7 @@ class Group extends Model
*/
public static function getDefaultConfigs(): Collection
{
return collect([
GroupConfigKey::MaximumFileSize => 5120,
GroupConfigKey::ConcurrentUploadNum => 3,
GroupConfigKey::IsUploadNeedsReview => false,
GroupConfigKey::LimitPerMinute => 20,
GroupConfigKey::LimitPerHour => 100,
GroupConfigKey::LimitPerDay => 300,
GroupConfigKey::LimitPerWeek => 600,
GroupConfigKey::LimitPerMonth => 999,
GroupConfigKey::AcceptedFileSuffixes => ['jpg', 'jpeg', 'gif', 'png', 'apng', 'bmp', 'ico'],
GroupConfigKey::PathNamingRule => '{Y}/{m}/{d}',
GroupConfigKey::FileNamingRule => '{uniqid}',
]);
return Utils::config(ConfigKey::GuestGroupConfigs);
}
protected static function booted()
+19 -3
View File
@@ -2,7 +2,9 @@
namespace App\Models;
use App\Enums\GroupConfigKey;
use App\Enums\Strategy\LocalOption;
use App\Enums\StrategyKey;
use App\Service\ImageService;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
@@ -18,6 +20,7 @@ use League\Flysystem\Filesystem;
* @property int $id
* @property int $user_id
* @property int $album_id
* @property int $group_id
* @property int $strategy_id
* @property string $key
* @property string $path
@@ -43,6 +46,7 @@ use League\Flysystem\Filesystem;
* @property Carbon $created_at
* @property-read User $user
* @property-read Album $album
* @property-read Group $group
* @property-read Strategy $strategy
*/
class Image extends Model
@@ -70,6 +74,7 @@ class Image extends Model
protected $hidden = [
'user_id',
'album_id',
'group_id',
'strategy_id',
'is_unhealthy',
'permission',
@@ -120,10 +125,10 @@ class Image extends Model
return Storage::disk('uploads')->url($this->pathname);
}
// 是否启用原图保护功能
if ($this->strategy->configs->get(LocalOption::IsEnableOriginalProtection)) {
if ($this->group->configs->get(GroupConfigKey::IsEnableOriginalProtection)) {
return asset("{$this->key}.{$this->extension}");
} else {
return rtrim($this->strategy->configs->get(LocalOption::Domain), '/').'/'.$this->pathname;
return rtrim($this->strategy->configs->get('domain'), '/').'/'.$this->pathname;
}
});
}
@@ -162,9 +167,20 @@ class Image extends Model
return $this->belongsTo(Album::class, 'album_id', 'id');
}
public function group(): BelongsTo
{
return $this->belongsTo(Group::class, 'group_id', 'id')->withDefault(function (Group $group) {
$group->name = '系统默认组';
$group->configs = $group::getDefaultConfigs();
});
}
public function strategy(): BelongsTo
{
return $this->belongsTo(Strategy::class, 'strategy_id', 'id');
return $this->belongsTo(Strategy::class, 'strategy_id', 'id')->withDefault(function (Strategy $strategy) {
$strategy->key = StrategyKey::Local;
$strategy->configs = collect([LocalOption::Root => config('filesystems.disks.uploads.root')]);
});
}
private function generateKey($length = 6): string
-1
View File
@@ -51,7 +51,6 @@ class Strategy extends Model
static::creating(function (self $strategy) {
$strategy->configs = collect([
LocalOption::Domain => env('APP_URL'),
LocalOption::IsEnableOriginalProtection => true,
]);
});
}
+8 -5
View File
@@ -24,11 +24,15 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image as InterventionImage;
use Intervention\Image\Gd\Font;
use Intervention\Image\ImageManager;
use JetBrains\PhpStorm\NoReturn;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemAdapter;
use League\Flysystem\FilesystemException;
use League\Flysystem\Local\LocalFilesystemAdapter;
use Overtrue\Flysystem\Qiniu\QiniuAdapter;
use Psr\Http\Message\StreamInterface;
class ImageService
{
@@ -68,6 +72,7 @@ class ImageService
// 如果该用户有角色组,覆盖默认组、上传策略配置
if ($user->group) {
$image->group_id = $user->group_id;
$configs = $user->group->configs;
// 获取策略列表,根据用户所选的策略上传
$strategies = $user->group->strategies()->get();
@@ -155,15 +160,13 @@ class ImageService
$builder->where('strategy_id', $id);
})->where('md5', $image->md5)->where('sha1', $image->sha1)->first();
if (is_null($existing)) {
$handle = fopen($file, 'r');
$handle = $img->stream();
try {
$filesystem->writeStream($pathname, $handle);
$filesystem->writeStream($pathname, $handle->detach());
} catch (FilesystemException $e) {
throw new UploadException('图片上传失败');
}
if (! fclose($handle)) {
throw new UploadException('资源关闭失败');
}
$handle->close();
} else {
$image->fill($existing->only('path', 'name'));
}
-1
View File
@@ -27,7 +27,6 @@ class Utils
case ConfigKey::IsEnableGallery:
case ConfigKey::IsEnableRegistration:
case ConfigKey::IsUserNeedVerify:
case ConfigKey::IsEnableThumbnail:
$value = (bool) $value;
break;
case ConfigKey::MailConfigs:
+2 -1
View File
@@ -13,7 +13,8 @@
"laravel/framework": "^9.0",
"laravel/sanctum": "^2.14",
"laravel/tinker": "^2.7",
"overtrue/flysystem-qiniu": "^2.0"
"overtrue/flysystem-qiniu": "^2.0",
"topthink/think-image": "^1.0"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.6",
Generated
+51 -1
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": "c36bb3f58e9cf016cf72e03a16057222",
"content-hash": "afa63033085cb52b18c21975da51c685",
"packages": [
{
"name": "asm89/stack-cors",
@@ -5577,6 +5577,56 @@
},
"time": "2021-12-08T09:12:39+00:00"
},
{
"name": "topthink/think-image",
"version": "v1.0.7",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-image.git",
"reference": "8586cf47f117481c6d415b20f7dedf62e79d5512"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-image/zipball/8586cf47f117481c6d415b20f7dedf62e79d5512",
"reference": "8586cf47f117481c6d415b20f7dedf62e79d5512",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-gd": "*"
},
"require-dev": {
"phpunit/phpunit": "4.8.*",
"topthink/framework": "^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"think\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"description": "The ThinkPHP5 Image Package",
"support": {
"issues": "https://github.com/top-think/think-image/issues",
"source": "https://github.com/top-think/think-image/tree/master"
},
"time": "2016-09-29T06:05:43+00:00"
},
{
"name": "vlucas/phpdotenv",
"version": "v5.4.1",
@@ -21,6 +21,7 @@ class CreateImagesTable extends Migration
$table->id();
$table->foreignId('user_id')->nullable()->comment('用户')->constrained('users')->onDelete('set null');
$table->foreignId('album_id')->nullable()->comment('相册')->constrained('albums')->onDelete('set null');
$table->foreignId('group_id')->nullable()->comment('角色组')->constrained('groups')->onDelete('set null');
$table->foreignId('strategy_id')->nullable()->comment('策略')->constrained('strategies')->onDelete('set null');
$table->string('key')->unique()->comment('key');
$table->string('path')->comment('保存路径');
+17 -2
View File
@@ -3,6 +3,7 @@
namespace Database\Seeders;
use App\Enums\ConfigKey;
use App\Enums\GroupConfigKey;
use App\Enums\Mail\SmtpOption;
use App\Models\Group;
use Illuminate\Database\Seeder;
@@ -29,7 +30,6 @@ class DatabaseSeeder extends Seeder
ConfigKey::IsAllowGuestUpload => 1,
ConfigKey::UserInitialCapacity => 512000,
ConfigKey::IsUserNeedVerify => 1,
ConfigKey::IsEnableThumbnail => 1,
ConfigKey::MailConfigs => json_encode([
'default' => 'smtp',
'mailers' => [
@@ -42,7 +42,22 @@ class DatabaseSeeder extends Seeder
SmtpOption::AuthMode => null,
],
]),
ConfigKey::GuestGroupConfigs => Group::getDefaultConfigs()->toJson(),
ConfigKey::GuestGroupConfigs => collect([
GroupConfigKey::MaximumFileSize => 5120,
GroupConfigKey::ConcurrentUploadNum => 3,
GroupConfigKey::IsEnableReview => false,
GroupConfigKey::IsEnableWatermark => false,
GroupConfigKey::IsEnableOriginalProtection => false,
GroupConfigKey::WatermarkConfigs => new \stdClass(),
GroupConfigKey::LimitPerMinute => 20,
GroupConfigKey::LimitPerHour => 100,
GroupConfigKey::LimitPerDay => 300,
GroupConfigKey::LimitPerWeek => 600,
GroupConfigKey::LimitPerMonth => 999,
GroupConfigKey::AcceptedFileSuffixes => ['jpg', 'jpeg', 'gif', 'png', 'apng', 'bmp', 'ico'],
GroupConfigKey::PathNamingRule => '{Y}/{m}/{d}',
GroupConfigKey::FileNamingRule => '{uniqid}',
])->toJson(),
])->transform(function ($value, $key) use ($date) {
return ['name' => $key, 'value' => $value, 'updated_at' => $date, 'created_at' => $date];
})->values()->toArray();
+1 -1
View File
@@ -723,7 +723,7 @@
},
open: {
text: '新窗口打开',
action: e => window.open($(e).find('img').attr('src')),
action: e => window.open($(e).data('json').url),
visible: () => ds.getSelection().length === 1,
},
copies: {