masoud
4 years ago
20 changed files with 490 additions and 118 deletions
-
5.env.example
-
203app/Console/Commands/CostCommand.php
-
38app/Events/ModelSaved.php
-
110app/Http/Controllers/ActivityController.php
-
1app/Http/Controllers/AuthController.php
-
2app/Http/Resources/TaskResource.php
-
73app/Listeners/ActivityRegistration.php
-
31app/Models/Activity.php
-
33app/Models/Model.php
-
2app/Models/Task.php
-
4app/Models/User.php
-
5app/Providers/EventServiceProvider.php
-
5composer.json
-
2config/app.php
-
2database/factories/BusinessFactory.php
-
4database/migrations/2020_08_18_085017_fingerprints.php
-
2database/migrations/2020_08_18_085018_create_businesses_table.php
-
45database/migrations/2021_03_06_085855_create_activities_table.php
-
36database/migrations/2021_03_06_114918_create_failed_jobs_table.php
-
5routes/api.php
@ -0,0 +1,38 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Events; |
||||
|
|
||||
|
use Illuminate\Broadcasting\Channel; |
||||
|
use Illuminate\Broadcasting\InteractsWithSockets; |
||||
|
use Illuminate\Broadcasting\PresenceChannel; |
||||
|
use Illuminate\Broadcasting\PrivateChannel; |
||||
|
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; |
||||
|
use Illuminate\Foundation\Events\Dispatchable; |
||||
|
use Illuminate\Queue\SerializesModels; |
||||
|
|
||||
|
class ModelSaved |
||||
|
{ |
||||
|
use Dispatchable, InteractsWithSockets, SerializesModels; |
||||
|
|
||||
|
public $message; |
||||
|
|
||||
|
/** |
||||
|
* Create a new event instance. |
||||
|
* |
||||
|
* @return void |
||||
|
*/ |
||||
|
public function __construct($message) |
||||
|
{ |
||||
|
$this->message = $message; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the channels the event should broadcast on. |
||||
|
* |
||||
|
* @return \Illuminate\Broadcasting\Channel|array |
||||
|
*/ |
||||
|
public function broadcastOn() |
||||
|
{ |
||||
|
return new PrivateChannel('channel-name'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,110 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Http\Controllers; |
||||
|
|
||||
|
use App\Models\Activity; |
||||
|
use App\Rules\MaxBound; |
||||
|
use Illuminate\Http\Request; |
||||
|
use Spatie\QueryBuilder\AllowedFilter; |
||||
|
use Spatie\QueryBuilder\QueryBuilder; |
||||
|
|
||||
|
class ActivityController extends Controller |
||||
|
{ |
||||
|
public function index($business, Request $request) |
||||
|
{ |
||||
|
permit('businessAccess'); |
||||
|
$this->indexValidation($request); |
||||
|
$per_page = $request->limit > 100 ? 10 : $request->limit; |
||||
|
return $this->indexFiltering($business)->paginate($per_page); |
||||
|
} |
||||
|
|
||||
|
public function indexValidation($request) |
||||
|
{ |
||||
|
$bound = 10; |
||||
|
$this->validate($request, [ |
||||
|
'filter.project_id' => [new MaxBound($bound)] , |
||||
|
'filter.system_id' => [new MaxBound($bound)] , |
||||
|
'filter.workflow_id' => [new MaxBound($bound)] , |
||||
|
'filter.status_id' => [new MaxBound($bound)] , |
||||
|
'filter.sprint_id' => [new MaxBound($bound)] , |
||||
|
'filter.actor_id' => [new MaxBound($bound)] , |
||||
|
'filter.user_id' => [new MaxBound($bound)] , |
||||
|
'filter.subject_id' => [new MaxBound($bound)] , |
||||
|
//todo: validation for crud_id and table_id
|
||||
|
'filter.creates_before' => 'bail|nullable|date|date_format:Y-m-d' , |
||||
|
'filter.creates_after' => 'bail|nullable|date|date_format:Y-m-d' , |
||||
|
'filter.creates_in' => 'bail|nullable|numeric|max:90' , |
||||
|
]); |
||||
|
} |
||||
|
public function indexFiltering($business) |
||||
|
{ |
||||
|
$query = Activity::where('business_id', $business); |
||||
|
$activityQ = QueryBuilder::for($query) |
||||
|
->allowedFilters([ |
||||
|
AllowedFilter::exact('project_id'), |
||||
|
AllowedFilter::exact('system_id'), |
||||
|
AllowedFilter::exact('workflow_id'), |
||||
|
AllowedFilter::exact('status_id'), |
||||
|
AllowedFilter::exact('sprint_id'), |
||||
|
AllowedFilter::exact('task_id'), |
||||
|
AllowedFilter::exact('actor_id'), |
||||
|
AllowedFilter::exact('user_id'), |
||||
|
AllowedFilter::exact('crud_id'), |
||||
|
AllowedFilter::exact('table_id'), |
||||
|
AllowedFilter::exact('subject_id'), |
||||
|
AllowedFilter::scope('creates_before'), |
||||
|
AllowedFilter::scope('creates_after'), |
||||
|
AllowedFilter::scope('creates_in'), |
||||
|
]) |
||||
|
->defaultSort('-id') |
||||
|
->allowedSorts('id', 'created_at'); |
||||
|
if (\request('_business_info')['info']['users'][\auth()->id()]['level'] != enum('levels.owner.id')) { |
||||
|
$requested_projects = isset(\request('filter')['project_id']) ? |
||||
|
array_unique(explode(',',\request('filter')['project_id'] ?? null )) : |
||||
|
null; |
||||
|
$requested_projects = collect($requested_projects)->keyBy(null)->toArray(); |
||||
|
$project_ids = $this->myStateProjects($requested_projects); |
||||
|
$activityQ->where(function ($q) use ($project_ids) { |
||||
|
$q->whereIn('project_id', $project_ids['non_guest_ids']) |
||||
|
->orWhere(function ($q) use ($project_ids) { |
||||
|
$q->whereIn('project_id', $project_ids['guest_ids']) |
||||
|
->where('user_id', auth()->id()); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
return $activityQ; |
||||
|
} |
||||
|
|
||||
|
public function myStateProjects($requested_projects) |
||||
|
{ |
||||
|
$non_guest_ids = []; |
||||
|
$guest_ids = []; |
||||
|
$is_empty = empty($requested_projects); |
||||
|
|
||||
|
foreach (\request('_business_info')['info']['projects'] as $p_id => $p) { |
||||
|
|
||||
|
$level = \request('_business_info')['info']['projects'][$p_id]['members'][\auth()->id()]['level']; |
||||
|
|
||||
|
if (( $is_empty || isset($requested_projects[$p_id])) |
||||
|
&& $level > enum('levels.guest.id')) { |
||||
|
array_push($non_guest_ids, $p_id); |
||||
|
} |
||||
|
if (( $is_empty || isset($requested_projects[$p_id])) |
||||
|
&& $level == enum('levels.guest.id')) { |
||||
|
array_push($guest_ids, $p_id); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ['non_guest_ids' => $non_guest_ids, 'guest_ids' => $guest_ids]; |
||||
|
} |
||||
|
|
||||
|
public function store($business, Request $request) |
||||
|
{ |
||||
|
return Activity::create($request->merge(['business_id' => $business])->all()); |
||||
|
} |
||||
|
|
||||
|
public function delete() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,73 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Listeners; |
||||
|
|
||||
|
use App\Events\ModelSaved; |
||||
|
use App\Models\Activity; |
||||
|
use Illuminate\Contracts\Queue\ShouldQueue; |
||||
|
use Illuminate\Queue\InteractsWithQueue; |
||||
|
use Illuminate\Support\Facades\Log; |
||||
|
|
||||
|
class ActivityRegistration implements ShouldQueue |
||||
|
{ |
||||
|
/** |
||||
|
* If your queue connection's after_commit configuration option is set to true, |
||||
|
* indicate that a particular queued listener should be dispatched after all database transactions closed |
||||
|
* |
||||
|
* @var boolean |
||||
|
*/ |
||||
|
public $afterCommit = true; |
||||
|
|
||||
|
/** |
||||
|
* The name of the connection the job should be sent to. |
||||
|
* |
||||
|
* @var string|null |
||||
|
*/ |
||||
|
public $connection = 'redis'; |
||||
|
|
||||
|
/** |
||||
|
* The name of the queue the job should be sent to. |
||||
|
* It's just a name and if don't set it, laravel use default queue name in the connection |
||||
|
* |
||||
|
* @var string|null |
||||
|
*/ |
||||
|
public $queue = 'activities'; |
||||
|
|
||||
|
/** |
||||
|
* Create the event listener. |
||||
|
* |
||||
|
* @return void |
||||
|
*/ |
||||
|
public function __construct() |
||||
|
{ |
||||
|
//
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Handle the event. |
||||
|
* |
||||
|
* @param ModelSaved $event |
||||
|
* @return void |
||||
|
*/ |
||||
|
public function handle(ModelSaved $event) |
||||
|
{ |
||||
|
Log::info('listener:'. json_encode($event->message)); |
||||
|
$message = json_decode($event->message); |
||||
|
Activity::create([ |
||||
|
'business_id' => $message->business, |
||||
|
'project_id' => $message->project, |
||||
|
'actor_id' => $message->auth, |
||||
|
'system_id' => $message->data->system_id, |
||||
|
'workflow_id' => $message->data->workflow_id, |
||||
|
'status_id' => $message->data->status_id, |
||||
|
'sprint_id' => $message->data->sprint_id, |
||||
|
'task_id' => $message->data->task_id ?? null, |
||||
|
'subject_id' => $message->data->subject_id ?? null, |
||||
|
'user_id' => $message->data->user_id, |
||||
|
'crud_id' => $message->data->crud_id, |
||||
|
'table_id' => enum('tables.'.$message->data->table_name.'.id'), |
||||
|
'original' => $message->data->original, |
||||
|
'diff' => $message->data->diff, |
||||
|
]); |
||||
|
} |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use Illuminate\Database\Migrations\Migration; |
||||
|
use Illuminate\Database\Schema\Blueprint; |
||||
|
use Illuminate\Support\Facades\Schema; |
||||
|
|
||||
|
class CreateActivitiesTable extends Migration |
||||
|
{ |
||||
|
/** |
||||
|
* Run the migrations. |
||||
|
* |
||||
|
* @return void |
||||
|
*/ |
||||
|
public function up() |
||||
|
{ |
||||
|
Schema::create('activities', function (Blueprint $table) { |
||||
|
$table->id(); |
||||
|
$table->unsignedBigInteger('business_id'); |
||||
|
$table->unsignedBigInteger('project_id')->nullable(); |
||||
|
$table->unsignedBigInteger('system_id')->nullable(); |
||||
|
$table->unsignedBigInteger('workflow_id')->nullable(); |
||||
|
$table->unsignedBigInteger('status_id')->nullable(); |
||||
|
$table->unsignedBigInteger('sprint_id')->nullable(); |
||||
|
$table->unsignedBigInteger('task_id')->nullable(); |
||||
|
$table->unsignedBigInteger('subject_id')->nullable();//row id
|
||||
|
$table->unsignedBigInteger('actor_id'); |
||||
|
$table->unsignedBigInteger('user_id')->nullable(); |
||||
|
$table->unsignedBigInteger('crud_id')->nullable(); |
||||
|
$table->unsignedBigInteger('table_id')->nullable(); |
||||
|
$table->json('original')->nullable(); // a unique identifier that represent the type of action
|
||||
|
$table->json('diff')->nullable(); // all data that has been changed
|
||||
|
$table->timestamps(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Reverse the migrations. |
||||
|
* |
||||
|
* @return void |
||||
|
*/ |
||||
|
public function down() |
||||
|
{ |
||||
|
Schema::dropIfExists('activities'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use Illuminate\Database\Migrations\Migration; |
||||
|
use Illuminate\Database\Schema\Blueprint; |
||||
|
use Illuminate\Support\Facades\Schema; |
||||
|
|
||||
|
class CreateFailedJobsTable extends Migration |
||||
|
{ |
||||
|
/** |
||||
|
* Run the migrations. |
||||
|
* |
||||
|
* @return void |
||||
|
*/ |
||||
|
public function up() |
||||
|
{ |
||||
|
Schema::create('failed_jobs', function (Blueprint $table) { |
||||
|
$table->id(); |
||||
|
$table->string('uuid')->unique(); |
||||
|
$table->text('connection'); |
||||
|
$table->text('queue'); |
||||
|
$table->longText('payload'); |
||||
|
$table->longText('exception'); |
||||
|
$table->timestamp('failed_at')->useCurrent(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Reverse the migrations. |
||||
|
* |
||||
|
* @return void |
||||
|
*/ |
||||
|
public function down() |
||||
|
{ |
||||
|
Schema::dropIfExists('failed_jobs'); |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue