Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix translations for activity logs #907

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ public function table(Table $table): Table
->columns([
TextColumn::make('event')
->html()
->formatStateUsing(fn ($state, ActivityLog $activityLog) => __('activity.'.str($state)->replace(':', '.'))) // TODO: convert properties to a format that trans likes, see ActivityLogEntry.tsx - wrapProperties
->formatStateUsing(function ($state, ActivityLog $activityLog) {
$properties = $activityLog->wrapProperties();

return trans_choice('activity.'.str($state)->replace(':', '.'), array_key_exists('count', $properties) ? $properties['count'] : 1, $properties);
})
Boy132 marked this conversation as resolved.
Show resolved Hide resolved
->description(fn ($state) => $state),
TextColumn::make('user')
->state(fn (ActivityLog $activityLog) => $activityLog->actor instanceof User ? $activityLog->actor->username : 'System')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ public function table(Table $table): Table

Activity::event('server:file.rename')
->property('directory', $this->path)
->property('files', [['to' => $location, 'from' => $file->name]])
->property('to', $location)
->property('from', $file->name)
->log();

Notification::make()
Expand Down
8 changes: 6 additions & 2 deletions app/Http/Controllers/Api/Client/Servers/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,17 @@ public function create(CreateFolderRequest $request, Server $server): JsonRespon
*/
public function rename(RenameFileRequest $request, Server $server): JsonResponse
{
$files = $request->input('files');

$this->fileRepository
->setServer($server)
->renameFiles($request->input('root'), $request->input('files'));
->renameFiles($request->input('root'), $files);

Activity::event('server:file.rename')
->property('directory', $request->input('root'))
->property('files', $request->input('files'))
->property('files', $files)
->property('to', $files['to'])
->property('from', $files['from'])
->log();

return new JsonResponse([], Response::HTTP_NO_CONTENT);
Expand Down
32 changes: 30 additions & 2 deletions app/Models/ActivityLog.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Model as IlluminateModel;
use Illuminate\Support\Str;

/**
* \App\Models\ActivityLog.
Expand Down Expand Up @@ -156,8 +157,8 @@ public function htmlable(): string
'username' => 'system',
]);
}

$event = __('activity.'.str($this->event)->replace(':', '.'));
$properties = $this->wrapProperties();
$event = trans_choice('activity.'.str($this->event)->replace(':', '.'), array_key_exists('count', $properties) ? $properties['count'] : 1, $properties);

return "
<div style='display: flex; align-items: center;'>
Expand All @@ -171,4 +172,31 @@ public function htmlable(): string
</div>
";
}

public function wrapProperties(): array
{
if (!$this->properties || $this->properties->isEmpty()) {
return [];
}

$properties = $this->properties->mapWithKeys(function ($value, $key) {
if (!is_array($value)) {
// Perform some directory normalization at this point.
if ($key === 'directory') {
$value = str_replace('//', '/', '/' . trim($value, '/') . '/');
}

return [$key => $value];
}

return [Str::singular($key) => array_first($value), "{$key}_count" => count($value)];
});

$keys = $properties->keys()->filter(fn ($key) => Str::endsWith($key, '_count'))->values();
if ($keys->containsOneItem()) {
$properties = $properties->merge(['count' => $properties->get($keys[0])])->except([$keys[0]]);
}

return $properties->toArray();
}
}
39 changes: 1 addition & 38 deletions app/Transformers/Api/Client/ActivityLogTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace App\Transformers\Api\Client;

use Illuminate\Support\Str;
use App\Models\User;
use App\Models\ActivityLog;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -29,7 +28,7 @@ public function transform(ActivityLog $model): array
'is_api' => !is_null($model->api_key_id),
'ip' => $this->canViewIP($model->actor) ? $model->ip : null,
'description' => $model->description,
'properties' => $this->properties($model),
'properties' => $model->wrapProperties(),
'has_additional_metadata' => $this->hasAdditionalMetadata($model),
'timestamp' => $model->timestamp->toAtomString(),
];
Expand All @@ -44,42 +43,6 @@ public function includeActor(ActivityLog $model): ResourceAbstract
return $this->item($model->actor, $this->makeTransformer(UserTransformer::class), User::RESOURCE_NAME);
}

/**
* Transforms any array values in the properties into a countable field for easier
* use within the translation outputs.
*/
protected function properties(ActivityLog $model): object
{
if (!$model->properties || $model->properties->isEmpty()) {
return (object) [];
}

$properties = $model->properties
->mapWithKeys(function ($value, $key) use ($model) {
if ($key === 'ip' && $model->actor instanceof User && !$model->actor->is($this->request->user())) {
return [$key => '[hidden]'];
}

if (!is_array($value)) {
// Perform some directory normalization at this point.
if ($key === 'directory') {
$value = str_replace('//', '/', '/' . trim($value, '/') . '/');
}

return [$key => $value];
}

return [$key => $value, "{$key}_count" => count($value)];
});

$keys = $properties->keys()->filter(fn ($key) => Str::endsWith($key, '_count'))->values();
if ($keys->containsOneItem()) {
$properties = $properties->merge(['count' => $properties->get($keys[0])])->except([$keys[0]]);
}

return (object) $properties->toArray();
}

/**
* Determines if there are any log properties that we've not already exposed
* in the response language string and that are not just the IP address or
Expand Down
56 changes: 24 additions & 32 deletions lang/en/activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
'checkpoint' => 'Two-factor authentication requested',
'recovery-token' => 'Used two-factor recovery token',
'token' => 'Solved two-factor challenge',
'ip-blocked' => 'Blocked request from unlisted IP address for :identifier',
'ip-blocked' => 'Blocked request from unlisted IP address for <b>:identifier</b>',
'sftp' => [
'fail' => 'Failed SFTP log in',
],
Expand All @@ -26,12 +26,12 @@
'password-changed' => 'Changed password',
],
'api-key' => [
'create' => 'Created new API key :identifier',
'delete' => 'Deleted API key :identifier',
'create' => 'Created new API key <b>:identifier</b>',
'delete' => 'Deleted API key <b>:identifier</b>',
],
'ssh-key' => [
'create' => 'Added SSH key :fingerprint to account',
'delete' => 'Removed SSH key :fingerprint from account',
'create' => 'Added SSH key <b>:fingerprint</b> to account',
'delete' => 'Removed SSH key <b>:fingerprint</b> from account',
],
'two-factor' => [
'create' => 'Enabled two-factor auth',
Expand All @@ -41,7 +41,7 @@
'server' => [
'reinstall' => 'Reinstalled server',
'console' => [
'command' => 'Executed ":command" on the server',
'command' => 'Executed "<b>:command</b>" on the server',
],
'power' => [
'start' => 'Started the server',
Expand All @@ -67,39 +67,31 @@
'delete' => 'Deleted database <b>:name</b>',
],
'file' => [
'compress_one' => 'Compressed :directory:file',
'compress_other' => 'Compressed :count files in :directory',
'read' => 'Viewed the contents of :file',
'copy' => 'Created a copy of :file',
'create-directory' => 'Created directory :directory<b>:name</b>',
'decompress' => 'Decompressed :files in :directory',
'delete_one' => 'Deleted :directory:files.0',
'delete_other' => 'Deleted :count files in :directory',
'download' => 'Downloaded :file',
'pull' => 'Downloaded a remote file from :url to :directory',
'rename_one' => 'Renamed :directory:files.0.from to :directory:files.0.to',
'rename_other' => 'Renamed :count files in :directory',
'write' => 'Wrote new content to :file',
'compress' => 'Compressed <b>:directory:file</b>|Compressed <b>:count</b> files in <b>:directory</b>',
'read' => 'Viewed the contents of <b>:file</b>',
'copy' => 'Created a copy of <b>:file</b>',
'create-directory' => 'Created directory <b>:directory:name</b>',
'decompress' => 'Decompressed <b>:file</b> in <b>:directory</b>',
'delete' => 'Deleted <b>:directory:file</b>|Deleted <b>:count</b> files in <b>:directory</b>',
'download' => 'Downloaded <b>:file</b>',
'pull' => 'Downloaded a remote file from <b>:url</b> to <b>:directory</b>',
'rename' => 'Renamed <b>:directory:from</b> to <b>:directory:to</b>|Renamed <b>:count</b> files in <b>:directory</b>',
'write' => 'Wrote new content to <b>:file</b>',
'upload' => 'Began a file upload',
'uploaded' => 'Uploaded :directory:file',
'uploaded' => 'Uploaded <b>:directory:file</b>',
],
'sftp' => [
'denied' => 'Blocked SFTP access due to permissions',
'create_one' => 'Created :files.0',
'create_other' => 'Created :count new files',
'write_one' => 'Modified the contents of :files.0',
'write_other' => 'Modified the contents of :count files',
'delete_one' => 'Deleted :files.0',
'delete_other' => 'Deleted :count files',
'create-directory_one' => 'Created the :files.0 directory',
'create-directory_other' => 'Created :count directories',
'rename_one' => 'Renamed :files.0.from to :files.0.to',
'rename_other' => 'Renamed or moved :count files',
'create' => 'Created <b>:file</b>|Created <b>:count</b> new files',
'write' => 'Modified the contents of <b>:file</b>|Modified the contents of <b>:count</b> files',
'delete' => 'Deleted <b>:file</b>|Deleted <b>:count</b> files',
'create-directory' => 'Created the :file</b> directory|Created <b>:count</b> directories',
'rename' => 'Renamed <b>:from</b> to <b>:to</b>|Renamed or moved <b>:count</b> files',
],
'allocation' => [
'create' => 'Added :allocation to the server',
'notes' => 'Updated the notes for :allocation from "<b>:old</b>" to "<b>:new</b>"',
'primary' => 'Set :allocation as the primary server allocation',
'notes' => 'Updated the notes for <b>:allocation</b> from "<b>:old</b>" to "<b>:new</b>"',
'primary' => 'Set <b>:allocation</b> as the primary server allocation',
'delete' => 'Deleted the :allocation allocation',
],
'schedule' => [
Expand Down
Loading