add event users

This commit is contained in:
2023-05-11 16:49:12 +10:00
parent fc853bd5f1
commit c471a97a23
9 changed files with 242 additions and 30 deletions

View File

@@ -301,7 +301,7 @@ class Conductor
$transformedCollection = collect(); $transformedCollection = collect();
foreach ($collection as $item) { foreach ($collection as $item) {
if ($conductor->viewable($item)) { if ($conductor->viewable($item) === true) {
$transformedCollection->push($conductor->transformModel($item)); $transformedCollection->push($conductor->transformModel($item));
} }
} }

View File

@@ -106,8 +106,12 @@ class EventConductor extends Conductor
*/ */
public function includeAttachments(Model $model) public function includeAttachments(Model $model)
{ {
return $model->attachments()->get()->map(function ($attachment) { $user = auth()->user();
return MediaConductor::includeModel(request(), 'attachments', $attachment->media);
return $model->attachments()->get()->map(function ($attachment) use ($user) {
if ($attachment->private === false || ($user !== null && ($user->hasPermission('admin/events') === true || $attachment->users->contains($user) === true))) {
return MediaConductor::includeModel(request(), 'attachments', $attachment->media);
}
}); });
} }

View File

@@ -6,8 +6,10 @@ use App\Enum\HttpResponseCodes;
use App\Models\Event; use App\Models\Event;
use App\Conductors\EventConductor; use App\Conductors\EventConductor;
use App\Conductors\MediaConductor; use App\Conductors\MediaConductor;
use App\Conductors\UserConductor;
use App\Http\Requests\EventRequest; use App\Http\Requests\EventRequest;
use App\Models\Media; use App\Models\Media;
use App\Models\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class EventController extends ApiController class EventController extends ApiController
@@ -18,7 +20,7 @@ class EventController extends ApiController
public function __construct() public function __construct()
{ {
$this->middleware('auth:sanctum') $this->middleware('auth:sanctum')
->only(['store','update','destroy']); ->only(['store','update','destroy', 'userAdd', 'userUpdate', 'userDelete']);
} }
/** /**
@@ -111,11 +113,8 @@ class EventController extends ApiController
* Get a list of attachments related to this model. * Get a list of attachments related to this model.
* *
* @param Request $request The user request. * @param Request $request The user request.
* @param Article $article The article model. * @param Event $event The event model.
* @return JsonResponse Returns the article attachments. * @return JsonResponse Returns the event attachments.
* @throws InvalidFormatException
* @throws BindingResolutionException
* @throws InvalidCastException
*/ */
public function getAttachments(Request $request, Event $event) public function getAttachments(Request $request, Event $event)
{ {
@@ -134,15 +133,13 @@ class EventController extends ApiController
* Store an attachment related to this model. * Store an attachment related to this model.
* *
* @param Request $request The user request. * @param Request $request The user request.
* @param Article $article The article model. * @param Event $event The event model.
* @return JsonResponse The response. * @return JsonResponse The response.
* @throws BindingResolutionException
* @throws MassAssignmentException
*/ */
public function storeAttachment(Request $request, Event $event) public function storeAttachment(Request $request, Event $event)
{ {
if (EventConductor::updatable($event) === true) { if (EventConductor::updatable($event) === true) {
if ($request->has("medium") && Media::find($request->medium)) { if ($request->has("medium") === true && Media::find($request->medium) !== null) {
$event->attachments()->create(['media_id' => $request->medium]); $event->attachments()->create(['media_id' => $request->medium]);
return $this->respondCreated(); return $this->respondCreated();
} }
@@ -157,10 +154,8 @@ class EventController extends ApiController
* Update/replace attachments related to this model. * Update/replace attachments related to this model.
* *
* @param Request $request The user request. * @param Request $request The user request.
* @param Article $article The related model. * @param Event $event The related model.
* @return JsonResponse * @return JsonResponse
* @throws BindingResolutionException
* @throws MassAssignmentException
*/ */
public function updateAttachments(Request $request, Event $event) public function updateAttachments(Request $request, Event $event)
{ {
@@ -175,7 +170,7 @@ class EventController extends ApiController
// Delete attachments that are not in $mediaIds // Delete attachments that are not in $mediaIds
foreach ($attachments as $attachment) { foreach ($attachments as $attachment) {
if (!in_array($attachment->media_id, $mediaIds)) { if (in_array($attachment->media_id, $mediaIds) === false) {
$attachment->delete(); $attachment->delete();
} }
} }
@@ -185,13 +180,13 @@ class EventController extends ApiController
$found = false; $found = false;
foreach ($attachments as $attachment) { foreach ($attachments as $attachment) {
if ($attachment->media_id == $mediaId) { if ($attachment->media_id === $mediaId) {
$found = true; $found = true;
break; break;
} }
} }
if (!$found) { if ($found === false) {
$event->attachments()->create(['media_id' => $mediaId]); $event->attachments()->create(['media_id' => $mediaId]);
} }
} }
@@ -204,11 +199,11 @@ class EventController extends ApiController
/** /**
* Delete a specific related attachment. * Delete a specific related attachment.
*
* @param Request $request The user request. * @param Request $request The user request.
* @param Article $article The model. * @param Event $event The model.
* @param Media $medium The attachment medium. * @param Media $medium The attachment medium.
* @return JsonResponse * @return JsonResponse
* @throws BindingResolutionException
*/ */
public function deleteAttachment(Request $request, Event $event, Media $medium) public function deleteAttachment(Request $request, Event $event, Media $medium)
{ {
@@ -224,7 +219,7 @@ class EventController extends ApiController
} }
} }
if ($deleted) { if ($deleted === true) {
// Attachment was deleted successfully // Attachment was deleted successfully
return $this->respondNoContent(); return $this->respondNoContent();
} else { } else {
@@ -235,4 +230,82 @@ class EventController extends ApiController
return $this->respondForbidden(); return $this->respondForbidden();
} }
public function userList(Request $request, Event $event)
{
$authUser = $request->user();
$eventUsers = $event->users;
if ($authUser !== null) {
$isAdmin = $authUser->hasPermission('admin/events');
$isEventUser = $eventUsers->contains($authUser->id);
if ($isAdmin === true || $isEventUser === true) {
if ($isAdmin === false) {
$eventUsers = $eventUsers->filter(function ($user) use ($authUser) {
return $user->id === $authUser->id;
});
}
return $this->respondAsResource(UserConductor::collection($request, $eventUsers), ['isCollection' => true, 'resourceName' => 'users']);
}
return $this->respondNotFound();
}
return $this->respondForbidden();
}
public function userAdd(Request $request, Event $event)
{
$authUser = $request->user();
if ($authUser !== null && $authUser->hasPermission('admin/events') === true) {
if ($request->has("users") === true) {
$eventUsers = $event->users()->pluck('user_id')->toArray(); // Get the current users in the event
$requestedUsers = $request->input("users"); // Get the requested users
$usersToAdd = array_diff($requestedUsers, $eventUsers); // Users to add
$usersToRemove = array_diff($eventUsers, $requestedUsers); // Users to remove
// Add missing users
foreach ($usersToAdd as $userToAdd) {
if (User::find($userToAdd) !== null) {
$event->users()->attach($userToAdd);
}
}
// Remove extra users
foreach ($usersToRemove as $userToRemove) {
$event->users()->detach($userToRemove);
}
return $this->respondNoContent();
}//end if
return $this->respondWithErrors(['users' => 'The user list was not found']);
}//end if
return $this->respondForbidden();
}
public function userUpdate(Request $request, Event $event)
{
// only admin/events permitted
}
public function userDelete(Request $request, Event $event, User $user)
{
$authUser = $request->user();
if ($authUser !== null && $authUser->hasPermission('admin/events') === true) {
$eventUsers = $event->users;
if ($eventUsers->find($user->id) !== null) {
$eventUsers->detach($user->id);
return $this->respondNoContent();
} else {
return $this->respondNotFound();
}
}
return $this->respondForbidden();
}
} }

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Conductors\EventConductor;
use App\Enum\HttpResponseCodes; use App\Enum\HttpResponseCodes;
use App\Http\Requests\UserRequest; use App\Http\Requests\UserRequest;
use App\Http\Requests\UserForgotPasswordRequest; use App\Http\Requests\UserForgotPasswordRequest;
@@ -20,6 +21,8 @@ use App\Models\UserCode;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use App\Conductors\UserConductor; use App\Conductors\UserConductor;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\Container\BindingResolutionException;
class UserController extends ApiController class UserController extends ApiController
{ {
@@ -37,7 +40,8 @@ class UserController extends ApiController
'forgotPassword', 'forgotPassword',
'resetPassword', 'resetPassword',
'verifyEmail', 'verifyEmail',
'resendVerifyEmailCode' 'resendVerifyEmailCode',
'eventList',
]); ]);
} }
@@ -330,4 +334,29 @@ class UserController extends ApiController
return $this->respondNotFound(); return $this->respondNotFound();
} }
/**
* Return a JSON event list of a user.
*
* @param Request $request The http request.
* @param User $user The specified user.
* @return JsonResponse
*/
public function eventList(Request $request, User $user)
{
if ($request->user() !== null && ($request->user() === $user || $request->user()->hasPermission('admin/events') === true)) {
$collection = $user->events;
$total = $collection->count();
$collection = EventConductor::collection($request, $collection);
return $this->respondAsResource(
$collection,
['isCollection' => true,
'appendData' => ['total' => $total]
]
);
} else {
return $this->respondForbidden();
}
}
} }

View File

@@ -5,6 +5,8 @@ namespace App\Models;
use App\Traits\Uuids; use App\Traits\Uuids;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Event extends Model class Event extends Model
{ {
@@ -36,9 +38,21 @@ class Event extends Model
/** /**
* Get all of the article's attachments. * Get all of the article's attachments.
*
* @return MorphMany
*/ */
public function attachments() public function attachments()
{ {
return $this->morphMany('App\Models\Attachment', 'attachable'); return $this->morphMany('App\Models\Attachment', 'attachable');
} }
/**
* Get all the associated users.
*
* @return BelongsToMany
*/
public function users()
{
return $this->belongsToMany(User::class, 'event_user', 'event_id', 'user_id');
}
} }

44
app/Models/EventUsers.php Normal file
View File

@@ -0,0 +1,44 @@
<?php
namespace App\Models;
use App\Traits\Uuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class EventUser extends Model
{
use HasFactory;
use Uuids;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'event_id',
'user_id',
];
/**
* Get the event for this attachment.
*
* @return BelongsTo
*/
public function event()
{
return $this->belongsTo(Event::class);
}
/**
* Get the user for this attachment.
*
* @return BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@@ -6,6 +6,7 @@ namespace App\Models;
use App\Traits\Uuids; use App\Traits\Uuids;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\HasApiTokens;
@@ -76,11 +77,6 @@ class User extends Authenticatable implements Auditable
]; ];
// public function getPermissionsAttribute() {
// return $this->permissions()->pluck('permission')->toArray();
// }
/** /**
* Get the list of files of the user * Get the list of files of the user
* *
@@ -120,7 +116,7 @@ class User extends Authenticatable implements Auditable
*/ */
public function givePermission($permissions) public function givePermission($permissions)
{ {
if (!is_array($permissions)) { if (is_array($permissions) === false) {
$permissions = [$permissions]; $permissions = [$permissions];
} }
@@ -145,7 +141,7 @@ class User extends Authenticatable implements Auditable
*/ */
public function revokePermission($permissions) public function revokePermission($permissions)
{ {
if (!is_array($permissions)) { if (is_array($permissions) === false) {
$permissions = [$permissions]; $permissions = [$permissions];
} }
@@ -193,4 +189,14 @@ class User extends Authenticatable implements Auditable
{ {
return $this->hasMany(UserLogins::class); return $this->hasMany(UserLogins::class);
} }
/**
* Get the events associated with the user.
*
* @return BelongsToMany
*/
public function events()
{
return $this->belongsToMany(Event::class, 'event_user', 'user_id', 'event_id');
}
} }

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('event_users', function (Blueprint $table) {
$table->id();
$table->uuid('event_id');
$table->uuid('user_id');
$table->timestamps();
$table->foreign('event_id')->references('id')->on('event')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('user')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('event_users');
}
};

View File

@@ -34,6 +34,7 @@ Route::post('/users/forgotPassword', [UserController::class, 'forgotPassword']);
Route::post('/users/resetPassword', [UserController::class, 'resetPassword']); Route::post('/users/resetPassword', [UserController::class, 'resetPassword']);
Route::post('/users/resendVerifyEmailCode', [UserController::class, 'resendVerifyEmailCode']); Route::post('/users/resendVerifyEmailCode', [UserController::class, 'resendVerifyEmailCode']);
Route::post('/users/verifyEmail', [UserController::class, 'verifyEmail']); Route::post('/users/verifyEmail', [UserController::class, 'verifyEmail']);
Route::get('/users/{user}/events', [UserController::class, 'eventList']);
Route::apiResource('media', MediaController::class); Route::apiResource('media', MediaController::class);
Route::get('media/{medium}/download', [MediaController::class, 'download']); Route::get('media/{medium}/download', [MediaController::class, 'download']);
@@ -44,6 +45,11 @@ Route::apiAttachmentResource('articles', ArticleController::class);
Route::apiResource('events', EventController::class); Route::apiResource('events', EventController::class);
Route::apiAttachmentResource('events', EventController::class); Route::apiAttachmentResource('events', EventController::class);
Route::get('/events/{event}/users', [EventController::class, 'userList']);
Route::post('/events/{event}/users', [EventController::class, 'userAdd']);
Route::match(['put', 'patch'], '/events/{event}/users', [EventController::class, 'userUpdate']);
Route::delete('/events/{event}/users/{user}', [EventController::class, 'userDelete']);
Route::post('/contact', [ContactController::class, 'send']); Route::post('/contact', [ContactController::class, 'send']);
Route::apiResource('/shortlinks', ShortlinkController::class); Route::apiResource('/shortlinks', ShortlinkController::class);