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

Granular esi scheduling for users #682

Closed
2 changes: 1 addition & 1 deletion src/Acl/AccessManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public function giveUserRole(int $user_id, int $role_id)

// If the role does not already have the user, add it.
if (! $role->users->contains($user_id)) {
$role->users()->save($user);
$role->users()->attach($user);
event(new UserRoleAdded($user_id, $role));
}
}
Expand Down
56 changes: 54 additions & 2 deletions src/Http/Controllers/Configuration/ScheduleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@

namespace Seat\Web\Http\Controllers\Configuration;

use Artisan;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Seat\Services\Models\Schedule;
use Seat\Web\Http\Controllers\Controller;
use Seat\Web\Http\Validation\NewSchedule;
use Seat\Web\Models\Acl\Role;
use Seat\Web\Models\CharacterSchedulingRule;

/**
* Class ScheduleController.
Expand Down Expand Up @@ -55,8 +58,11 @@ public function listSchedule()

];

$character_scheduling_rules = CharacterSchedulingRule::with('role')->get();
$roles = Role::all();

return view('web::configuration.schedule.view',
compact('schedule', 'commands', 'expressions'));
compact('schedule', 'commands', 'expressions', 'character_scheduling_rules', 'roles'));
}

/**
Expand Down Expand Up @@ -85,4 +91,50 @@ public function deleteSchedule(int $schedule_id)
return redirect()->back()
->with('success', 'Schedule entry deleted!');
}

public function newCharacterSchedulingRule(Request $request)
{
$request->validate([
'role_id' => 'required|integer',
'time' => 'required|decimal:0,2|min:1',
'timeunit' => 'required|string|in:hour,day,week',
]);

$role = Role::find($request->role_id);
if($role === null) {
return redirect()->back()->with('error', trans('web::seat.role_not_found'));
}

$rule = $role->character_scheduling_rule;
if($rule === null) {
$rule = new CharacterSchedulingRule();
$rule->role_id = $role->id;
}

// $time_modifier: conversion factor from timeunit to seconds
if($request->timeunit === 'hour') {
$time_modifier = 60 * 60;
} elseif ($request->timeunit === 'day') {
$time_modifier = 60 * 60 * 24;
} elseif ($request->timeunit === 'week') {
$time_modifier = 60 * 60 * 24 * 7;
}

$rule->update_interval = $request->time * $time_modifier;
$rule->save();

return redirect()->back()->with('success', trans('web::seat.character_scheduling_rule_creation_success'));
}

public function deleteCharacterSchedulingRule(Request $request): \Illuminate\Http\RedirectResponse
{
$request->validate([
'role_id' => 'required|integer',
]);

CharacterSchedulingRule::destroy($request->role_id);

return redirect()->back()
->with('success', trans('web::seat.character_scheduling_rule_deleted'));
}
}
8 changes: 8 additions & 0 deletions src/Http/Routes/Configuration/Schedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@
Route::get('/delete/{schedule_id}')
->name('seatcore::configuration.schedule.delete')
->uses('ScheduleController@deleteSchedule');

Route::post('rules/delete')
->name('seatcore::configuration.schedule.rule.delete')
->uses('ScheduleController@deleteCharacterSchedulingRule');

Route::post('rules/create')
->name('seatcore::configuration.schedule.rule.create')
->uses('ScheduleController@newCharacterSchedulingRule');
17 changes: 16 additions & 1 deletion src/Models/Acl/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,20 @@
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Collection;
use Intervention\Image\Facades\Image;
use OpenApi\Attributes as OA;
use Seat\Tests\Web\Database\Factories\RoleFactory;
use Seat\Web\Models\CharacterSchedulingRule;
use Seat\Web\Models\Squads\Squad;
use Seat\Web\Models\Squads\SquadRole;
use Seat\Web\Models\User;

/**
* @property CharacterSchedulingRule character_scheduling_rule
* @property Collection users
*/
#[OA\Schema(
title: 'Role',
description: 'Role',
Expand Down Expand Up @@ -102,12 +109,20 @@ public function squads()
->using(SquadRole::class);
}

/**
* @return HasOne
*/
public function character_scheduling_rule(): HasOne
{
return $this->hasOne(CharacterSchedulingRule::class);
}

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users()
{
return $this->belongsToMany(User::class);
return $this->belongsToMany(User::class)->using(RoleUser::class);
}

/**
Expand Down
52 changes: 52 additions & 0 deletions src/Models/Acl/RoleUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of SeAT
*
* Copyright (C) 2015 to present Leon Jacobs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

namespace Seat\Web\Models\Acl;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Seat\Web\Models\User;

/**
* @property int role_id
* @property int user_id
* @property User user
* @property Role role
*/
class RoleUser extends Pivot
{
/**
* @return BelongsTo
*/
public function role(): BelongsTo
{
return $this->belongsTo(Role::class);
}

/**
* @return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
83 changes: 83 additions & 0 deletions src/Models/CharacterSchedulingRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/*
* This file is part of SeAT
*
* Copyright (C) 2015 to present Leon Jacobs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

namespace Seat\Web\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Seat\Eveapi\Models\RefreshToken;
use Seat\Eveapi\Models\RefreshTokenSchedule;
use Seat\Services\Models\ExtensibleModel;
use Seat\Web\Models\Acl\Role;

/**
* @property int $id
* @property int $role_id
* @property int update_interval
* @property Role $role
*/
class CharacterSchedulingRule extends ExtensibleModel
{
/**
* @var bool
*/
public $timestamps = false;

/**
* @var string
*/
protected $primaryKey = 'role_id';

/**
* @var bool
*/
public $incrementing = false;

const DEFAULT_UPDATE_INTERVAL = 60 * 60; // 1 hour, the esi cache timer for most endpoints

public function role(): BelongsTo
{
return $this->belongsTo(Role::class);
}

public static function updateUserRefreshTokenSchedule(User $user): void
{
$update_interval = $user->roles()
->whereHas('character_scheduling_rule')
->get()
->min('character_scheduling_rule.update_interval') ?? self::DEFAULT_UPDATE_INTERVAL;

$user->refresh_tokens()->with('token_schedule')->get()
->each(function (RefreshToken $token) use ($update_interval) {
$schedule = $token->token_schedule;

if($schedule === null) {
$schedule = new RefreshTokenSchedule();
$schedule->character_id = $token->character_id;
$schedule->last_update = Carbon::createFromTimestamp(0); // this field is not optional, therefore set it to the earliest date possible
}

$schedule->update_interval = $update_interval;
$schedule->save();
});
}
}
5 changes: 5 additions & 0 deletions src/Models/Squads/SquadMember.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
* Class SquadMember.
*
* @package Seat\Web\Models\Squads
*
* @property int squad_id
* @property int user_id
* @property Squad squad
* @property User user
*/
class SquadMember extends Pivot
{
Expand Down
15 changes: 15 additions & 0 deletions src/Models/Squads/SquadRole.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,29 @@

namespace Seat\Web\Models\Squads;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Seat\Web\Models\Acl\Role;

/**
* Class SquadRole.
*
* @package Seat\Web\Models\Squads
*
* @property int $role_id
* @property int $squad_id
* @property Role $role
* @property Squad $squad
*/
class SquadRole extends Pivot
{
public function role(): BelongsTo
{
return $this->belongsTo(Role::class);
}

public function squad(): BelongsTo
{
return $this->belongsTo(Squad::class);
}
}
16 changes: 11 additions & 5 deletions src/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,27 @@
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Collection;
use Seat\Eveapi\Models\Character\CharacterInfo;
use Seat\Eveapi\Models\RefreshToken;
use Seat\Services\Models\UserSetting;
use Seat\Services\Settings\Profile;
use Seat\Tests\Web\Database\Factories\UserFactory;
use Seat\Web\Models\Acl\Role;
use Seat\Web\Models\Acl\RoleUser;
use Seat\Web\Models\Squads\Squad;
use Seat\Web\Models\Squads\SquadMember;

/**
* Class User.
*
* @package Seat\Web\Models
*
* @property int id
* @property Collection roles
*/
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
Expand Down Expand Up @@ -153,11 +159,11 @@ public function refresh_tokens()
}

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
* @return BelongsToMany
*/
public function roles()
public function roles(): BelongsToMany
{
return $this->belongsToMany(Role::class);
return $this->belongsToMany(Role::class)->using(RoleUser::class);
}

/**
Expand Down Expand Up @@ -197,15 +203,15 @@ public function main_character()
}

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
* @return BelongsToMany
*/
public function moderators()
{
return $this->belongsToMany(Squad::class, 'squad_moderator');
}

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
* @return BelongsToMany
*/
public function squads()
{
Expand Down
Loading
Loading