Introduce filament

This commit is contained in:
xiaomlove
2022-06-27 01:39:01 +08:00
parent aae45835ee
commit 1aca20070d
92 changed files with 3535 additions and 83 deletions
+81
View File
@@ -0,0 +1,81 @@
<?php
namespace App\Auth;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Http\Request;
class NexusWebGuard implements Guard
{
use GuardHelpers;
/**
* The request instance.
*
* @var \Illuminate\Http\Request
*/
protected $request;
/**
* Create a new authentication guard.
*
* @param callable $callback
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Contracts\Auth\UserProvider|null $provider
* @return void
*/
public function __construct(Request $request, UserProvider $provider = null)
{
$this->request = $request;
$this->provider = $provider;
}
/**
* Get the currently authenticated user.
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
if (! is_null($this->user)) {
return $this->user;
}
return $this->user = $this->provider->retrieveByCredentials($this->request->cookie());
}
/**
* Validate a user's credentials.
*
* @param array $credentials
* @return bool
*/
public function validate(array $credentials = [])
{
$required = ['c_secure_pass', 'c_secure_uid', 'c_secure_login'];
foreach ($required as $value) {
if (empty($credentials[$value])) {
return false;
}
}
$b_id = base64($credentials["c_secure_uid"],false);
$id = intval($b_id ?? 0);
if (!$id || !is_valid_id($id) || strlen($credentials["c_secure_pass"]) != 32) {
return false;
}
if ($this->provider->retrieveById($id)) {
return true;
}
return false;
}
public function logout()
{
logoutcookie();
return nexus_redirect('login.php');
}
}
+91
View File
@@ -0,0 +1,91 @@
<?php
namespace App\Auth;
use App\Models\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
class NexusWebUserProvider implements UserProvider
{
/**
* @var \Illuminate\Database\Eloquent\Builder
*/
protected $query;
public function __construct()
{
$this->query = User::query();
}
/**
* Retrieve a user by their unique identifier.
*
* @param mixed $identifier
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier)
{
return $this->query->find($identifier);
}
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* @param mixed $identifier
* @param string $token
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByToken($identifier, $token)
{
}
/**
* Update the "remember me" token for the given user in storage.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param string $token
* @return void
*/
public function updateRememberToken(Authenticatable $user, $token)
{
}
/**
* Retrieve a user by the given credentials.
*
* @param array $credentials
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials)
{
if (!empty($credentials['c_secure_uid'])) {
$b_id = base64($credentials["c_secure_uid"],false);
return $this->query->find($b_id);
}
}
/**
* Validate a user against the given credentials.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param array $credentials
* @return bool
*/
public function validateCredentials(Authenticatable $user, array $credentials)
{
if ($credentials["c_secure_login"] == base64("yeah")) {
if ($credentials["c_secure_pass"] != md5($user->passhash . $_SERVER["REMOTE_ADDR"])) {
return false;
}
} else {
if ($credentials["c_secure_pass"] !== md5($user->passhash)) {
return false;
}
}
return true;
}
}
+4 -7
View File
@@ -78,13 +78,10 @@ class Test extends Command
*/
public function handle()
{
$a = 2;
$b = 2;
if ($a != 1 && $b == 2) {
echo "OK";
} else {
echo 'Bad';
}
$r = 'MTAwNDI%3D';
$r = 'MTAwNDI%3D';
$r = 'MTAwMDM%3D';
dd(base64_decode($r));
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Filament;
trait NexusOptionsTrait
{
private static array $matchTypes = ['dec' => 'dec', 'hex' => 'hex'];
private static array $yesOrNo = ['yes' => 'yes', 'no' => 'no'];
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace App\Filament;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Database\Eloquent\Model;
class PageList extends ListRecords
{
protected ?string $maxContentWidth = 'full';
protected function getTableRecordUrlUsing(): ?\Closure
{
return function (Model $record): ?string {
return null;
};
}
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace App\Filament\Pages;
class Dashboard extends \Filament\Pages\Dashboard
{
protected ?string $maxContentWidth = 'full';
}
@@ -0,0 +1,90 @@
<?php
namespace App\Filament\Resources\System;
use App\Filament\NexusOptionsTrait;
use App\Filament\Resources\System\AgentAllowResource\Pages;
use App\Filament\Resources\System\AgentAllowResource\RelationManagers;
use App\Models\AgentAllow;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class AgentAllowResource extends Resource
{
use NexusOptionsTrait;
protected static ?string $model = AgentAllow::class;
protected static ?string $navigationIcon = 'heroicon-o-check';
protected static ?string $navigationGroup = 'System';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.agent_allows');
}
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('family')->required(),
Forms\Components\TextInput::make('start_name')->required(),
Forms\Components\TextInput::make('peer_id_start')->required(),
Forms\Components\TextInput::make('peer_id_pattern')->required(),
Forms\Components\Radio::make('peer_id_matchtype')->options(self::$matchTypes)->required(),
Forms\Components\TextInput::make('peer_id_match_num')->integer()->required(),
Forms\Components\TextInput::make('agent_start')->required(),
Forms\Components\TextInput::make('agent_pattern')->required(),
Forms\Components\Radio::make('agent_matchtype')->options(self::$matchTypes)->required(),
Forms\Components\TextInput::make('agent_match_num')->required(),
Forms\Components\Radio::make('exception')->options(self::$yesOrNo)->required(),
Forms\Components\Radio::make('allowhttps')->options(self::$yesOrNo)->required(),
Forms\Components\Textarea::make('comment'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('family')->searchable(),
Tables\Columns\TextColumn::make('start_name')->searchable(),
Tables\Columns\TextColumn::make('peer_id_start'),
Tables\Columns\TextColumn::make('agent_start'),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
RelationManagers\DeniesRelationManager::class,
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListAgentAllows::route('/'),
'create' => Pages\CreateAgentAllow::route('/create'),
'edit' => Pages\EditAgentAllow::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\System\AgentAllowResource\Pages;
use App\Filament\Resources\System\AgentAllowResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateAgentAllow extends CreateRecord
{
protected static string $resource = AgentAllowResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\System\AgentAllowResource\Pages;
use App\Filament\Resources\System\AgentAllowResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditAgentAllow extends EditRecord
{
protected static string $resource = AgentAllowResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\System\AgentAllowResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\System\AgentAllowResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListAgentAllows extends PageList
{
protected static string $resource = AgentAllowResource::class;
protected function getActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,52 @@
<?php
namespace App\Filament\Resources\System\AgentAllowResource\RelationManagers;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class DeniesRelationManager extends RelationManager
{
protected static string $relationship = 'denies';
protected static ?string $recordTitleAttribute = 'name';
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required()->maxLength(255),
Forms\Components\TextInput::make('peer_id')->required()->maxLength(255),
Forms\Components\TextInput::make('agent')->required()->maxLength(255),
Forms\Components\Textarea::make('comment'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('peer_id'),
Tables\Columns\TextColumn::make('agent'),
])
->filters([
//
])
->headerActions([
Tables\Actions\CreateAction::make(),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
}
@@ -0,0 +1,78 @@
<?php
namespace App\Filament\Resources\System;
use App\Filament\Resources\System\AgentDenyResource\Pages;
use App\Filament\Resources\System\AgentDenyResource\RelationManagers;
use App\Models\AgentDeny;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class AgentDenyResource extends Resource
{
protected static ?string $model = AgentDeny::class;
protected static ?string $navigationIcon = 'heroicon-o-ban';
protected static ?string $navigationGroup = 'System';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.agent_denies');
}
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('family_id')->label('Allow family')
->relationship('family', 'family')->required(),
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('peer_id')->required(),
Forms\Components\TextInput::make('agent')->required(),
Forms\Components\Textarea::make('comment'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('family.family')->label('Family'),
Tables\Columns\TextColumn::make('name')->searchable(),
Tables\Columns\TextColumn::make('peer_id')->searchable(),
Tables\Columns\TextColumn::make('agent')->searchable(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListAgentDenies::route('/'),
'create' => Pages\CreateAgentDeny::route('/create'),
'edit' => Pages\EditAgentDeny::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\System\AgentDenyResource\Pages;
use App\Filament\Resources\System\AgentDenyResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateAgentDeny extends CreateRecord
{
protected static string $resource = AgentDenyResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\System\AgentDenyResource\Pages;
use App\Filament\Resources\System\AgentDenyResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditAgentDeny extends EditRecord
{
protected static string $resource = AgentDenyResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\System\AgentDenyResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\System\AgentDenyResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListAgentDenies extends PageList
{
protected static string $resource = AgentDenyResource::class;
protected function getActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,102 @@
<?php
namespace App\Filament\Resources\System;
use App\Filament\Resources\System\ExamResource\Pages;
use App\Filament\Resources\System\ExamResource\RelationManagers;
use App\Models\Exam;
use App\Repositories\UserRepository;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class ExamResource extends Resource
{
protected static ?string $model = Exam::class;
protected static ?string $navigationIcon = 'heroicon-o-exclamation';
protected static ?string $navigationGroup = 'System';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.exams_list');
}
public static function form(Form $form): Form
{
$userRep = new UserRepository();
return $form
->schema([
Forms\Components\Section::make('Base info')->schema([
Forms\Components\TextInput::make('name')->required()->columnSpan(['sm' => 2]),
Forms\Components\TextInput::make('priority')->columnSpan(['sm' => 2])->helperText('The higher the value, the higher the priority, and when multiple exam match the same user, the one with the highest priority is assigned.'),
Forms\Components\Radio::make('status')->options(['0' => 'Enabled', '1' => 'Disabled'])->inline()->columnSpan(['sm' => 2]),
Forms\Components\Radio::make('is_discovered')->options(['0' => 'No', '1' => 'Yes'])->label('Discovered')->inline()->columnSpan(['sm' => 2]),
])->columns(2),
Forms\Components\Section::make('Time')->schema([
Forms\Components\DateTimePicker::make('begin'),
Forms\Components\DateTimePicker::make('end'),
Forms\Components\TextInput::make('duration')->integer()->columnSpan(['sm' => 2])
->helperText('Unit: days. When assign to user, begin and end are used if they are specified. Otherwise begin time is the time at assignment, and the end time is the time at assignment plus the duration.'),
])->columns(2),
Forms\Components\Section::make('Select user')->schema([
Forms\Components\CheckboxList::make('filters.classes')->options($userRep->listClass())->columnSpan(['sm' => 2])->columns(4)->label('Classes'),
Forms\Components\DateTimePicker::make('filters.register_time_range.0')->label('Register time begin'),
Forms\Components\DateTimePicker::make('filters.register_time_range.1')->label('Register time end'),
Forms\Components\Toggle::make('filters.donate_status')->label('Donated'),
])->columns(2),
Forms\Components\Textarea::make('description')->columnSpan(['sm' => 2]),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('indexFormatted')->label('Indexes')->html(),
Tables\Columns\TextColumn::make('begin'),
Tables\Columns\TextColumn::make('end'),
Tables\Columns\TextColumn::make('durationText')->label('Duration'),
Tables\Columns\TextColumn::make('filterFormatted')->label('Target users')->html(),
Tables\Columns\BooleanColumn::make('is_discovered')->label('Discovered'),
Tables\Columns\TextColumn::make('priority')->label('Priority'),
Tables\Columns\TextColumn::make('statusText')->label('Status'),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListExams::route('/'),
'create' => Pages\CreateExam::route('/create'),
'edit' => Pages\EditExam::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\System\ExamResource\Pages;
use App\Filament\Resources\System\ExamResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateExam extends CreateRecord
{
protected static string $resource = ExamResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\System\ExamResource\Pages;
use App\Filament\Resources\System\ExamResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditExam extends EditRecord
{
protected static string $resource = ExamResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\System\ExamResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\System\ExamResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListExams extends PageList
{
protected static string $resource = ExamResource::class;
protected function getActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,81 @@
<?php
namespace App\Filament\Resources\System;
use App\Filament\Resources\System\MedalResource\Pages;
use App\Filament\Resources\System\MedalResource\RelationManagers;
use App\Models\Medal;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class MedalResource extends Resource
{
protected static ?string $model = Medal::class;
protected static ?string $navigationIcon = 'heroicon-o-badge-check';
protected static ?string $navigationGroup = 'System';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.medals_list');
}
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('price')->required()->integer(),
Forms\Components\TextInput::make('image_large')->required(),
Forms\Components\TextInput::make('image_small')->required(),
Forms\Components\Radio::make('get_type')->options(Medal::listGetTypes(true))->inline()->columnSpan(['sm' => 2])->required(),
Forms\Components\TextInput::make('duration')->integer()->columnSpan(['sm' => 2])->helperText('Unit: day, if empty, belongs to user forever.'),
Forms\Components\Textarea::make('description')->columnSpan(['sm' => 2]),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name'),
Tables\Columns\ImageColumn::make('image_large')->height(120),
Tables\Columns\ImageColumn::make('image_small')->height(120),
Tables\Columns\TextColumn::make('getTypeText')->label('Get type'),
Tables\Columns\TextColumn::make('price'),
Tables\Columns\TextColumn::make('duration'),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListMedals::route('/'),
'create' => Pages\CreateMedal::route('/create'),
'edit' => Pages\EditMedal::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\System\MedalResource\Pages;
use App\Filament\Resources\System\MedalResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateMedal extends CreateRecord
{
protected static string $resource = MedalResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\System\MedalResource\Pages;
use App\Filament\Resources\System\MedalResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditMedal extends EditRecord
{
protected static string $resource = MedalResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\System\MedalResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\System\MedalResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListMedals extends PageList
{
protected static string $resource = MedalResource::class;
protected function getActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,84 @@
<?php
namespace App\Filament\Resources\System;
use App\Filament\NexusOptionsTrait;
use App\Filament\Resources\System\SettingResource\Pages;
use App\Filament\Resources\System\SettingResource\RelationManagers;
use App\Models\Setting;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class SettingResource extends Resource
{
use NexusOptionsTrait;
protected static ?string $model = Setting::class;
protected static ?string $navigationIcon = 'heroicon-o-cog';
protected static ?string $navigationGroup = 'System';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.settings');
}
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required()->disabled()->columnSpan(['sm' => 2]),
Forms\Components\Textarea::make('value')->required()->columnSpan(['sm' => 2])
->afterStateHydrated(function (Forms\Components\Textarea $component, $state) {
$arr = json_decode($state, true);
if (is_array($arr)) {
$component->disabled();
}
})
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name')->searchable(),
Tables\Columns\TextColumn::make('value')->limit(),
Tables\Columns\BadgeColumn::make('autoload')->colors(['success' => 'yes', 'warning' => 'no']),
Tables\Columns\TextColumn::make('updated_at'),
])
->filters([
Tables\Filters\SelectFilter::make('autoload')->options(self::$yesOrNo),
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
// Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListSettings::route('/'),
// 'create' => Pages\CreateSetting::route('/create'),
'edit' => Pages\EditSetting::route('/{record}/edit'),
'hit-and-run' => Pages\EditHitAndRun::route('/hit-and-run'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\System\SettingResource\Pages;
use App\Filament\Resources\System\SettingResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateSetting extends CreateRecord
{
protected static string $resource = SettingResource::class;
}
@@ -0,0 +1,15 @@
<?php
namespace App\Filament\Resources\System\SettingResource\Pages;
use App\Filament\Resources\System\SettingResource;
use Filament\Resources\Pages\Page;
class EditHitAndRun extends Page
{
protected static string $resource = SettingResource::class;
protected static string $view = 'filament.resources.system.setting-resource.pages.edit-hit-and-run';
}
@@ -0,0 +1,33 @@
<?php
namespace App\Filament\Resources\System\SettingResource\Pages;
use App\Filament\Resources\System\SettingResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditSetting extends EditRecord
{
protected static string $resource = SettingResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
protected function getRedirectUrl(): ?string
{
return $this->getResource()::getUrl('index');
}
protected function mutateFormDataBeforeSave(array $data): array
{
$arr = json_decode($data['value'], true);
if (is_array($arr)) {
throw new \LogicException("Not support edit this !");
}
return $data;
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\System\SettingResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\System\SettingResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListSettings extends PageList
{
protected static string $resource = SettingResource::class;
protected function getActions(): array
{
return [
// Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,85 @@
<?php
namespace App\Filament\Resources\Torrent;
use App\Filament\Resources\Torrent\TagResource\Pages;
use App\Filament\Resources\Torrent\TagResource\RelationManagers;
use App\Models\Tag;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class TagResource extends Resource
{
protected static ?string $model = Tag::class;
protected static ?string $navigationIcon = 'heroicon-o-tag';
protected static ?string $navigationGroup = 'Torrent';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.tags_list');
}
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('color')->required()->label('Background color'),
Forms\Components\TextInput::make('font_color')->required(),
Forms\Components\TextInput::make('font_size')->required(),
Forms\Components\TextInput::make('margin')->required(),
Forms\Components\TextInput::make('padding')->required(),
Forms\Components\TextInput::make('border_radius')->required(),
Forms\Components\TextInput::make('priority')->integer(),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('color')->label('Background color'),
Tables\Columns\TextColumn::make('font_color'),
Tables\Columns\TextColumn::make('font_size'),
Tables\Columns\TextColumn::make('margin'),
Tables\Columns\TextColumn::make('padding'),
Tables\Columns\TextColumn::make('border_radius'),
Tables\Columns\TextColumn::make('priority'),
Tables\Columns\TextColumn::make('updated_at')->dateTime('Y-m-d H:i'),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListTags::route('/'),
'create' => Pages\CreateTag::route('/create'),
'edit' => Pages\EditTag::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,13 @@
<?php
namespace App\Filament\Resources\Torrent\TagResource\Pages;
use App\Filament\Resources\Torrent\TagResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateTag extends CreateRecord
{
protected static string $resource = TagResource::class;
}
@@ -0,0 +1,24 @@
<?php
namespace App\Filament\Resources\Torrent\TagResource\Pages;
use App\Filament\Resources\Torrent\TagResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditTag extends EditRecord
{
protected static string $resource = TagResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
protected function getRedirectUrl(): ?string
{
return $this->getResource()::getUrl('index');
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\Torrent\TagResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\Torrent\TagResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListTags extends PageList
{
protected static string $resource = TagResource::class;
protected function getActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,84 @@
<?php
namespace App\Filament\Resources\User;
use App\Filament\Resources\User\ExamUserResource\Pages;
use App\Filament\Resources\User\ExamUserResource\RelationManagers;
use App\Models\ExamUser;
use App\Repositories\ExamRepository;
use App\Repositories\HitAndRunRepository;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
class ExamUserResource extends Resource
{
protected static ?string $model = ExamUser::class;
protected static ?string $navigationIcon = 'heroicon-o-user';
protected static ?string $navigationGroup = 'User';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.exam_users');
}
public static function form(Form $form): Form
{
return $form
->schema([
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('user.username')->label('User')->searchable(),
Tables\Columns\TextColumn::make('exam.name')->label('Exam'),
Tables\Columns\BooleanColumn::make('is_done')->label('Is done'),
Tables\Columns\TextColumn::make('statusText')->label('Status'),
Tables\Columns\TextColumn::make('created_at')->dateTime('Y-m-d H:i'),
])
->filters([
Tables\Filters\SelectFilter::make('status')->options(ExamUser::listStatus(true)),
Tables\Filters\SelectFilter::make('is_done')->options(['0' => 'No', '1' => 'yes']),
])
->actions([
// Tables\Actions\ViewAction::make(),
])
->prependBulkActions([
Tables\Actions\BulkAction::make('Avoid')->action(function (Collection $records) {
$idArr = $records->pluck('id')->toArray();
$rep = new ExamRepository();
$rep->avoidExamUserBulk(['id' => $idArr], Auth::user());
})
->deselectRecordsAfterCompletion()
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListExamUsers::route('/'),
'create' => Pages\CreateExamUser::route('/create'),
'edit' => Pages\EditExamUser::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\User\ExamUserResource\Pages;
use App\Filament\Resources\User\ExamUserResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateExamUser extends CreateRecord
{
protected static string $resource = ExamUserResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\User\ExamUserResource\Pages;
use App\Filament\Resources\User\ExamUserResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditExamUser extends EditRecord
{
protected static string $resource = ExamUserResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\User\ExamUserResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\User\ExamUserResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListExamUsers extends PageList
{
protected static string $resource = ExamUserResource::class;
protected function getActions(): array
{
return [
// Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,91 @@
<?php
namespace App\Filament\Resources\User;
use App\Filament\Resources\User\HitAndRunResource\Pages;
use App\Filament\Resources\User\HitAndRunResource\RelationManagers;
use App\Models\HitAndRun;
use App\Repositories\HitAndRunRepository;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
class HitAndRunResource extends Resource
{
protected static ?string $model = HitAndRun::class;
protected static ?string $navigationIcon = 'heroicon-o-beaker';
protected static ?string $navigationGroup = 'User';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.hit_and_runs');
}
public static function form(Form $form): Form
{
return $form
->schema(Forms\Components\Card::make()->schema([
// Forms\Components\Select::make('user')->relationship('user', 'username')->required(),
// Forms\Components\Select::make('torrent_id')->relationship('torrent', 'name')->required(),
Forms\Components\Radio::make('status')->options(HitAndRun::listStatus(true))->inline()->required(),
// Forms\Components\Select::make('snatch_id')->relationship('snatch', 'uploaded'),
Forms\Components\Textarea::make('comment'),
Forms\Components\DateTimePicker::make('created_at')->displayFormat('Y-m-d H:i:s'),
]));
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('user.username')->searchable(),
Tables\Columns\TextColumn::make('torrent.name')->limit(50),
Tables\Columns\TextColumn::make('snatch.uploadText')->label('Uploaded'),
Tables\Columns\TextColumn::make('snatch.downloadText')->label('Downloaded'),
Tables\Columns\TextColumn::make('snatch.shareRatio')->label('Ratio'),
Tables\Columns\TextColumn::make('seedTimeRequired'),
Tables\Columns\TextColumn::make('inspectTimeLeft'),
Tables\Columns\TextColumn::make('statusText')->label('Status'),
])
->filters([
Tables\Filters\SelectFilter::make('status')->options(HitAndRun::listStatus(true)),
])
->actions([
Tables\Actions\ViewAction::make(),
])
->prependBulkActions([
Tables\Actions\BulkAction::make('Pardon')->action(function (Collection $records) {
$idArr = $records->pluck('id')->toArray();
$rep = new HitAndRunRepository();
$rep->bulkPardon(['id' => $idArr], Auth::user());
})
->deselectRecordsAfterCompletion()
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListHitAndRuns::route('/'),
// 'create' => Pages\CreateHitAndRun::route('/create'),
// 'edit' => Pages\EditHitAndRun::route('/{record}/edit'),
'view' => Pages\ViewHitAndRun::route('/{record}'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\User\HitAndRunResource\Pages;
use App\Filament\Resources\User\HitAndRunResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateHitAndRun extends CreateRecord
{
protected static string $resource = HitAndRunResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\User\HitAndRunResource\Pages;
use App\Filament\Resources\User\HitAndRunResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditHitAndRun extends EditRecord
{
protected static string $resource = HitAndRunResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\User\HitAndRunResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\User\HitAndRunResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListHitAndRuns extends PageList
{
protected static string $resource = HitAndRunResource::class;
protected function getActions(): array
{
return [
// Actions\CreateAction::make(),
];
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Filament\Resources\User\HitAndRunResource\Pages;
use App\Filament\Resources\User\HitAndRunResource;
use App\Models\HitAndRun;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ViewRecord;
use Filament\Forms;
class ViewHitAndRun extends ViewRecord
{
protected static string $resource = HitAndRunResource::class;
protected function getFormSchema(): array
{
return [
Forms\Components\TextInput::make('id'),
Forms\Components\TextInput::make('uid'),
Forms\Components\Radio::make('status')->options(HitAndRun::listStatus(true))->inline(),
Forms\Components\Textarea::make('comment'),
Forms\Components\DateTimePicker::make('created_at'),
];
}
}
@@ -0,0 +1,96 @@
<?php
namespace App\Filament\Resources\User;
use App\Filament\Resources\User\UserResource\Pages;
use App\Filament\Resources\User\UserResource\RelationManagers;
use App\Models\User;
use Filament\Forms;
use Filament\Forms\Components\Grid;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class UserResource extends Resource
{
protected static ?string $model = User::class;
protected static ?string $navigationIcon = 'heroicon-o-users';
protected static ?string $navigationGroup = 'User';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.users_list');
}
public static function form(Form $form): Form
{
return $form
->schema(Forms\Components\Card::make()->schema([
Forms\Components\TextInput::make('username')->required(),
Forms\Components\TextInput::make('email')->required(),
Forms\Components\TextInput::make('password')->password()->required(),
Forms\Components\TextInput::make('password_confirmation')->password()->required()->same('password'),
Forms\Components\TextInput::make('id')->integer(),
Forms\Components\Select::make('class')->options(array_column(User::$classes, 'text')),
]));
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')->sortable(),
Tables\Columns\TextColumn::make('username')->searchable(),
Tables\Columns\TextColumn::make('email')->searchable(),
Tables\Columns\TextColumn::make('class')->label('Class')
->formatStateUsing(fn(Tables\Columns\Column $column) => $column->getRecord()->classText)
->sortable(),
Tables\Columns\TextColumn::make('uploaded')->label('Uploaded')
->formatStateUsing(fn(Tables\Columns\Column $column) => $column->getRecord()->uploadedText)
->sortable(),
Tables\Columns\TextColumn::make('downloaded')->label('Downloaded')
->formatStateUsing(fn(Tables\Columns\Column $column) => $column->getRecord()->downloadedText)
->sortable(),
Tables\Columns\BadgeColumn::make('status')->colors(['success' => 'confirmed', 'warning' => 'pending']),
Tables\Columns\BadgeColumn::make('enabled')->colors(['success' => 'yes', 'danger' => 'no']),
Tables\Columns\TextColumn::make('added')->sortable()->dateTime('Y-m-d H:i'),
Tables\Columns\TextColumn::make('last_access')->dateTime('Y-m-d H:i'),
])
->defaultSort('added', 'desc')
->filters([
Tables\Filters\SelectFilter::make('class')->options(array_column(User::$classes, 'text')),
Tables\Filters\SelectFilter::make('status')->options(['confirmed' => 'confirmed', 'pending' => 'pending']),
Tables\Filters\SelectFilter::make('enabled')->options(['enabled' => 'enabled', 'disabled' => 'disabled']),
])
->actions([
Tables\Actions\ViewAction::make(),
])
->bulkActions([
// Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListUsers::route('/'),
'create' => Pages\CreateUser::route('/create'),
// 'edit' => Pages\EditUser::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Filament\Resources\User\UserResource\Pages;
use App\Filament\Resources\User\UserResource;
use App\Repositories\UserRepository;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Database\Eloquent\Model;
class CreateUser extends CreateRecord
{
protected static string $resource = UserResource::class;
public function create(bool $another = false): void
{
$userRep = new UserRepository();
$data = $this->form->getState();
try {
$this->record = $userRep->store($data);
$this->notify(
'success ',
$this->getCreatedNotificationMessage(),
);
$this->redirect($this->getRedirectUrl());
} catch (\Exception $exception) {
$this->notify(
'danger',
$exception->getMessage(),
);
}
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\User\UserResource\Pages;
use App\Filament\Resources\User\UserResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditUser extends EditRecord
{
protected static string $resource = UserResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Filament\Resources\User\UserResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\User\UserResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Database\Eloquent\Model;
class ListUsers extends PageList
{
protected static string $resource = UserResource::class;
protected function getActions(): array
{
return [
Actions\CreateAction::make(),
];
}
// public function isTableSearchable(): bool
// {
// return true;
// }
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Widgets;
use Filament\Widgets\Widget;
class AccountInfo extends Widget
{
protected static string $view = 'filament.widgets.account-info';
protected int | string | array $columnSpan = 'full';
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Filament\Widgets;
use App\Models\Torrent;
use Closure;
use Filament\Tables;
use Filament\Widgets\TableWidget as BaseWidget;
use Illuminate\Database\Eloquent\Builder;
class LatestTorrents extends BaseWidget
{
protected static ?int $sort = 2;
protected function getTableHeading(): string | Closure | null
{
return __('dashboard.latest_torrent.page_title');
}
protected function isTablePaginationEnabled(): bool
{
return false;
}
protected function getTableQuery(): Builder
{
return Torrent::query()->orderBy('id', 'desc')->limit(5);
}
protected function getTableColumns(): array
{
return [
Tables\Columns\TextColumn::make('name')->limit(40),
Tables\Columns\TextColumn::make('user.username'),
Tables\Columns\TextColumn::make('size')->formatStateUsing(fn ($state) => mksize($state)),
Tables\Columns\TextColumn::make('added')->dateTime(),
];
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Filament\Widgets;
use App\Models\User;
use Closure;
use Filament\Tables;
use Filament\Widgets\TableWidget as BaseWidget;
use Illuminate\Database\Eloquent\Builder;
class LatestUsers extends BaseWidget
{
protected static ?int $sort = 1;
protected function getTableHeading(): string | Closure | null
{
return __('dashboard.latest_user.page_title');
}
protected function isTablePaginationEnabled(): bool
{
return false;
}
protected function getTableQuery(): Builder
{
return User::query()->orderBy('id', 'desc')->limit(5);
}
protected function getTableColumns(): array
{
return [
Tables\Columns\TextColumn::make('username'),
Tables\Columns\TextColumn::make('email'),
Tables\Columns\BadgeColumn::make('status')->colors(['success' => 'confirmed', 'danger' => 'pending']),
Tables\Columns\TextColumn::make('added')->dateTime(),
];
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace App\Filament\Widgets;
use App\Models\Torrent;
use Carbon\Carbon;
use Filament\Widgets\LineChartWidget;
use Flowframe\Trend\Trend;
use Flowframe\Trend\TrendValue;
class TorrentTrend extends LineChartWidget
{
protected static ?int $sort = 4;
protected function getHeading(): ?string
{
return __('dashboard.torrent_trend.page_title');
}
protected function getData(): array
{
$data = Trend::model(Torrent::class)
->dateColumn('added')
->between(
start: now()->subDays(30),
end: now(),
)
->perDay()
->count();
return [
'datasets' => [
[
'label' => 'Torrent',
'data' => $data->map(fn (TrendValue $value) => $value->aggregate),
],
],
'labels' => $data->map(fn (TrendValue $value) => Carbon::parse($value->date)->format('m-d')),
];
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Filament\Widgets;
use App\Models\Torrent;
use App\Models\User;
use Carbon\Carbon;
use Filament\Widgets\LineChartWidget;
use Flowframe\Trend\Trend;
use Flowframe\Trend\TrendValue;
class UserTrend extends LineChartWidget
{
protected static ?int $sort = 3;
protected function getHeading(): ?string
{
return __('dashboard.user_trend.page_title');
}
protected function getData(): array
{
$data = Trend::model(User::class)
->dateColumn('added')
->between(
start: now()->subDays(30),
end: now(),
)
->perDay()
->count();
return [
'datasets' => [
[
'label' => 'User',
'data' => $data->map(fn (TrendValue $value) => $value->aggregate),
],
],
'labels' => $data->map(fn (TrendValue $value) => Carbon::parse($value->date)->format('m-d')),
];
}
}
+1
View File
@@ -58,6 +58,7 @@ class Kernel extends HttpKernel
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.nexus' => \App\Http\Middleware\NexusAuth::class,
'auth.filament' => \Filament\Http\Middleware\Authenticate::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
+6 -1
View File
@@ -12,6 +12,11 @@ class EncryptCookies extends Middleware
* @var array
*/
protected $except = [
//
'c_secure_pass',
'c_secure_uid',
'c_secure_login',
'c_secure_ssl',
'c_secure_tracker_ssl',
];
}
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Filament\Http\Middleware\Authenticate;
class Filament extends Authenticate
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request): string
{
return getSchemeAndHttpHost() . '/login.php';
}
}
+11 -7
View File
@@ -4,6 +4,7 @@ namespace App\Http\Middleware;
use Carbon\Carbon;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\App;
@@ -26,15 +27,18 @@ class Locale
public function handle(Request $request, Closure $next)
{
$user = $request->user();
$language = $user->language;
$locale = self::$languageMaps[$language->site_lang_folder] ?? 'en';
do_log("user: {$user->id}, language: {$language->id}, set locale: $locale");
App::setLocale($locale);
Carbon::setLocale($locale);
if ($user) {
$language = $user->language;
$locale = self::$languageMaps[$language->site_lang_folder] ?? 'en';
do_log("user: {$user->id}, language: {$language->id}, set locale: $locale");
App::setLocale($locale);
Carbon::setLocale($locale);
}
/** @var Response $response */
$response = $next($request);
$response->header('Request-Id', nexus()->getRequestId())->header('Running-In-Octane', RUNNING_IN_OCTANE ? 1 : 0);
if ($response instanceof Response || $response instanceof JsonResponse) {
$response->header('Request-Id', nexus()->getRequestId())->header('Running-In-Octane', RUNNING_IN_OCTANE ? 1 : 0);
}
return $response;
}
+2 -48
View File
@@ -26,9 +26,9 @@ class ExamResource extends JsonResource
'duration' => $this->duration ?: '',
'duration_text' => $this->duration_text,
'filters' => $this->normalizeFilters($this->resource),
'filters_formatted' => $this->formatFilters($this->resource),
'filters_formatted' => $this->filterFormatted,
'indexes' => $this->indexes,
'indexes_formatted' => $this->formatIndexes($this->resource),
'indexes_formatted' => $this->indexFormatted,
'status' => $this->status,
'status_text' => $this->statusText,
'is_discovered' => $this->is_discovered,
@@ -48,50 +48,4 @@ class ExamResource extends JsonResource
return $filters;
}
private function formatFilters(Exam $exam)
{
$currentFilters = $exam->filters;
$arr = [];
$filter = Exam::FILTER_USER_CLASS;
if (!empty($currentFilters->{$filter})) {
$classes = collect(User::$classes)->only($currentFilters->{$filter});
$arr[] = sprintf('%s: %s', Exam::$filters[$filter]['name'], $classes->pluck('text')->implode(', '));
}
$filter = Exam::FILTER_USER_REGISTER_TIME_RANGE;
if (!empty($currentFilters->{$filter})) {
$range = $currentFilters->{$filter};
$arr[] = sprintf(
"%s: \n%s ~ %s",
Exam::$filters[$filter]['name'],
$range[0] ? Carbon::parse($range[0])->toDateTimeString() : '-',
$range[1] ? Carbon::parse($range[1])->toDateTimeString() : '-'
);
}
$filter = Exam::FILTER_USER_DONATE;
if (!empty($currentFilters->{$filter})) {
$donateStatus = $classes = collect(User::$donateStatus)->only($currentFilters->{$filter});
$arr[] = sprintf('%s: %s', Exam::$filters[$filter]['name'], $donateStatus->pluck('text')->implode(', '));
}
return implode("\n", $arr);
}
private function formatIndexes(Exam $exam)
{
$indexes = $exam->indexes;
$arr = [];
foreach ($indexes as $index) {
if (isset($index['checked']) && $index['checked']) {
$arr[] = sprintf(
'%s: %s %s',
Exam::$indexes[$index['index']]['name'] ?? '',
$index['require_value'],
Exam::$indexes[$index['index']]['unit'] ?? ''
);
}
}
return implode("\n", $arr);
}
}
+48
View File
@@ -2,6 +2,7 @@
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class Exam extends NexusModel
@@ -78,4 +79,51 @@ class Exam extends NexusModel
return '';
}
public function getIndexFormattedAttribute(): string
{
$indexes = $this->indexes;
$arr = [];
foreach ($indexes as $index) {
if (isset($index['checked']) && $index['checked']) {
$arr[] = sprintf(
'%s: %s %s',
self::$indexes[$index['index']]['name'] ?? '',
$index['require_value'],
self::$indexes[$index['index']]['unit'] ?? ''
);
}
}
return implode("<br/>", $arr);
}
public function getFilterFormattedAttribute(): string
{
$currentFilters = $this->filters;
$arr = [];
$filter = self::FILTER_USER_CLASS;
if (!empty($currentFilters->{$filter})) {
$classes = collect(User::$classes)->only($currentFilters->{$filter});
$arr[] = sprintf('%s: %s', self::$filters[$filter]['name'], $classes->pluck('text')->implode(', '));
}
$filter = self::FILTER_USER_REGISTER_TIME_RANGE;
if (!empty($currentFilters->{$filter})) {
$range = $currentFilters->{$filter};
$arr[] = sprintf(
"%s: \n%s ~ %s",
self::$filters[$filter]['name'],
$range[0] ? Carbon::parse($range[0])->toDateTimeString() : '-',
$range[1] ? Carbon::parse($range[1])->toDateTimeString() : '-'
);
}
$filter = self::FILTER_USER_DONATE;
if (!empty($currentFilters->{$filter})) {
$donateStatus = $classes = collect(User::$donateStatus)->only($currentFilters->{$filter});
$arr[] = sprintf('%s: %s', self::$filters[$filter]['name'], $donateStatus->pluck('text')->implode(', '));
}
return implode("<br/>", $arr);
}
}
+15
View File
@@ -41,6 +41,21 @@ class ExamUser extends NexusModel
return self::$isDoneInfo[$this->is_done]['text'] ?? '';
}
public static function listStatus($onlyKeyValue = false): array
{
$result = self::$status;
$keyValues = [];
foreach ($result as $key => &$value) {
$text = nexus_trans('exam-user.status.' . $key);
$value['text'] = $text;
$keyValues[$key] = $text;
}
if ($onlyKeyValue) {
return $keyValues;
}
return $result;
}
public function getBeginAttribute()
{
$begin = $this->getRawOriginal('begin');
+8 -2
View File
@@ -55,11 +55,17 @@ class HitAndRun extends NexusModel
return nexus_trans('hr.status_' . $this->status);
}
public static function listStatus(): array
public static function listStatus($onlyKeyValue = false): array
{
$result = self::$status;
$keyValues = [];
foreach ($result as $key => &$value) {
$value['text'] = nexus_trans('hr.status_' . $key);
$text = nexus_trans('hr.status_' . $key);
$value['text'] = $text;
$keyValues[$key] = $text;
}
if ($onlyKeyValue) {
return $keyValues;
}
return $result;
}
+16 -1
View File
@@ -10,7 +10,7 @@ class Medal extends NexusModel
const GET_TYPE_GRANT = 2;
public static $getTypeText = [
public static array $getTypeText = [
self::GET_TYPE_EXCHANGE => ['text' => 'Exchange'],
self::GET_TYPE_GRANT => ['text' => 'Grant'],
];
@@ -19,6 +19,21 @@ class Medal extends NexusModel
public $timestamps = true;
public static function listGetTypes($onlyKeyValues = false): array
{
$results = self::$getTypeText;
$keyValues = [];
foreach ($results as $type => &$info) {
$text = nexus_trans("medal.get_types.$type");
$keyValues[$type] = $text;
$info['text'] = $text;
}
if ($onlyKeyValues) {
return $keyValues;
}
return $results;
}
public function getGetTypeTextAttribute($value): string
{
return self::$getTypeText[$this->get_type]['text'] ?? '';
+1 -1
View File
@@ -23,7 +23,7 @@ class NexusModel extends Model
*/
protected function serializeDate(\DateTimeInterface $date)
{
return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
return $date->format($this->dateFormat ?: 'Y-m-d H:i');
}
/**
+30 -2
View File
@@ -6,6 +6,7 @@ use App\Http\Middleware\Locale;
use App\Repositories\ExamRepository;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
@@ -13,8 +14,10 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Laravel\Sanctum\HasApiTokens;
use Nexus\Database\NexusDB;
use Filament\Models\Contracts\FilamentUser;
use Filament\Models\Contracts\HasName;
class User extends Authenticatable
class User extends Authenticatable implements FilamentUser, HasName
{
use HasFactory, Notifiable, HasApiTokens;
@@ -99,6 +102,17 @@ class User extends Authenticatable
return $classText;
}
public function canAccessFilament(): bool
{
return true;
// return str_ends_with($this->email, '@yourdomain.com') && $this->hasVerifiedEmail();
}
public function getFilamentName(): string
{
return $this->username;
}
/**
* @see ExamRepository::isExamMatchUser()
*
@@ -120,7 +134,7 @@ class User extends Authenticatable
*/
protected function serializeDate(\DateTimeInterface $date): string
{
return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
return $date->format($this->dateFormat ?: 'Y-m-d H:i');
}
/**
@@ -244,6 +258,20 @@ class User extends Authenticatable
return 'en';
}
protected function uploadedText(): Attribute
{
return new Attribute(
get: fn($value, $attributes) => mksize($attributes['uploaded'])
);
}
protected function downloadedText(): Attribute
{
return new Attribute(
get: fn($value, $attributes) => mksize($attributes['downloaded'])
);
}
public static function getMinSeedPoints($class)
{
$setting = Setting::get("account.{$class}_min_seed_points");
+10
View File
@@ -2,11 +2,13 @@
namespace App\Providers;
use Carbon\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Illuminate\Http\Resources\Json\JsonResource;
use Nexus\Nexus;
use Filament\Facades\Filament;
class AppServiceProvider extends ServiceProvider
{
@@ -30,5 +32,13 @@ class AppServiceProvider extends ServiceProvider
// JsonResource::withoutWrapping();
DB::connection(config('database.default'))->enableQueryLog();
Filament::serving(function () {
Filament::registerNavigationGroups([
'User',
'Torrent',
'System',
]);
});
}
}
+7
View File
@@ -2,6 +2,8 @@
namespace App\Providers;
use App\Auth\NexusWebGuard;
use App\Auth\NexusWebUserProvider;
use App\Models\User;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
@@ -31,6 +33,11 @@ class AuthServiceProvider extends ServiceProvider
Auth::viaRequest('nexus-cookie', function (Request $request) {
return $this->getUserByCookie($request->cookie());
});
Auth::extend('nexus-web', function ($app, $name, array $config) {
// 返回 Illuminate\Contracts\Auth\Guard 的实例 ...
return new NexusWebGuard($app->make('request'), new NexusWebUserProvider());
});
}
private function getUserByCookie($cookie)
+1 -1
View File
@@ -115,7 +115,7 @@ class UserRepository extends BaseRepository
'class' => $class
];
$user = new User($data);
if ($params['id']) {
if (!empty($params['id'])) {
if (User::query()->where('id', $params['id'])->exists()) {
throw new \InvalidArgumentException("uid: {$params['id']} already exists.");
}