mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-06 12:45:30 +00:00
Add some experimental account endpoints using a package
This commit is contained in:
@@ -36,6 +36,7 @@ use Illuminate\Session\TokenMismatchException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Validation\ValidationException as LaravelValidationException;
|
||||
use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException;
|
||||
use LaravelJsonApi\Core\Exceptions\JsonApiException;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -63,6 +64,7 @@ class Handler extends ExceptionHandler
|
||||
HttpException::class,
|
||||
SuspiciousOperationException::class,
|
||||
BadHttpHeaderException::class,
|
||||
JsonApiException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
59
app/JsonApi/V3/Accounts/AccountRepository.php
Normal file
59
app/JsonApi/V3/Accounts/AccountRepository.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/*
|
||||
* AccountRepository.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\JsonApi\V3\Accounts;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Support\JsonApi\Concerns\UsergroupAware;
|
||||
use LaravelJsonApi\Contracts\Store\QueriesAll;
|
||||
use LaravelJsonApi\NonEloquent\AbstractRepository;
|
||||
|
||||
|
||||
class AccountRepository extends AbstractRepository implements QueriesAll
|
||||
{
|
||||
use UsergroupAware;
|
||||
|
||||
/**
|
||||
* SiteRepository constructor.
|
||||
*
|
||||
*/
|
||||
public function __construct() {}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function find(string $resourceId): ?object
|
||||
{
|
||||
|
||||
return Account::find((int) $resourceId);
|
||||
}
|
||||
|
||||
public function queryAll(): Capabilities\AccountQuery
|
||||
{
|
||||
return Capabilities\AccountQuery::make()
|
||||
->withUserGroup($this->userGroup)
|
||||
->withServer($this->server)
|
||||
->withSchema($this->schema);
|
||||
}
|
||||
|
||||
}
|
160
app/JsonApi/V3/Accounts/AccountResource.php
Normal file
160
app/JsonApi/V3/Accounts/AccountResource.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
/*
|
||||
* AccountResource.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\JsonApi\V3\Accounts;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use LaravelJsonApi\Core\Resources\JsonApiResource;
|
||||
|
||||
class AccountResource extends JsonApiResource
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the resource id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function id(): string
|
||||
{
|
||||
return (string) $this->resource->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource's attributes.
|
||||
*
|
||||
* @param Request|null $request
|
||||
*
|
||||
* @return iterable
|
||||
*/
|
||||
public function attributes($request): iterable
|
||||
{
|
||||
return [
|
||||
'created_at' => $this->resource->created_at,
|
||||
'updated_at' => $this->resource->updated_at,
|
||||
'name' => $this->resource->name,
|
||||
'iban' => '' === $this->resource->iban ? null : $this->resource->iban,
|
||||
'active' => $this->resource->active,
|
||||
'virtual_balance' => $this->resource->virtual_balance,
|
||||
'last_activity' => $this->resource->last_activity,
|
||||
'balance' => $this->resource->balance,
|
||||
'native_balance' => $this->resource->native_balance,
|
||||
'type' => $this->resource->name,
|
||||
|
||||
// 'type' => strtolower($accountType),
|
||||
// 'account_role' => $accountRole,
|
||||
// 'currency_id' => $currencyId,
|
||||
// 'currency_code' => $currencyCode,
|
||||
// 'currency_symbol' => $currencySymbol,
|
||||
// 'currency_decimal_places' => $decimalPlaces,
|
||||
// 'current_balance' => app('steam')->bcround(app('steam')->balance($account, $date), $decimalPlaces),
|
||||
// 'current_balance_date' => $date->toAtomString(),
|
||||
// 'notes' => $this->repository->getNoteText($account),
|
||||
// 'monthly_payment_date' => $monthlyPaymentDate,
|
||||
// 'credit_card_type' => $creditCardType,
|
||||
// 'account_number' => $this->repository->getMetaValue($account, 'account_number'),
|
||||
// 'bic' => $this->repository->getMetaValue($account, 'BIC'),
|
||||
// 'opening_balance' => $openingBalance,
|
||||
// 'opening_balance_date' => $openingBalanceDate,
|
||||
// 'liability_type' => $liabilityType,
|
||||
// 'liability_direction' => $liabilityDirection,
|
||||
// 'interest' => $interest,
|
||||
// 'interest_period' => $interestPeriod,
|
||||
// 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'),
|
||||
// 'include_net_worth' => $includeNetWorth,
|
||||
// 'longitude' => $longitude,
|
||||
// 'latitude' => $latitude,
|
||||
// 'zoom_level' => $zoomLevel,
|
||||
// 'id' => (string) $account->id,
|
||||
// 'created_at' => $account->created_at->toAtomString(),
|
||||
// 'updated_at' => $account->updated_at->toAtomString(),
|
||||
// 'active' => $account->active,
|
||||
// 'order' => $order,
|
||||
// 'name' => $account->name,
|
||||
// 'iban' => '' === (string) $account->iban ? null : $account->iban,
|
||||
// 'account_number' => $this->accountMeta[$id]['account_number'] ?? null,
|
||||
// 'type' => strtolower($accountType),
|
||||
// 'account_role' => $accountRole,
|
||||
// 'currency_id' => (string) $currency->id,
|
||||
// 'currency_code' => $currency->code,
|
||||
// 'currency_symbol' => $currency->symbol,
|
||||
// 'currency_decimal_places' => $currency->decimal_places,
|
||||
//
|
||||
// 'native_currency_id' => (string) $this->default->id,
|
||||
// 'native_currency_code' => $this->default->code,
|
||||
// 'native_currency_symbol' => $this->default->symbol,
|
||||
// 'native_currency_decimal_places' => $this->default->decimal_places,
|
||||
//
|
||||
// // balance:
|
||||
// 'current_balance' => $balance,
|
||||
// 'native_current_balance' => $nativeBalance,
|
||||
// 'current_balance_date' => $this->getDate()->endOfDay()->toAtomString(),
|
||||
//
|
||||
// // balance difference
|
||||
// 'balance_difference' => $balanceDiff,
|
||||
// 'native_balance_difference' => $nativeBalanceDiff,
|
||||
// 'balance_difference_start' => $diffStart,
|
||||
// 'balance_difference_end' => $diffEnd,
|
||||
//
|
||||
// // more meta
|
||||
// 'last_activity' => array_key_exists($id, $this->lastActivity) ? $this->lastActivity[$id]->toAtomString() : null,
|
||||
//
|
||||
// // liability stuff
|
||||
// 'liability_type' => $liabilityType,
|
||||
// 'liability_direction' => $liabilityDirection,
|
||||
// 'interest' => $interest,
|
||||
// 'interest_period' => $interestPeriod,
|
||||
// 'current_debt' => $currentDebt,
|
||||
//
|
||||
// // object group
|
||||
// 'object_group_id' => null !== $objectGroupId ? (string) $objectGroupId : null,
|
||||
// 'object_group_order' => $objectGroupOrder,
|
||||
// 'object_group_title' => $objectGroupTitle,
|
||||
// 'notes' => $this->repository->getNoteText($account),
|
||||
// 'monthly_payment_date' => $monthlyPaymentDate,
|
||||
// 'credit_card_type' => $creditCardType,
|
||||
// 'bic' => $this->repository->getMetaValue($account, 'BIC'),
|
||||
// 'virtual_balance' => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''),
|
||||
// 'opening_balance' => $openingBalance,
|
||||
// 'opening_balance_date' => $openingBalanceDate,
|
||||
// 'include_net_worth' => $includeNetWorth,
|
||||
// 'longitude' => $longitude,
|
||||
// 'latitude' => $latitude,
|
||||
// 'zoom_level' => $zoomLevel,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource's relationships.
|
||||
*
|
||||
* @param Request|null $request
|
||||
*
|
||||
* @return iterable
|
||||
*/
|
||||
public function relationships($request): iterable
|
||||
{
|
||||
return [
|
||||
$this->relation('user')->withData($this->resource->user),
|
||||
//$this->relation('tags')->withData($this->resource->getTags()),
|
||||
];
|
||||
}
|
||||
}
|
190
app/JsonApi/V3/Accounts/AccountSchema.php
Normal file
190
app/JsonApi/V3/Accounts/AccountSchema.php
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/*
|
||||
* AccountSchema.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\JsonApi\V3\Accounts;
|
||||
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use LaravelJsonApi\Core\Schema\Schema;
|
||||
use LaravelJsonApi\Eloquent\Fields\DateTime;
|
||||
use LaravelJsonApi\NonEloquent\Fields\Attribute;
|
||||
use LaravelJsonApi\NonEloquent\Fields\ID;
|
||||
use LaravelJsonApi\NonEloquent\Fields\ToMany;
|
||||
use LaravelJsonApi\NonEloquent\Fields\ToOne;
|
||||
use LaravelJsonApi\NonEloquent\Filters\Filter;
|
||||
use LaravelJsonApi\NonEloquent\Pagination\EnumerablePagination;
|
||||
|
||||
class AccountSchema extends Schema
|
||||
{
|
||||
use ValidatesUserGroupTrait;
|
||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
|
||||
|
||||
/**
|
||||
* The model the schema corresponds to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static string $model = Account::class;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function fields(): iterable
|
||||
{
|
||||
return [
|
||||
ID::make(),
|
||||
DateTime::make('created_at')->sortable()->readOnly(),
|
||||
DateTime::make('updated_at')->sortable()->readOnly(),
|
||||
Attribute::make('name')->sortable(),
|
||||
Attribute::make('iban'),
|
||||
Attribute::make('active'),
|
||||
Attribute::make('virtual_balance'),
|
||||
|
||||
Attribute::make('last_activity')->sortable(),
|
||||
Attribute::make('balance')->sortable(),
|
||||
Attribute::make('native_balance')->sortable(),
|
||||
Attribute::make('type'),
|
||||
|
||||
// fancy fields:
|
||||
|
||||
|
||||
|
||||
//Attribute::make('current_balance')->sortable(),
|
||||
|
||||
// 'type' => strtolower($accountType),
|
||||
// 'account_role' => $accountRole,
|
||||
// 'currency_id' => $currencyId,
|
||||
// 'currency_code' => $currencyCode,
|
||||
// 'currency_symbol' => $currencySymbol,
|
||||
// 'currency_decimal_places' => $decimalPlaces,
|
||||
// 'current_balance' => app('steam')->bcround(app('steam')->balance($account, $date), $decimalPlaces),
|
||||
// 'current_balance_date' => $date->toAtomString(),
|
||||
// 'notes' => $this->repository->getNoteText($account),
|
||||
// 'monthly_payment_date' => $monthlyPaymentDate,
|
||||
// 'credit_card_type' => $creditCardType,
|
||||
// 'account_number' => $this->repository->getMetaValue($account, 'account_number'),
|
||||
// 'bic' => $this->repository->getMetaValue($account, 'BIC'),
|
||||
// 'opening_balance' => $openingBalance,
|
||||
// 'opening_balance_date' => $openingBalanceDate,
|
||||
// 'liability_type' => $liabilityType,
|
||||
// 'liability_direction' => $liabilityDirection,
|
||||
// 'interest' => $interest,
|
||||
// 'interest_period' => $interestPeriod,
|
||||
// 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'),
|
||||
// 'include_net_worth' => $includeNetWorth,
|
||||
// 'longitude' => $longitude,
|
||||
// 'latitude' => $latitude,
|
||||
// 'zoom_level' => $zoomLevel,
|
||||
// 'id' => (string) $account->id,
|
||||
// 'created_at' => $account->created_at->toAtomString(),
|
||||
// 'updated_at' => $account->updated_at->toAtomString(),
|
||||
// 'active' => $account->active,
|
||||
// 'order' => $order,
|
||||
// 'name' => $account->name,
|
||||
// 'iban' => '' === (string) $account->iban ? null : $account->iban,
|
||||
// 'account_number' => $this->accountMeta[$id]['account_number'] ?? null,
|
||||
// 'type' => strtolower($accountType),
|
||||
// 'account_role' => $accountRole,
|
||||
// 'currency_id' => (string) $currency->id,
|
||||
// 'currency_code' => $currency->code,
|
||||
// 'currency_symbol' => $currency->symbol,
|
||||
// 'currency_decimal_places' => $currency->decimal_places,
|
||||
//
|
||||
// 'native_currency_id' => (string) $this->default->id,
|
||||
// 'native_currency_code' => $this->default->code,
|
||||
// 'native_currency_symbol' => $this->default->symbol,
|
||||
// 'native_currency_decimal_places' => $this->default->decimal_places,
|
||||
//
|
||||
// // balance:
|
||||
// 'current_balance' => $balance,
|
||||
// 'native_current_balance' => $nativeBalance,
|
||||
// 'current_balance_date' => $this->getDate()->endOfDay()->toAtomString(),
|
||||
//
|
||||
// // balance difference
|
||||
// 'balance_difference' => $balanceDiff,
|
||||
// 'native_balance_difference' => $nativeBalanceDiff,
|
||||
// 'balance_difference_start' => $diffStart,
|
||||
// 'balance_difference_end' => $diffEnd,
|
||||
//
|
||||
// // more meta
|
||||
// 'last_activity' => array_key_exists($id, $this->lastActivity) ? $this->lastActivity[$id]->toAtomString() : null,
|
||||
//
|
||||
// // liability stuff
|
||||
// 'liability_type' => $liabilityType,
|
||||
// 'liability_direction' => $liabilityDirection,
|
||||
// 'interest' => $interest,
|
||||
// 'interest_period' => $interestPeriod,
|
||||
// 'current_debt' => $currentDebt,
|
||||
//
|
||||
// // object group
|
||||
// 'object_group_id' => null !== $objectGroupId ? (string) $objectGroupId : null,
|
||||
// 'object_group_order' => $objectGroupOrder,
|
||||
// 'object_group_title' => $objectGroupTitle,
|
||||
// 'notes' => $this->repository->getNoteText($account),
|
||||
// 'monthly_payment_date' => $monthlyPaymentDate,
|
||||
// 'credit_card_type' => $creditCardType,
|
||||
// 'bic' => $this->repository->getMetaValue($account, 'BIC'),
|
||||
// 'virtual_balance' => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''),
|
||||
// 'opening_balance' => $openingBalance,
|
||||
// 'opening_balance_date' => $openingBalanceDate,
|
||||
// 'include_net_worth' => $includeNetWorth,
|
||||
// 'longitude' => $longitude,
|
||||
// 'latitude' => $latitude,
|
||||
// 'zoom_level' => $zoomLevel,
|
||||
|
||||
ToOne::make('user'),
|
||||
// ToMany::make('tags'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function pagination(): EnumerablePagination
|
||||
{
|
||||
return EnumerablePagination::make();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function filters(): iterable
|
||||
{
|
||||
return [
|
||||
Filter::make('name'),
|
||||
];
|
||||
}
|
||||
public function repository(): AccountRepository
|
||||
{
|
||||
$userGroup = $this->validateUserGroup(request());
|
||||
return AccountRepository::make()
|
||||
->withUserGroup($userGroup)
|
||||
->withServer($this->server)
|
||||
->withSchema($this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
84
app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php
Normal file
84
app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
* AccountQuery.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\JsonApi\V3\Accounts\Capabilities;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Support\JsonApi\Concerns\UsergroupAware;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\JsonApi\ExpandsQuery;
|
||||
use FireflyIII\Support\JsonApi\FiltersPagination;
|
||||
use FireflyIII\Support\JsonApi\SortsCollection;
|
||||
use FireflyIII\Support\JsonApi\ValidateSortParameters;
|
||||
use LaravelJsonApi\Contracts\Store\HasPagination;
|
||||
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
|
||||
use LaravelJsonApi\NonEloquent\Concerns\PaginatesEnumerables;
|
||||
|
||||
class AccountQuery extends QueryAll implements HasPagination
|
||||
{
|
||||
use PaginatesEnumerables;
|
||||
use FiltersPagination;
|
||||
use ValidateSortParameters;
|
||||
use UsergroupAware;
|
||||
use ExpandsQuery;
|
||||
use SortsCollection;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override] public function get(): iterable
|
||||
{
|
||||
$filters = $this->queryParameters->filter();
|
||||
$sort = $this->queryParameters->sortFields();
|
||||
$pagination = $this->filtersPagination($this->queryParameters->page());
|
||||
$needsAll = $this->validateParams('account', $sort);
|
||||
$query = $this->userGroup->accounts();
|
||||
|
||||
if (!$needsAll) {
|
||||
$query = $this->addPagination($query, $pagination);
|
||||
}
|
||||
$query = $this->addSortParams($query, $sort);
|
||||
$query = $this->addFilterParams('account', $query, $filters);
|
||||
|
||||
$collection = $query->get(['accounts.*']);
|
||||
|
||||
// enrich data
|
||||
$enrichment = new AccountEnrichment();
|
||||
$collection = $enrichment->enrich($collection);
|
||||
|
||||
|
||||
// add filters after the query
|
||||
|
||||
// add sort after the query
|
||||
$collection = $this->sortCollection($collection, $sort);
|
||||
|
||||
|
||||
return $collection;
|
||||
|
||||
// var_dump($filters->value('name'));
|
||||
// exit;
|
||||
|
||||
|
||||
return Account::get();
|
||||
}
|
||||
}
|
42
app/JsonApi/V3/Server.php
Normal file
42
app/JsonApi/V3/Server.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\JsonApi\V3;
|
||||
|
||||
use FireflyIII\JsonApi\V3\Accounts\AccountSchema;
|
||||
use FireflyIII\JsonApi\V3\Users\UserSchema;
|
||||
use LaravelJsonApi\Core\Server\Server as BaseServer;
|
||||
|
||||
class Server extends BaseServer
|
||||
{
|
||||
|
||||
/**
|
||||
* The base URI namespace for this server.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $baseUri = '/api/v3';
|
||||
|
||||
/**
|
||||
* Bootstrap the server when it is handling an HTTP request.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function serving(): void
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server's list of schemas.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function allSchemas(): array
|
||||
{
|
||||
return [
|
||||
AccountSchema::class,
|
||||
UserSchema::class,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
65
app/JsonApi/V3/Users/UserSchema.php
Normal file
65
app/JsonApi/V3/Users/UserSchema.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\JsonApi\V3\Users;
|
||||
|
||||
use FireflyIII\User;
|
||||
use LaravelJsonApi\Eloquent\Contracts\Paginator;
|
||||
use LaravelJsonApi\Eloquent\Fields\DateTime;
|
||||
use LaravelJsonApi\Eloquent\Fields\ID;
|
||||
use LaravelJsonApi\Eloquent\Fields\Relations\HasMany;
|
||||
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
|
||||
use LaravelJsonApi\Eloquent\Pagination\PagePagination;
|
||||
use LaravelJsonApi\Eloquent\Schema;
|
||||
|
||||
class UserSchema extends Schema
|
||||
{
|
||||
|
||||
/**
|
||||
* The model the schema corresponds to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static string $model = User::class;
|
||||
|
||||
/**
|
||||
* Get the resource fields.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fields(): array
|
||||
{
|
||||
return [
|
||||
ID::make(),
|
||||
DateTime::make('createdAt')->sortable()->readOnly(),
|
||||
DateTime::make('updatedAt')->sortable()->readOnly(),
|
||||
HasMany::make('accounts'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource filters.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
WhereIdIn::make($this),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource paginator.
|
||||
*
|
||||
* @return Paginator|null
|
||||
*/
|
||||
public function pagination(): ?Paginator
|
||||
{
|
||||
return PagePagination::make();
|
||||
}
|
||||
public function authorizable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
54
app/Policies/AccountPolicy.php
Normal file
54
app/Policies/AccountPolicy.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*
|
||||
* AccountPolicy.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Policies;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\User;
|
||||
|
||||
class AccountPolicy
|
||||
{
|
||||
|
||||
/**
|
||||
* TODO needs better authentication.
|
||||
*
|
||||
* @param User $user
|
||||
* @param Account $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function view(User $user, Account $account): bool
|
||||
{
|
||||
return auth()->check() && $user->id === $account->user_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Everybody can do this, but selection should limit to user.
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
}
|
29
app/Policies/UserPolicy.php
Normal file
29
app/Policies/UserPolicy.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* UserPolicy.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Policies;
|
||||
|
||||
class UserPolicy
|
||||
{
|
||||
|
||||
}
|
48
app/Support/JsonApi/Concerns/UsergroupAware.php
Normal file
48
app/Support/JsonApi/Concerns/UsergroupAware.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/*
|
||||
* UsergroupAware.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Concerns;
|
||||
|
||||
use FireflyIII\Models\UserGroup;
|
||||
|
||||
trait UsergroupAware
|
||||
{
|
||||
|
||||
protected UserGroup $userGroup;
|
||||
|
||||
public function getUserGroup(): UserGroup
|
||||
{
|
||||
return $this->userGroup;
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
|
||||
public function withUserGroup(UserGroup $userGroup): self {
|
||||
$this->userGroup = $userGroup;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
79
app/Support/JsonApi/Enrichments/AccountEnrichment.php
Normal file
79
app/Support/JsonApi/Enrichments/AccountEnrichment.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/*
|
||||
* AccountEnricher.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class AccountEnrichment implements EnrichmentInterface
|
||||
{
|
||||
|
||||
private Collection $collection;
|
||||
|
||||
#[\Override] public function enrich(Collection $collection): Collection
|
||||
{
|
||||
$this->collection = $collection;
|
||||
|
||||
// do everything here:
|
||||
$this->getLastActivity();
|
||||
$this->getMetaBalances();
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO this method refers to a single-use method inside Steam that could be moved here.
|
||||
* @return void
|
||||
*/
|
||||
private function getLastActivity(): void
|
||||
{
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$lastActivity = $accountRepository->getLastActivity($this->collection);
|
||||
foreach ($lastActivity as $row) {
|
||||
$this->collection->where('id', $row['account_id'])->first()->last_activity = Carbon::parse($row['date_max'], config('app.timezone'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO this method refers to a single-use method inside Steam that could be moved here.
|
||||
* @return void
|
||||
*/
|
||||
private function getMetaBalances(): void
|
||||
{
|
||||
try {
|
||||
$array = app('steam')->balancesByAccountsConverted($this->collection, today());
|
||||
} catch (FireflyException $e) {
|
||||
Log::error(sprintf('Could not load balances: %s', $e->getMessage()));
|
||||
return;
|
||||
}
|
||||
foreach ($array as $accountId => $row) {
|
||||
$this->collection->where('id', $accountId)->first()->balance = $row['balance'];
|
||||
$this->collection->where('id', $accountId)->first()->native_balance = $row['native_balance'];
|
||||
}
|
||||
}
|
||||
}
|
32
app/Support/JsonApi/Enrichments/EnrichmentInterface.php
Normal file
32
app/Support/JsonApi/Enrichments/EnrichmentInterface.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
* EnricherInterface.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
interface EnrichmentInterface
|
||||
{
|
||||
public function enrich(Collection $collection): Collection;
|
||||
|
||||
}
|
68
app/Support/JsonApi/ExpandsQuery.php
Normal file
68
app/Support/JsonApi/ExpandsQuery.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/*
|
||||
* ExpandsQuery.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi;
|
||||
|
||||
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||
use LaravelJsonApi\Core\Query\FilterParameters;
|
||||
use LaravelJsonApi\Core\Query\SortFields;
|
||||
|
||||
trait ExpandsQuery
|
||||
{
|
||||
final protected function addPagination(Builder $query, array $pagination): Builder
|
||||
{
|
||||
$skip = ($pagination['number'] - 1) * $pagination['size'];
|
||||
return $query->skip($skip)->take($pagination['size']);
|
||||
}
|
||||
|
||||
final protected function addSortParams(Builder $query, SortFields $sort): Builder
|
||||
{
|
||||
foreach ($sort->all() as $sortField) {
|
||||
$query->orderBy($sortField->name(), $sortField->isAscending() ? 'ASC' : 'DESC');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
final protected function addFilterParams(string $class, Builder $query, ?FilterParameters $filters): Builder
|
||||
{
|
||||
if (null === $filters) {
|
||||
return $query;
|
||||
}
|
||||
$config = config(sprintf('firefly.valid_query_filters.%s', $class)) ?? [];
|
||||
if (count($filters->all()) === 0) {
|
||||
return $query;
|
||||
}
|
||||
$query->where(function (Builder $q) use ($config, $filters) {
|
||||
foreach ($filters->all() as $filter) {
|
||||
if (in_array($filter->key(), $config, true)) {
|
||||
foreach($filter->value() as $value) {
|
||||
$q->where($filter->key(), 'LIKE', sprintf('%%%s%%', $value));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
55
app/Support/JsonApi/FiltersPagination.php
Normal file
55
app/Support/JsonApi/FiltersPagination.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* FiltersPagination.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi;
|
||||
|
||||
trait FiltersPagination
|
||||
{
|
||||
|
||||
protected function filtersPagination(?array $pagination): array
|
||||
{
|
||||
if (null === $pagination) {
|
||||
return [
|
||||
'number' => 1,
|
||||
'size' => $this->getPageSize(),
|
||||
];
|
||||
}
|
||||
// cleanup page number
|
||||
$pagination['number'] = (int) ($pagination['number'] ?? 1);
|
||||
$pagination['number'] = min(65536, max($pagination['number'], 1));
|
||||
|
||||
// clean up page size
|
||||
$pagination['size'] = (int) ($pagination['size'] ?? $this->getPageSize());
|
||||
$pagination['size'] = min(1337, max($pagination['size'], 1));
|
||||
|
||||
return $pagination;
|
||||
}
|
||||
|
||||
private function getPageSize(): int
|
||||
{
|
||||
if (auth()->check()) {
|
||||
return (int) app('preferences')->get('listPageSize', 50)->data;
|
||||
}
|
||||
return 50;
|
||||
}
|
||||
}
|
40
app/Support/JsonApi/SortsCollection.php
Normal file
40
app/Support/JsonApi/SortsCollection.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/*
|
||||
* SortsCollection.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use LaravelJsonApi\Core\Query\SortFields;
|
||||
|
||||
trait SortsCollection
|
||||
{
|
||||
protected function sortCollection(Collection $collection, SortFields $sortFields): Collection {
|
||||
|
||||
foreach($sortFields->all() as $sortField) {
|
||||
$collection = $sortField->isAscending() ? $collection->sortBy($sortField->name()) : $collection->sortByDesc($sortField->name());
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
}
|
43
app/Support/JsonApi/ValidateSortParameters.php
Normal file
43
app/Support/JsonApi/ValidateSortParameters.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/*
|
||||
* ValidateSortParameters.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi;
|
||||
|
||||
use LaravelJsonApi\Core\Query\SortFields;
|
||||
|
||||
trait ValidateSortParameters
|
||||
{
|
||||
function validateParams(string $class, SortFields $params): bool
|
||||
{
|
||||
|
||||
$config = config(sprintf('firefly.full_data_set.%s', $class)) ?? [];
|
||||
|
||||
foreach ($params->all() as $field) {
|
||||
if (in_array($field->name(), $config, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
35
config/jsonapi.php
Normal file
35
config/jsonapi.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use FireflyIII\JsonApi\V3\Server;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Root Namespace
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The root JSON:API namespace, within your application's namespace.
|
||||
| This is used when generating any class that does not sit *within*
|
||||
| a server's namespace. For example, new servers and filters.
|
||||
|
|
||||
| By default this is set to `JsonApi` which means the root namespace
|
||||
| will be `\App\JsonApi`, if your application's namespace is `App`.
|
||||
*/
|
||||
'namespace' => 'JsonApi',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Servers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| A list of the JSON:API compliant APIs in your application, referred to
|
||||
| as "servers". They must be listed below, with the array key being the
|
||||
| unique name for each server, and the value being the fully-qualified
|
||||
| class name of the server class.
|
||||
*/
|
||||
'servers' => [
|
||||
// 'v1' => \App\JsonApi\V1\Server::class,
|
||||
'v3' => Server::class,
|
||||
],
|
||||
];
|
@@ -22,6 +22,19 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use LaravelJsonApi\Laravel\Facades\JsonApiRoute;
|
||||
use LaravelJsonApi\Laravel\Routing\ResourceRegistrar;
|
||||
use LaravelJsonApi\Laravel\Http\Controllers\JsonApiController;
|
||||
|
||||
|
||||
JsonApiRoute::server('v3')
|
||||
->prefix('v3')
|
||||
->resources(function (ResourceRegistrar $server) {
|
||||
$server->resource('accounts', JsonApiController::class);
|
||||
$server->resource('users', JsonApiController::class);
|
||||
});
|
||||
|
||||
|
||||
// V2 API route for Summary boxes
|
||||
// BASIC
|
||||
Route::group(
|
||||
|
Reference in New Issue
Block a user