Skip to content

Commit

Permalink
Merge pull request #32 from openfoodfoundation/feature/api-token-crea…
Browse files Browse the repository at this point in the history
…te-event

Feature: Added audit events for tokens / teams / team users
  • Loading branch information
ok200paul authored Aug 19, 2024
2 parents 012e890 + 70b2731 commit ebe2887
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 5 deletions.
36 changes: 36 additions & 0 deletions app/Events/PersonalAccessTokens/PersonalAccessTokenWasCreated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Events\PersonalAccessTokens;

use App\Models\PersonalAccessToken;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;

class PersonalAccessTokenWasCreated
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

/**
* Create a new event instance.
*
* @param PersonalAccessToken|SanctumPersonalAccessToken $personalAccessToken
*/
public function __construct(public PersonalAccessToken|SanctumPersonalAccessToken $personalAccessToken) {}

/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('channel-name'),
];
}
}
35 changes: 35 additions & 0 deletions app/Events/TeamUsers/TeamUserWasCreated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace App\Events\TeamUsers;

use App\Models\TeamUser;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class TeamUserWasCreated
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

/**
* Create a new event instance.
*
* @param TeamUser $teamUser
*/
public function __construct(public TeamUser $teamUser) {}

/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('channel-name'),
];
}
}
35 changes: 35 additions & 0 deletions app/Events/Teams/TeamWasCreated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace App\Events\Teams;

use App\Models\Team;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class TeamWasCreated
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

/**
* Create a new event instance.
*
* @param Team $team
*/
public function __construct(public Team $team) {}

/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('channel-name'),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use App\Enums\ApiResponse;
use App\Enums\PersonalAccessTokenAbility;
use App\Events\PersonalAccessTokens\PersonalAccessTokenWasCreated;
use App\Exceptions\DisallowedApiFieldException;
use App\Http\Controllers\Api\HandlesAPIRequests;
use App\Http\Controllers\Controller;
Expand Down Expand Up @@ -104,6 +105,8 @@ public function store(): JsonResponse
$this->message = ApiResponse::RESPONSE_SAVED->value;
$this->data = ['token' => $token->plainTextToken];

event(new PersonalAccessTokenWasCreated($token->accessToken));

}
catch (Exception $e) {

Expand Down
36 changes: 36 additions & 0 deletions app/Jobs/AuditItems/RecordPersonalAccessTokenWasCreated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Jobs\AuditItems;

use App\Models\PersonalAccessToken;
use App\Models\User;
use App\Services\AuditItemService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;

class RecordPersonalAccessTokenWasCreated implements ShouldQueue
{
use Queueable;

/**
* Create a new job instance.
*
* @param PersonalAccessToken|SanctumPersonalAccessToken $personalAccessToken
*/
public function __construct(public PersonalAccessToken|SanctumPersonalAccessToken $personalAccessToken) {}

/**
* Execute the job.
*/
public function handle(): void
{
$user = User::find($this->personalAccessToken->tokenable_id);

AuditItemService::createAuditItemForEvent(
model : $this->personalAccessToken,
eventText: 'Access token "' . $this->personalAccessToken->name . '" was created for user ' . $user->name . '.',
teamId : $user->current_team_id,
);
}
}
37 changes: 37 additions & 0 deletions app/Jobs/AuditItems/RecordTeamUserWasCreatedAuditItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace App\Jobs\AuditItems;

use App\Models\Team;
use App\Models\TeamUser;
use App\Models\User;
use App\Services\AuditItemService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class RecordTeamUserWasCreatedAuditItem implements ShouldQueue
{
use Queueable;

/**
* Create a new job instance.
*
* @param TeamUser $teamUser
*/
public function __construct(public TeamUser $teamUser) {}

/**
* Execute the job.
*/
public function handle(): void
{
$user = User::find($this->teamUser->user_id);
$team = Team::find($this->teamUser->team_id);

AuditItemService::createAuditItemForEvent(
model : $this->teamUser,
eventText: 'User ' . $user->name . ' was added to team "' . $team->name . '".',
teamId : $this->teamUser->team_id
);
}
}
32 changes: 32 additions & 0 deletions app/Jobs/AuditItems/RecordTeamWasCreatedAuditItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Jobs\AuditItems;

use App\Models\Team;
use App\Services\AuditItemService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class RecordTeamWasCreatedAuditItem implements ShouldQueue
{
use Queueable;

/**
* Create a new job instance.
*
* @param Team $team
*/
public function __construct(public Team $team) {}

/**
* Execute the job.
*/
public function handle(): void
{
AuditItemService::createAuditItemForEvent(
model : $this->team,
eventText: 'Team ' . $this->team->name . ' was created.',
teamId : $this->team->id
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\Jobs;
namespace App\Jobs\AuditItems;

use App\Models\User;
use App\Services\AuditItemService;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Listeners\PersonalAccessTokens;

use App\Events\PersonalAccessTokens\PersonalAccessTokenWasCreated;
use App\Jobs\AuditItems\RecordPersonalAccessTokenWasCreated;
use Illuminate\Contracts\Queue\ShouldQueue;

class HandlePersonalAccessTokenWasCreatedEvent implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct() {}

/**
* Handle the event.
*
* @param PersonalAccessTokenWasCreated $event
*/
public function handle(PersonalAccessTokenWasCreated $event): void
{
dispatch(new RecordPersonalAccessTokenWasCreated($event->personalAccessToken));
}
}
24 changes: 24 additions & 0 deletions app/Listeners/TeamUsers/HandleTeamUserWasCreatedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Listeners\TeamUsers;

use App\Events\TeamUsers\TeamUserWasCreated;
use App\Jobs\AuditItems\RecordTeamUserWasCreatedAuditItem;

class HandleTeamUserWasCreatedEvent
{
/**
* Create the event listener.
*/
public function __construct() {}

/**
* Handle the event.
*
* @param TeamUserWasCreated $event
*/
public function handle(TeamUserWasCreated $event): void
{
dispatch(new RecordTeamUserWasCreatedAuditItem($event->teamUser));
}
}
25 changes: 25 additions & 0 deletions app/Listeners/Teams/HandleTeamWasCreatedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Listeners\Teams;

use App\Events\Teams\TeamWasCreated;
use App\Jobs\AuditItems\RecordTeamWasCreatedAuditItem;
use Illuminate\Contracts\Queue\ShouldQueue;

class HandleTeamWasCreatedEvent implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct() {}

/**
* Handle the event.
*
* @param TeamWasCreated $event
*/
public function handle(TeamWasCreated $event): void
{
dispatch(new RecordTeamWasCreatedAuditItem($event->team));
}
}
2 changes: 1 addition & 1 deletion app/Listeners/Users/HandleUserWasCreatedEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace App\Listeners\Users;

use App\Events\Users\UserWasCreated;
use App\Jobs\RecordUserWasCreatedAuditItem;
use App\Jobs\AuditItems\RecordUserWasCreatedAuditItem;

class HandleUserWasCreatedEvent
{
Expand Down
12 changes: 12 additions & 0 deletions app/Models/AuditItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;

class AuditItem extends Model
{
Expand Down Expand Up @@ -44,6 +45,9 @@ public function dashboardUrl(): Attribute
switch ($this->auditable_type) {
case User::class:
case Team::class:
case PersonalAccessToken::class:
case SanctumPersonalAccessToken::class:
case TeamUser::class:
$url = '/my-team';
break;
}
Expand All @@ -68,6 +72,14 @@ public function adminUrl(): Attribute
case Team::class:
$url = '/admin/team/' . $this->auditable_id;
break;
case TeamUser::class:
$url = '/admin/team/' . $this->auditable->team_id;
break;
case PersonalAccessToken::class:
case SanctumPersonalAccessToken::class:
$url = '/admin/api-access-token/' . $this->auditable_id;
break;

}

return Attribute::make(
Expand Down
5 changes: 5 additions & 0 deletions app/Models/PersonalAccessToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Models;

use App\Events\PersonalAccessTokens\PersonalAccessTokenWasCreated;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;

Expand All @@ -23,6 +24,10 @@ class PersonalAccessToken extends SanctumPersonalAccessToken
'team_id',
];

protected $dispatchesEvents = [
'created' => PersonalAccessTokenWasCreated::class,
];

public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'tokenable_id', 'id');
Expand Down
5 changes: 5 additions & 0 deletions app/Models/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Models;

use App\Events\Teams\TeamWasCreated;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
Expand All @@ -13,6 +14,10 @@ class Team extends Model
use HasFactory;
use SoftDeletes;

protected $dispatchesEvents = [
'created' => TeamWasCreated::class,
];

public function teamUsers(): HasMany
{
return $this->hasMany(TeamUser::class, 'team_id', 'id');
Expand Down
Loading

0 comments on commit ebe2887

Please sign in to comment.