mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-09-01 21:00:58 +00:00
refactor(accounts): rewrite legacy-era regions of the provider, admin companies, profile controller and routes in place
This commit is contained in:
@@ -46,11 +46,19 @@ class AccountsServiceProvider extends ServiceProvider
|
||||
Gate::policy(User::class, UserPolicy::class);
|
||||
Gate::policy(Role::class, RolePolicy::class);
|
||||
|
||||
Gate::define('create company', [CompanyPolicy::class, 'create']);
|
||||
Gate::define('transfer company ownership', [CompanyPolicy::class, 'transferOwnership']);
|
||||
Gate::define('delete company', [CompanyPolicy::class, 'delete']);
|
||||
Gate::define('manage company', [SettingsPolicy::class, 'manageCompany']);
|
||||
Gate::define('delete multiple users', [UserPolicy::class, 'deleteMultiple']);
|
||||
Gate::define('owner only', [OwnerPolicy::class, 'managedByOwner']);
|
||||
// Ability names the controllers authorize against, each one routed to
|
||||
// the policy method that decides it. Registered in this order.
|
||||
$gates = [
|
||||
'create company' => [CompanyPolicy::class, 'create'],
|
||||
'transfer company ownership' => [CompanyPolicy::class, 'transferOwnership'],
|
||||
'delete company' => [CompanyPolicy::class, 'delete'],
|
||||
'manage company' => [SettingsPolicy::class, 'manageCompany'],
|
||||
'delete multiple users' => [UserPolicy::class, 'deleteMultiple'],
|
||||
'owner only' => [OwnerPolicy::class, 'managedByOwner'],
|
||||
];
|
||||
|
||||
foreach ($gates as $ability => $handler) {
|
||||
Gate::define($ability, $handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,7 @@ class CompaniesController extends Controller
|
||||
$this->authorize('create company');
|
||||
|
||||
$user = $request->user();
|
||||
|
||||
$company = Company::create($request->getCompanyPayload());
|
||||
$company = Company::query()->create($request->getCompanyPayload());
|
||||
$company->unique_hash = Hashids::connection(HashidConnection::Company->value)->encode($company->id);
|
||||
$company->save();
|
||||
$this->companyService->setupDefaults($company, (int) $request->validated('currency'));
|
||||
@@ -87,12 +86,15 @@ class CompaniesController extends Controller
|
||||
|
||||
public function destroy(Request $request)
|
||||
{
|
||||
$company = Company::find($request->header('company'));
|
||||
$company = Company::query()->find($request->header('company'));
|
||||
|
||||
$this->authorize('delete company', $company);
|
||||
|
||||
if ($request->name !== $company->name) {
|
||||
return respondJson('company_name_must_match_with_given_name', 'Company name must match with given name');
|
||||
if ($company->name !== $request->input('name')) {
|
||||
return respondJson(
|
||||
'company_name_must_match_with_given_name',
|
||||
'Company name must match with given name'
|
||||
);
|
||||
}
|
||||
|
||||
$this->companyService->delete($company);
|
||||
@@ -104,8 +106,6 @@ class CompaniesController extends Controller
|
||||
|
||||
public function userCompanies(Request $request)
|
||||
{
|
||||
$companies = $request->user()->companies;
|
||||
|
||||
return CompanyResource::collection($companies);
|
||||
return CompanyResource::collection($request->user()->companies);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,18 +25,27 @@ class UserProfileController extends Controller
|
||||
|
||||
public function update(ProfileRequest $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
$account = $request->user();
|
||||
|
||||
$user->update($request->validated());
|
||||
$account->update($request->validated());
|
||||
|
||||
return new UserResource($user);
|
||||
return new UserResource($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach, swap or drop the caller's profile picture.
|
||||
*
|
||||
* Three things can arrive on one call and each is handled in turn, so a
|
||||
* payload carrying both a removal flag and a picture ends up with the
|
||||
* picture, and a payload carrying both transports ends up with whatever
|
||||
* came in as base64. Only the two picture branches check that somebody is
|
||||
* actually signed in; the removal branch does not. Kept as it stands.
|
||||
*/
|
||||
public function uploadAvatar(AvatarRequest $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$user = $request->user();
|
||||
|
||||
if (isset($request->is_admin_avatar_removed) && (bool) $request->is_admin_avatar_removed) {
|
||||
if ($request->is_admin_avatar_removed ?? false) {
|
||||
$this->userAvatarManager->clear($user);
|
||||
}
|
||||
if ($user && $request->hasFile('admin_avatar')) {
|
||||
@@ -48,8 +57,9 @@ class UserProfileController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
if ($user && $request->has('avatar')) {
|
||||
$data = json_decode($request->avatar);
|
||||
if ($user !== null && $request->has('avatar')) {
|
||||
$encoded = $request->avatar;
|
||||
$data = json_decode($encoded);
|
||||
$this->userAvatarManager->replaceBase64($user, $data->data, $data->name);
|
||||
}
|
||||
|
||||
@@ -65,12 +75,8 @@ class UserProfileController extends Controller
|
||||
|
||||
public function updateSettings(UpdateSettingsRequest $request): JsonResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
$request->user()->setSettings($request->settings);
|
||||
|
||||
$user->setSettings($request->settings);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
]);
|
||||
return response()->json(['success' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use Illuminate\Support\Facades\Route;
|
||||
Route::get('/invitations/pending', [InvitationResponseController::class, 'pending']);
|
||||
Route::post('/invitations/{invitation:token}/accept', [InvitationResponseController::class, 'accept']);
|
||||
Route::post('/invitations/{invitation:token}/decline', [InvitationResponseController::class, 'decline']);
|
||||
Route::get('/auth/check', [AuthController::class, 'check']);
|
||||
Route::get('auth/check', [AuthController::class, 'check']); // is the caller's token still live?
|
||||
|
||||
Route::apiResource('company-invitations', InvitationController::class)->only(['index', 'store', 'destroy']);
|
||||
|
||||
@@ -23,11 +23,14 @@ Route::get('/me/settings', [UserProfileController::class, 'showSettings']);
|
||||
Route::put('/me/settings', [UserProfileController::class, 'updateSettings']);
|
||||
Route::post('/me/upload-avatar', [UserProfileController::class, 'uploadAvatar']);
|
||||
|
||||
Route::put('/company', [CompanyController::class, 'updateCompany']);
|
||||
Route::post('/company/upload-logo', [CompanyController::class, 'uploadCompanyLogo']);
|
||||
Route::controller(CompanyController::class)->group(function (): void {
|
||||
// The company record itself; its settings are handled separately below.
|
||||
Route::put('company', 'updateCompany');
|
||||
Route::post('company/upload-logo', 'uploadCompanyLogo');
|
||||
});
|
||||
Route::get('/company/settings', [CompanySettingsController::class, 'show']);
|
||||
Route::post('/company/settings', [CompanySettingsController::class, 'update']);
|
||||
Route::get('/company/has-transactions', [CompanySettingsController::class, 'checkTransactions']);
|
||||
|
||||
Route::get('abilities', AbilitiesController::class);
|
||||
Route::apiResource('roles', RolesController::class);
|
||||
Route::get('abilities', AbilitiesController::class); // the fixed catalogue the role editor lists
|
||||
Route::apiResources(['roles' => RolesController::class]);
|
||||
|
||||
@@ -5,9 +5,9 @@ use App\Domains\Accounts\Http\Controllers\Company\CompanySettingsController;
|
||||
use App\Domains\Accounts\Http\Controllers\Company\MembersController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::post('companies', [CompaniesController::class, 'store']);
|
||||
Route::post('companies', [CompaniesController::class, 'store']); // gated on owning the active company
|
||||
Route::post('/transfer/ownership/{user}', [CompanySettingsController::class, 'transferOwnership']);
|
||||
Route::post('companies/delete', [CompaniesController::class, 'destroy']);
|
||||
Route::post('companies/delete', [CompaniesController::class, 'destroy']); // posted, and confirmed by name
|
||||
Route::get('companies', [CompaniesController::class, 'userCompanies']);
|
||||
|
||||
Route::post('/members/delete', [MembersController::class, 'delete']);
|
||||
|
||||
@@ -8,9 +8,9 @@ use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::prefix('auth')->group(function (): void {
|
||||
Route::post('login', [AuthController::class, 'login']);
|
||||
Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');
|
||||
Route::post('logout', [AuthController::class, 'logout'])->middleware(['auth:sanctum']); // needs the token it revokes
|
||||
Route::post('password/email', [ForgotPasswordController::class, 'sendResetLinkEmail'])->middleware('throttle:10,2');
|
||||
Route::post('reset/password', [ResetPasswordController::class, 'reset']);
|
||||
Route::post('/reset/password', [ResetPasswordController::class, 'reset']); // the mailed token travels in the body
|
||||
});
|
||||
|
||||
Route::get('/invitations/{token}/details', [InvitationRegistrationController::class, 'details']);
|
||||
|
||||
Reference in New Issue
Block a user