mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-21 03:39:00 +00:00
Extended the user admin.
This commit is contained in:
@@ -78,5 +78,41 @@ class UserController extends Controller
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param UserRepositoryInterface $repository
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function show(UserRepositoryInterface $repository, User $user)
|
||||||
|
{
|
||||||
|
$title = strval(trans('firefly.administration'));
|
||||||
|
$mainTitleIcon = 'fa-hand-spock-o';
|
||||||
|
$subTitle = strval(trans('firefly.single_user_administration', ['email' => $user->email]));
|
||||||
|
$subTitleIcon = 'fa-user';
|
||||||
|
$defaultIp = '0.0.0.0';
|
||||||
|
$registration = Preferences::getForUser($user, 'registration_ip_address', $defaultIp)->data;
|
||||||
|
$confirmation = Preferences::getForUser($user, 'confirmation_ip_address', $defaultIp)->data;
|
||||||
|
$registrationHost = '';
|
||||||
|
$confirmationHost = '';
|
||||||
|
|
||||||
|
if ($registration != $defaultIp) {
|
||||||
|
$registrationHost = gethostbyaddr($registration);
|
||||||
|
}
|
||||||
|
if ($confirmation != $defaultIp) {
|
||||||
|
$confirmationHost = gethostbyaddr($confirmation);
|
||||||
|
}
|
||||||
|
|
||||||
|
$information = $repository->getUserData($user);
|
||||||
|
|
||||||
|
return view(
|
||||||
|
'admin.users.show',
|
||||||
|
compact(
|
||||||
|
'title', 'mainTitleIcon', 'subTitle', 'subTitleIcon', 'information',
|
||||||
|
'user', 'registration', 'confirmation', 'registrationHost', 'confirmationHost'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ use FireflyIII\Models\RuleGroup;
|
|||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HOME
|
* HOME
|
||||||
@@ -115,6 +116,13 @@ Breadcrumbs::register(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Breadcrumbs::register(
|
||||||
|
'admin.users.show', function (BreadCrumbGenerator $breadcrumbs, User $user) {
|
||||||
|
$breadcrumbs->parent('admin.users');
|
||||||
|
$breadcrumbs->push(trans('firefly.single_user_administration', ['email' => $user->email]), route('admin.users.show', $user->id));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'admin.users.domains', function (BreadCrumbGenerator $breadcrumbs) {
|
'admin.users.domains', function (BreadCrumbGenerator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('admin.index');
|
$breadcrumbs->parent('admin.index');
|
||||||
|
@@ -14,9 +14,11 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Repositories\User;
|
namespace FireflyIII\Repositories\User;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\Role;
|
use FireflyIII\Models\Role;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Preferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UserRepository
|
* Class UserRepository
|
||||||
@@ -56,4 +58,59 @@ class UserRepository implements UserRepositoryInterface
|
|||||||
{
|
{
|
||||||
return $this->all()->count();
|
return $this->all()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return basic user information.
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getUserData(User $user): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
|
||||||
|
// two factor:
|
||||||
|
$is2faEnabled = Preferences::getForUser($user, 'twoFactorAuthEnabled', false)->data;
|
||||||
|
$has2faSecret = !is_null(Preferences::getForUser($user, 'twoFactorAuthSecret'));
|
||||||
|
$return['has_2fa'] = false;
|
||||||
|
if ($is2faEnabled && $has2faSecret) {
|
||||||
|
$return['has_2fa'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is user activated?
|
||||||
|
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
|
||||||
|
$isConfirmed = Preferences::getForUser($user, 'user_confirmed', false)->data;
|
||||||
|
$return['is_activated'] = true;
|
||||||
|
if ($isConfirmed === false && $confirmAccount === true) {
|
||||||
|
$return['is_activated'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$return['is_admin'] = $user->hasRole('owner');
|
||||||
|
$return['blocked'] = intval($user->blocked) === 1;
|
||||||
|
$return['blocked_code'] = $user->blocked_code;
|
||||||
|
$return['accounts'] = $user->accounts()->count();
|
||||||
|
$return['journals'] = $user->transactionJournals()->count();
|
||||||
|
$return['transactions'] = $user->transactions()->count();
|
||||||
|
$return['attachments'] = $user->attachments()->count();
|
||||||
|
$return['attachments_size'] = $user->attachments()->sum('size');
|
||||||
|
$return['bills'] = $user->bills()->count();
|
||||||
|
$return['categories'] = $user->categories()->count();
|
||||||
|
$return['budgets'] = $user->budgets()->count();
|
||||||
|
$return['budgets_with_limits'] = BudgetLimit
|
||||||
|
::distinct()
|
||||||
|
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||||
|
->where('amount', '>', 0)
|
||||||
|
->whereNull('budgets.deleted_at')
|
||||||
|
->where('budgets.user_id', $user->id)->get(['budget_limits.budget_id'])->count();
|
||||||
|
$return['export_jobs'] = $user->exportJobs()->count();
|
||||||
|
$return['export_jobs_success'] = $user->exportJobs()->where('status', 'export_downloaded')->count();
|
||||||
|
$return['import_jobs'] = $user->exportJobs()->count();
|
||||||
|
$return['import_jobs_success'] = $user->exportJobs()->where('status', 'import_complete')->count();
|
||||||
|
$return['rule_groups'] = $user->ruleGroups()->count();
|
||||||
|
$return['rules'] = $user->rules()->count();
|
||||||
|
$return['tags'] = $user->tags()->count();
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,15 @@ interface UserRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function all(): Collection;
|
public function all(): Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return basic user information.
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getUserData(User $user): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives a user a role.
|
* Gives a user a role.
|
||||||
*
|
*
|
||||||
|
@@ -280,7 +280,7 @@ return [
|
|||||||
'pref_home_show_deposits' => 'Show deposits on the home screen',
|
'pref_home_show_deposits' => 'Show deposits on the home screen',
|
||||||
'pref_home_show_deposits_info' => 'The home screen already shows your expense accounts. Should it also show your revenue accounts?',
|
'pref_home_show_deposits_info' => 'The home screen already shows your expense accounts. Should it also show your revenue accounts?',
|
||||||
'pref_home_do_show_deposits' => 'Yes, show them',
|
'pref_home_do_show_deposits' => 'Yes, show them',
|
||||||
|
'successful_count' => 'of which :count successful',
|
||||||
'transaction_page_size_title' => 'Page size',
|
'transaction_page_size_title' => 'Page size',
|
||||||
'transaction_page_size_help' => 'Any list of transactions shows at most this many transactions',
|
'transaction_page_size_help' => 'Any list of transactions shows at most this many transactions',
|
||||||
'transaction_page_size_label' => 'Page size',
|
'transaction_page_size_label' => 'Page size',
|
||||||
@@ -735,7 +735,15 @@ return [
|
|||||||
'setting_single_user_mode' => 'Single user mode',
|
'setting_single_user_mode' => 'Single user mode',
|
||||||
'setting_single_user_mode_explain' => 'By default, Firefly III only accepts one (1) registration: you. This is a security measure, preventing others from using your instance unless you allow them to. Future registrations are blocked. When you uncheck this box, others can use your instance as wel, assuming they can reach it (when it is connected to the internet).',
|
'setting_single_user_mode_explain' => 'By default, Firefly III only accepts one (1) registration: you. This is a security measure, preventing others from using your instance unless you allow them to. Future registrations are blocked. When you uncheck this box, others can use your instance as wel, assuming they can reach it (when it is connected to the internet).',
|
||||||
'store_configuration' => 'Store configuration',
|
'store_configuration' => 'Store configuration',
|
||||||
|
'single_user_administration' => 'User administration for :email',
|
||||||
'hidden_fields_preferences' => 'Not all fields are visible right now. You must enable them in your <a href=":link">settings</a>.',
|
'hidden_fields_preferences' => 'Not all fields are visible right now. You must enable them in your <a href=":link">settings</a>.',
|
||||||
|
'user_data_information' => 'User data',
|
||||||
|
'user_information' => 'User information',
|
||||||
|
'total_size' => 'total size',
|
||||||
|
'budget_or_budgets' => 'budget(s)',
|
||||||
|
'budgets_with_limits' => 'budget(s) with configured amount',
|
||||||
|
'rule_or_rules' => 'rule(s)',
|
||||||
|
'rulegroup_or_groups' => 'rule group(s)',
|
||||||
|
|
||||||
// split a transaction:
|
// split a transaction:
|
||||||
'transaction_meta_data' => 'Transaction meta-data',
|
'transaction_meta_data' => 'Transaction meta-data',
|
||||||
|
@@ -25,6 +25,7 @@ return [
|
|||||||
'matchedOn' => 'Matched on',
|
'matchedOn' => 'Matched on',
|
||||||
'matchesOn' => 'Matched on',
|
'matchesOn' => 'Matched on',
|
||||||
'account_type' => 'Account type',
|
'account_type' => 'Account type',
|
||||||
|
'created_at' => 'Created at',
|
||||||
'new_balance' => 'New balance',
|
'new_balance' => 'New balance',
|
||||||
'account' => 'Account',
|
'account' => 'Account',
|
||||||
'matchingAmount' => 'Amount',
|
'matchingAmount' => 'Amount',
|
||||||
@@ -71,4 +72,15 @@ return [
|
|||||||
'blocked_code' => 'Block code',
|
'blocked_code' => 'Block code',
|
||||||
'domain' => 'Domain',
|
'domain' => 'Domain',
|
||||||
'registration_attempts' => 'Registration attempts',
|
'registration_attempts' => 'Registration attempts',
|
||||||
|
|
||||||
|
'accounts_count' => 'Number of accounts',
|
||||||
|
'journals_count' => 'Number of journals',
|
||||||
|
'attachments_count' => 'Number of attachments',
|
||||||
|
'bills_count' => 'Number of bills',
|
||||||
|
'categories_count' => 'Number of categories',
|
||||||
|
'export_jobs_count' => 'Number of export jobs',
|
||||||
|
'import_jobs_count' => 'Number of import jobs',
|
||||||
|
'budget_count' => 'Number of budgets',
|
||||||
|
'rule_and_groups_count' => 'Number of rules and rule groups',
|
||||||
|
'tags_count' => 'Number of tags',
|
||||||
];
|
];
|
||||||
|
@@ -35,7 +35,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>#{{ user.id }}</td>
|
<td>#{{ user.id }}</td>
|
||||||
<td>{{ user.email }}</td>
|
<td>
|
||||||
|
<a href="{{ route('admin.users.show',user.id) }}">{{ user.email }}</a></td>
|
||||||
<td>
|
<td>
|
||||||
{{ user.created_at.formatLocalized(monthAndDayFormat) }}
|
{{ user.created_at.formatLocalized(monthAndDayFormat) }}
|
||||||
{{ user.created_at.format('H:i') }}
|
{{ user.created_at.format('H:i') }}
|
||||||
|
151
resources/views/admin/users/show.twig
Normal file
151
resources/views/admin/users/show.twig
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
{% extends "./layout/default.twig" %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, user) }}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||||
|
<div class="box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'user_information'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body table-responsive">
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.id') }}</td>
|
||||||
|
<td>#{{ user.id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.email') }}</td>
|
||||||
|
<td><a href="mailto:{{ user.email }}">{{ user.email }}</a>
|
||||||
|
<td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.created_at') }}</td>
|
||||||
|
<td>
|
||||||
|
{{ user.created_at.formatLocalized(monthAndDayFormat) }}
|
||||||
|
{{ user.created_at.format('H:i') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.registered_from') }}</td>
|
||||||
|
<td>{{ registration }} ({{ registrationHost }})</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.confirmed_from') }}</td>
|
||||||
|
<td>{{ confirmation }} ({{ confirmationHost }})</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.is_admin') }}</td>
|
||||||
|
<td>
|
||||||
|
{% if information.is_admin %}
|
||||||
|
<small class="text-success"><i class="fa fa-fw fa-check"></i></small> Yes
|
||||||
|
{% else %}
|
||||||
|
<small class="text-danger"><i class="fa fa-fw fa-times"></i></small> No
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.has_two_factor') }}</td>
|
||||||
|
<td>
|
||||||
|
{% if information.has_2fa %}
|
||||||
|
<small class="text-success"><i class="fa fa-fw fa-check"></i></small> Yes
|
||||||
|
{% else %}
|
||||||
|
<small class="text-danger"><i class="fa fa-fw fa-times"></i></small> No
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.is_activated') }}</td>
|
||||||
|
<td>
|
||||||
|
{% if information.activated %}
|
||||||
|
<small class="text-success"><i class="fa fa-fw fa-check"></i></small> Yes
|
||||||
|
{% else %}
|
||||||
|
<small class="text-danger"><i class="fa fa-fw fa-times"></i></small> No
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.is_blocked') }}</td>
|
||||||
|
<td>
|
||||||
|
{% if information.blocked == 1 %}
|
||||||
|
<small class="text-danger"><i class="fa fa-fw fa-check" title="{{ 'yes'|_ }}"></i></small> Yes:
|
||||||
|
|
||||||
|
{% if information.blocked_code == "" %}
|
||||||
|
<em>~</em>
|
||||||
|
{% else %}
|
||||||
|
{{ information.blocked_code }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<small class="text-success"><i class="fa fa-fw fa-times" title="{{ 'no'|_ }}"></i></small> No
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||||
|
<div class="box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'user_data_information'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body table-responsive">
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.accounts_count') }}</td>
|
||||||
|
<td>{{ information.accounts }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.journals_count') }}</td>
|
||||||
|
<td>{{ information.journals }} ({{ information.transactions }} {{ trans('firefly.transactions') }})</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.attachments_count') }}</td>
|
||||||
|
<td>{{ information.attachments }} ({{ trans('firefly.total_size') }}: {{ information.attachments_size|filesize }})</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.bills_count') }}</td>
|
||||||
|
<td>{{ information.bills }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.categories_count') }}</td>
|
||||||
|
<td>{{ information.categories }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.export_jobs_count') }}</td>
|
||||||
|
<td>{{ information.export_jobs }}, {{ trans('firefly.successful_count', {count: information.export_jobs_success}) }}
|
||||||
|
<!-- of which x successful --></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.import_jobs_count') }}</td>
|
||||||
|
<td>{{ information.import_jobs }}, {{ trans('firefly.successful_count', {count: information.import_jobs_success}) }}
|
||||||
|
<!-- of which x successful --></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.budget_count') }}</td>
|
||||||
|
<td>{{ information.budgets }} {{ trans('firefly.budget_or_budgets') }},
|
||||||
|
{{ information.budgets_with_limits }} {{ trans('firefly.budgets_with_limits') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.rule_and_groups_count') }}</td>
|
||||||
|
<td>
|
||||||
|
{{ information.rules }} {{ 'rule_or_rules'|_ }} {{ 'in'|_ }} {{ information.rule_groups }}
|
||||||
|
|
||||||
|
{{ 'rulegroup_or_groups'|_ }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.tags_count') }}</td>
|
||||||
|
<td>{{ information.tags }} tags</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@@ -435,6 +435,7 @@ Route::group(
|
|||||||
// user manager
|
// user manager
|
||||||
Route::get('/admin/users', ['uses' => 'Admin\UserController@index', 'as' => 'admin.users']);
|
Route::get('/admin/users', ['uses' => 'Admin\UserController@index', 'as' => 'admin.users']);
|
||||||
Route::get('/admin/users/edit/{user}', ['uses' => 'Admin\UserController@edit', 'as' => 'admin.users.edit']);
|
Route::get('/admin/users/edit/{user}', ['uses' => 'Admin\UserController@edit', 'as' => 'admin.users.edit']);
|
||||||
|
Route::get('/admin/users/show/{user}', ['uses' => 'Admin\UserController@show', 'as' => 'admin.users.show']);
|
||||||
|
|
||||||
// user domains:
|
// user domains:
|
||||||
Route::get('/admin/domains', ['uses' => 'Admin\DomainController@domains', 'as' => 'admin.users.domains']);
|
Route::get('/admin/domains', ['uses' => 'Admin\DomainController@domains', 'as' => 'admin.users.domains']);
|
||||||
|
Reference in New Issue
Block a user