NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Imports for Laravel

Vlastníci a oprávnenia

Každý import beží pre vlastníka — tím, firmu alebo používateľa v aplikácii pre jedného nájomcu — a každé vyhľadávanie aj zápis zostáva v jeho rámci: párovanie prirodzeného kľúča, vyhľadávanie odkazov, záznamy, ktoré import vytvorí alebo aktualizuje, aj to, čo načíta vrátenie importu.

$imports = Imports::for($team)->by($user);

$imports->session($id);            // another owner's id → ImportNotFoundException (404)
$imports->batch($id);
$imports->sessions('assets', SessionStatus::Previewed)->paginate();   // newest first
$imports->running('assets');       // ?SessionHandle — committing or rolling back

Imports::session($id);             // trusted path: no owner check — never from HTTP code
Imports::batch($id);

Imports::session() a ::batch() bez vlastníka sú dôveryhodná cesta pre PHP kód; HTTP kód ich nikdy nepoužíva.

Ownership — deklarované, bezpečné odmietnutie

use RoundlyConsulting\Imports\Definition\Ownership;

Ownership::column('team_id');           // where team_id = owner key; new records: $context->ownerAttributes()
Ownership::belongsTo('team');           // whereBelongsTo($owner, 'team')
Ownership::morph('owner');              // owner_type + owner_id
Ownership::using(
    query: fn (Builder $q, Model $owner) => $q->whereHas('project', fn ($p) => $p->whereBelongsTo($owner)),
    owns: fn (Model $record, Model $owner) => $record->project->team_id === $owner->getKey(),
);
Ownership::global();                    // the explicit opt-out
  • Ownership::inherit() je predvolené pre pole s odkazom — pravidlo importéra.
  • Každé pravidlo ponúka attributes(Model $owner) — to, čo vráti ImportContext::ownerAttributes(): ['team_id' => 7] pre stĺpec, dvojicu <name>_type / <name>_id pre morph, inak [] — a k tomu isGlobal() a describe().
  • Pravidlo importéra obmedzuje párovanie prirodzeného kľúča aj načítanie pri vrátení a po každom vytvorení či aktualizácii musí OwnerScope::owns() záznam prijať, inak riadok zlyhá ako outside_owner.

OwnerScope

interface OwnerScope
{
    public function run(Model $owner, Closure $callback): mixed;                     // ambient context
    public function constrain(Builder $query, Model $owner, Ownership $rule): Builder;
    public function owns(Model $record, Model $owner, Ownership $rule): bool;
}

imports.owner_scope je predvolene Scoping\ExplicitOwnerScope: bez ambientného kontextu — run() len zavolá callback — a uplatní deklarované pravidlá (stĺpec, whereBelongsTo, morph dvojicu, vaše closure v using() alebo nič pri global()). Closure z using() sa uplatní vo vnorenom where a všetko, čo pridá constrain() vlastného scope, sa zoskupí do jednej podmienky, takže orWhere v ňom nikdy nerozšíri vyhľadávanie. Každý krok spracovania, ktorý číta vaše dáta, a každý vstupný bod na pozadí — úloha náhľadu, úlohy častí a vrátenia, callbacky dávky — beží v run($owner).

Recept: teams-for-laravel

teams-for-laravel je voliteľný. S ním spustíte každý import v rámci tímu, ktorý ho vlastní:

use RoundlyConsulting\Imports\Contracts\OwnerScope;
use RoundlyConsulting\Imports\Definition\Ownership;
use RoundlyConsulting\Imports\Scoping\ExplicitOwnerScope;
use RoundlyConsulting\Teams\Facades\Teams;
use RoundlyConsulting\Teams\Models\Team;

final class TeamsOwnerScope implements OwnerScope
{
    public function run(Model $owner, Closure $callback): mixed
    {
        if (! $owner instanceof Team) {
            throw new InvalidArgumentException('Imports owned by teams need a team as their owner.');
        }

        return Teams::runAs($owner, static fn (): mixed => $callback());
    }

    public function constrain(Builder $query, Model $owner, Ownership $rule): Builder
    {
        return (new ExplicitOwnerScope)->constrain($query, $owner, $rule);
    }

    public function owns(Model $record, Model $owner, Ownership $rule): bool
    {
        return (new ExplicitOwnerScope)->owns($record, $owner, $rule);
    }
}
// config/imports.php
'owner_scope' => App\Imports\TeamsOwnerScope::class,
'routes' => ['owner_resolver' => App\Imports\CurrentTeamOwner::class],   // ResolvesImportOwner → the current team

V Teams::runAs() izolujú TeamScope a TeamWriteGuard z balíka teams každé čítanie aj zápis Eloquentu a tím vlastníka importu nahradí tím, ktorý mal ten, kto úlohu do frontu odoslal. Presne táto trieda je testovaná so skutočným balíkom teams.

Oprávnenia

authorize(?Authenticatable $user, Model $owner, ImportOperation $operation) je povinné — bezpečné odmietnutie. Každá operácia handle sa naň pýta pre aktéra daného handle: čítanie ako View, zápisy ako vlastná operácia.

public function authorize(?Authenticatable $user, Model $owner, ImportOperation $operation): bool
{
    return match ($operation) {
        ImportOperation::View => $user?->can('view-imports', $owner) ?? false,
        ImportOperation::Upload, ImportOperation::Commit => $user?->can('import-assets', $owner) ?? false,
        ImportOperation::Rollback => $user?->can('undo-imports', $owner) ?? false,
    };
}

// or a Gate one-liner
return $user?->can('import-assets', $owner) ?? false;
  • Upload — pri nahratí, skôr než sa súbor prečíta alebo uloží, a pri zmenách mapovania, režimu, zdroja, náhľadu a uložených mapovaní.
  • Commit — pri importe a pokračovaní a znova na začiatku každého behu dávky; ten, kto import spustil a medzitým stratil prístup, spôsobí zlyhanie dávky (unauthorized).
  • Rollback — pri vrátení importu.
  • View — každé čítanie: stav, hárky, hlavičky, počty, priebeh, dáta náhľadu, riadky, návrh mapovania a report chýb pri relácii; stav, priebeh, súhrn, záznamy, canRollback, report vrátenia a predikáty pri dávke; zoznam relácií, running(), uložené mapovania a importers()->available(). sessions() bez importéra vypíše len importéry, ktorých authorize() povolí View.

Aktér null (bez by() alebo cez Imports::session() / ::batch()) je systémový kód: čo smie, rozhodne vaše authorize() — žiadne skryté obídenie neexistuje. Výsledok sa uloží pre inštanciu handle a operáciu, takže slučka, ktorá sa opakovane pýta na jeden handle, sa opýta raz.

Audit

Každá udalosť importu nesie ImportAudit — reláciu, dávku, importér, vlastníka, aktéra danej operácie, odkaz na súbor a počty:

use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Imports\Events\ImportCompleted;

Event::listen(fn (ImportCompleted $e) => AuditLog::create([
    'action' => 'import.completed', 'team_id' => $e->audit->owner->getKey(), 'user_id' => $e->audit->actor?->getKey(),
    'details' => ['importer' => $e->audit->importer, 'file' => $e->audit->file->originalName, 'created' => $e->summary->created],
]));

So sentinel-for-laravel (voliteľný) zapečatíte importované záznamy z evidencie v listeneri ImportCompleted ($batch->records(RecordAction::Created)) alebo udalosť zapíšete do vlastného zapečateného logu.

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.