Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 0 additions & 3 deletions app/Http/Controllers/Api/AssetsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -733,9 +733,6 @@ public function update(UpdateAssetRequest $request, Asset $asset): JsonResponse
if ($request->has('model_id')) {
$asset->model()->associate(AssetModel::find($request->validated()['model_id']));
}
if ($request->has('company_id')) {
$asset->company_id = Company::getIdForCurrentUser($request->validated()['company_id']);
}
if ($request->has('rtd_location_id') && !$request->has('location_id')) {
$asset->location_id = $request->validated()['rtd_location_id'];
}
Expand Down
5 changes: 5 additions & 0 deletions app/Http/Controllers/Api/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ public function update(SaveUserRequest $request, User $user): JsonResponse

if ($request->filled('company_id')) {
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));

// Remove the new company from the fmcs mapping table
if (Company::isFullMultipleCompanySupportEnabled() && $user->companies()->get()->contains($request->input('company_id'))) {
$user->companies()->detach($request->input('company_id'));
}
}

if ($user->id == $request->input('manager_id')) {
Expand Down
8 changes: 8 additions & 0 deletions app/Http/Controllers/Users/BulkUsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Models\License;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Group;
use App\Models\LicenseSeat;
use App\Models\ConsumableAssignment;
Expand Down Expand Up @@ -234,6 +235,13 @@ public function update(Request $request)
}
}

// Remove the new company from the fmcs mapping table
if ($request->filled('company_id') && Company::isFullMultipleCompanySupportEnabled()) {
foreach ($users as $user) {
$user->companies()->detach($request->input('company_id'));
}
}

return redirect()->route('users.index')
->with($return_array);
}
Expand Down
51 changes: 48 additions & 3 deletions app/Http/Controllers/Users/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ public function create(Request $request)

$user = new User;

return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions'))
$fmcs = Company::isFullMultipleCompanySupportEnabled();
if ($fmcs) {
$companies = Company::pluck('name', 'id');
$companyMappings = $user->company_ids();
} else {
$companies = null;
$companyMappings = null;
}

return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions', 'fmcs', 'companies', 'companyMappings'))
->with('user', $user);
}

Expand Down Expand Up @@ -156,6 +165,15 @@ public function store(SaveUserRequest $request)
$user->groups()->sync([]);
}

// Update the company mappings after removing the own company from the input, only super user are allowed to change the mappings
if (Company::isFullMultipleCompanySupportEnabled() && auth()->user()->isSuperUser()) {
$company_mappings = $request->input('companyMappings');
if ($company_mappings && ($key = array_search($user->company_id, $company_mappings)) !== false) {
unset($company_mappings[$key]);
}
$user->companies()->sync($company_mappings);
}

return Helper::getRedirectOption($request, $user->id, 'Users')
->with('success', trans('admin/users/message.success.create'));
}
Expand Down Expand Up @@ -206,7 +224,16 @@ public function edit(User $user)
$userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions);
$permissions = $this->filterDisplayable($permissions);

return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))->with('item', $user);
$fmcs = Company::isFullMultipleCompanySupportEnabled();
if ($fmcs) {
$companies = Company::pluck('name', 'id');
$companyMappings = $user->company_ids();
} else {
$companies = null;
$companyMappings = null;
}

return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions', 'fmcs', 'companies', 'companyMappings'))->with('item', $user);
}

}
Expand Down Expand Up @@ -327,6 +354,15 @@ public function update(SaveUserRequest $request, User $user)
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
session()->put(['redirect_option' => $request->get('redirect_option')]);

// Update the company mappings after removing the own company from the input, only super user are allowed to change the mappings
if (Company::isFullMultipleCompanySupportEnabled() && auth()->user()->isSuperUser()) {
$company_mappings = $request->input('companyMappings');
if ($company_mappings && ($key = array_search($user->company_id, $company_mappings)) !== false) {
unset($company_mappings[$key]);
}
$user->companies()->sync($company_mappings);
}

if ($user->save()) {
// Redirect to the user page
return Helper::getRedirectOption($request, $user->id, 'Users')
Expand Down Expand Up @@ -482,8 +518,17 @@ public function getClone(Request $request, User $user)

$userPermissions = Helper::selectedPermissionsArray($permissions, $clonedPermissions);

$fmcs = Company::isFullMultipleCompanySupportEnabled();
if ($fmcs) {
$companies = Company::pluck('name', 'id');
$companyMappings = $user_to_clone->company_ids();
} else {
$companies = null;
$companyMappings = null;
}

// Show the page
return view('users/edit', compact('permissions', 'userPermissions'))
return view('users/edit', compact('permissions', 'userPermissions', 'fmcs', 'companies', 'companyMappings'))
->with('user', $user)
->with('groups', Group::pluck('name', 'id'))
->with('userGroups', $userGroups)
Expand Down
8 changes: 8 additions & 0 deletions app/Http/Requests/UpdateAssetRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Http\Requests\Traits\MayContainCustomFields;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Setting;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
Expand All @@ -21,6 +22,13 @@ public function authorize()
return Gate::allows('update', $this->asset);
}

public function prepareForValidation(): void
{
$this->merge([
'company_id' => Company::getIdForCurrentUser($this->company_id),
]);
}

/**
* Get the validation rules that apply to the request.
*
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Accessory.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Accessory extends SnipeModel
'name' => 'required|min:3|max:255',
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer|exists:categories,id',
'company_id' => 'integer|nullable',
'company_id' => 'integer|nullable|fmcs_validator',
'location_id' => 'exists:locations,id|nullable|fmcs_location',
'min_amt' => 'integer|min:0|nullable',
'purchase_cost' => 'numeric|nullable|gte:0|max:9999999999999',
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function declinedCheckout(User $declinedBy, $signature)
'status_id' => ['required', 'integer', 'exists:status_labels,id'],
'asset_tag' => ['required', 'min:1', 'max:255', 'unique_undeleted:assets,asset_tag', 'not_array'],
'name' => ['nullable', 'max:255'],
'company_id' => ['nullable', 'integer', 'exists:companies,id'],
'company_id' => ['nullable', 'integer', 'exists:companies,id', 'fmcs_validator'],
'warranty_months' => ['nullable', 'numeric', 'digits_between:0,240'],
'last_checkout' => ['nullable', 'date_format:Y-m-d H:i:s'],
'last_checkin' => ['nullable', 'date_format:Y-m-d H:i:s'],
Expand Down
47 changes: 26 additions & 21 deletions app/Models/Company.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ final class Company extends SnipeModel
'notes',
];

private static function isFullMultipleCompanySupportEnabled()
public static function isFullMultipleCompanySupportEnabled()
{
$settings = Setting::getSettings();

Expand Down Expand Up @@ -109,21 +109,12 @@ public static function getIdFromInput($unescaped_input)
*/
public static function getIdForCurrentUser($unescaped_input)
{
if (! static::isFullMultipleCompanySupportEnabled()) {
return static::getIdFromInput($unescaped_input);
$current_user = auth()->user();
$input = static::getIdFromInput($unescaped_input);
if (static::canManageUsersCompanies()) {
return $input;
} else {
$current_user = auth()->user();

// Super users should be able to set a company to whatever they need
if ($current_user->isSuperUser()) {
return static::getIdFromInput($unescaped_input);
} else {
if ($current_user->company_id != null) {
return $current_user->company_id;
} else {
return null;
}
}
return $current_user->company_id;
}
}

Expand Down Expand Up @@ -165,14 +156,17 @@ public static function isCurrentUserHasAccess($companyable)

if (auth()->user()) {
// Log::warning('Companyable is '.$companyable);
$current_user_company_id = auth()->user()->company_id;
$current_user = auth()->user();
$companyable_company_id = $companyable->company_id;

// Set this to check companyable on company
if ($companyable instanceof Company) {
$companyable_company_id = $companyable->id;
}
return ($current_user_company_id == null) || ($current_user_company_id == $companyable_company_id) || auth()->user()->isSuperUser();

return ($current_user->company_id == null
|| $current_user->company_ids()->contains($companyable_company_id)
|| $current_user->isSuperUser());
}

return false;
Expand All @@ -186,8 +180,11 @@ public static function isCurrentUserAuthorized()

public static function canManageUsersCompanies()
{
return ! static::isFullMultipleCompanySupportEnabled() || auth()->user()->isSuperUser() ||
auth()->user()->company_id == null;
$current_user = auth()->user();
return (!static::isFullMultipleCompanySupportEnabled()
|| $current_user->isSuperUser()
|| $current_user->company_id == null
|| $current_user->company_ids()->count() > 1);
}

/**
Expand Down Expand Up @@ -300,7 +297,11 @@ private static function scopeCompanyablesDirectly($query, $column = 'company_id'

// If we are scoping the companies table itself, look for the company.id
if ($query->getModel()->getTable() == 'companies') {
return $query->where('companies.id', '=', $company_id);
if ($company_id != null) {
return $query->whereIn('companies.id', auth()->user()->company_ids());
} else {
return $query->where('companies.id', '=', null);
}
}


Expand All @@ -310,7 +311,11 @@ private static function scopeCompanyablesDirectly($query, $column = 'company_id'
// Dynamically get the table name if it's not passed in, based on the model we're querying against
$table = ($table_name) ? $table_name."." : $query->getModel()->getTable().".";

return $query->where($table.$column, '=', $company_id);
if ($company_id != null) {
return $query->whereIn($table.$column, auth()->user()->company_ids());
} else {
return $query->where($table.$column, '=', null);
}
}


Expand Down
2 changes: 1 addition & 1 deletion app/Models/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Component extends SnipeModel
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer|exists:categories,id',
'supplier_id' => 'nullable|integer|exists:suppliers,id',
'company_id' => 'integer|nullable|exists:companies,id',
'company_id' => 'integer|nullable|exists:companies,id|fmcs_validator',
'location_id' => 'exists:locations,id|nullable|fmcs_location',
'min_amt' => 'integer|min:0|nullable',
'purchase_date' => 'date_format:Y-m-d|nullable',
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Department.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Department extends SnipeModel
protected $rules = [
'name' => 'required|max:255|is_unique_department',
'location_id' => 'numeric|nullable',
'company_id' => 'numeric|nullable',
'company_id' => 'numeric|nullable|fmcs_validator',
'manager_id' => 'numeric|nullable',
];

Expand Down
2 changes: 1 addition & 1 deletion app/Models/License.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class License extends Depreciable
'license_name' => 'string|nullable|max:100',
'notes' => 'string|nullable',
'category_id' => 'required|exists:categories,id',
'company_id' => 'integer|nullable',
'company_id' => 'integer|nullable|fmcs_validator',
'purchase_cost'=> 'numeric|nullable|gte:0',
'purchase_date' => 'date_format:Y-m-d|nullable|max:10|required_with:depreciation_id',
'expiration_date' => 'date_format:Y-m-d|nullable|max:10',
Expand Down
29 changes: 29 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'website' => 'url|nullable|max:191',
'manager_id' => 'nullable|exists:users,id|cant_manage_self',
'location_id' => 'exists:locations,id|nullable|fmcs_location',
'company_id' => 'nullable|exists:companies,id|fmcs_validator',
'start_date' => 'nullable|date_format:Y-m-d',
'end_date' => 'nullable|date_format:Y-m-d|after_or_equal:start_date',
'autoassign_licenses' => 'boolean',
Expand Down Expand Up @@ -587,6 +588,34 @@ public function groups()
return $this->belongsToMany(\App\Models\Group::class, 'users_groups');
}

/**
* Establishes the user -> companies relationship for FullMultipleCompanySupport
*
* Since companies are scoped with the CompanyableTrait we must use withoutGlobalScopes() to get all mapped companies
*
* @author T. Regnery <[email protected]>
* @since [vX.X]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function companies()
{
return $this->belongsToMany(\App\Models\Company::class, 'companies_users_fmcs')->withoutGlobalScopes();
}

/**
* Returns the combined company_ids from the users "primary" company and the FullMultipleCompanySupport mapping table
*
* @author T. Regnery <[email protected]>
* @since [vX.X]
* @return Illuminate\Support\Collection
*/
public function company_ids()
{
$company_ids = $this->companies()->pluck('company_id');
$company_ids->push($this->company_id);
return $company_ids;
}

/**
* Establishes the user -> assets relationship
*
Expand Down
22 changes: 22 additions & 0 deletions app/Providers/ValidationServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Models\Location;
use App\Models\Setting;
use Illuminate\Support\Facades\DB;
use App\Models\Company;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

Expand Down Expand Up @@ -368,6 +369,27 @@ public function boot()
}
return true;
});

// Validates if the user has the permission to choose the specified company in case of FullMultipleCompanySupport
Validator::extendImplicit('fmcs_validator', function ($attribute, $value, $parameters, $validator) {
$current_user = auth()->user();

if ($current_user) {
if (!Company::isFullMultipleCompanySupportEnabled() || $current_user->isSuperUser() || $current_user->company_id == null) {
return true;
}

if ($value != null && $current_user->company_ids()->contains($value)) {
return true;
}
}
else {
// Needed for user creation from LDAP
return true;
}

return false;
});
}

/**
Expand Down
Loading
Loading