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

Hostia a odkazy pre hostí

Žiadateľ bez účtu je TicketGuest a jeho polia sa ukladajú cez attributes-for-laravel:

$ticket = Tickets::make()->subject('Broken link')->guest(['name' => 'Jo', 'email' => '[email protected] '])->create();

$guest = Tickets::guests()->resolve(['name' => 'Jo', 'email' => '[email protected]']);
$known = Tickets::guests()->find(['email' => '[email protected]']);   // read-only: the guest, or null
Tickets::guests()->update($guest, ['phone' => '+421 900 000 000']);
$link = Tickets::guests()->linkFor('TCK-9');              // a model or a reference; = Tickets::for($ticket)->guestLink()
$moved = Tickets::guests()->convert($guest, $user);       // when the guest registers
Tickets::for($ticket)->by($agent)->revokeGuestAccess();   // void every link issued so far

Polia hosťa

O tom, čo sa hostí pýtate, rozhodujete vy. tickets.guests.fields musí byť neprázdna mapa s práve jedným poľom display a každé pole má názov zodpovedajúci ^[a-z][a-z0-9_]{0,63}$. Dodaná sada:

// config/tickets.php
'guests' => [
    'fields' => [
        'name' => ['type' => 'string', 'rules' => ['required', 'string', 'max:120'], 'display' => true],
        'email' => ['type' => 'string', 'rules' => ['nullable', 'email:rfc', 'max:191'], 'identifying' => true, 'route' => 'mail', 'normalize' => 'email'],
        'phone' => ['type' => 'string', 'rules' => ['nullable', 'string', 'max:32'], 'identifying' => true, 'route' => 'vonage', 'normalize' => 'phone', 'encrypted' => false],
    ],
    // …
],
AtribútVýznam
typeHodnota AttributeType z attributes-for-laravel (string, integer, …); predvolene string.
rulesValidačné pravidlá Laravelu pre hodnotu.
displayPráve jedno pole je zobrazované meno hosťa.
identifyingNájde vracajúceho sa hosťa (skúša sa v poradí konfigurácie); unikátne medzi hosťami; nikdy nesmie byť šifrované.
routeKanál notifikácií, na ktorý toto pole smeruje (mail, vonage, …) — číta ho routeNotificationFor().
normalizeemail (orezanie, malé písmená) alebo phone (odstránenie medzier) pred porovnaním.
encryptedUložiť hodnotu šifrovane (nie pre identifikačné polia).

Rozpoznanie hosťa

resolve() a každý tiket založený s poliami hosťa:

  • Hodnoty sa zvalidujú podľa pravidiel poľa a normalizujú (email: orezaný, malými písmenami; phone: bez medzier). Chyby majú kľúč fields.<name> z Tickets::guests() a guest.<name> pri zakladaní tiketu či zmene žiadateľa — e-mail hosťa a vlastné pole email sa teda nikdy nezrazia. Hosť sa vyhodnotí skôr, než sa validujú vlastné polia.
  • Identifikačné polia sa skúšajú v poradí konfigurácie; prvá zhoda je hosť. Prázdne polia nájdeného hosťa sa doplnia; odlišné neidentifikačné hodnoty zostanú, pokiaľ nie je zapnuté tickets.guests.update_on_resolve.
  • Ak sa údaje zhodujú s hosťom, no nesú inú hodnotu ďalšieho identifikačného poľa, ktoré hosť má, vznikne nový hosť len s tými identifikačnými hodnotami, ktoré nemá žiadny iný hosť — tiket sa tak nikdy nedostane ku kontaktu inej osoby.
  • Soft-deleted hosť, ktorý sa znova ozve, sa obnoví; bez zhody sa hosť vytvorí. Dva súbežné prvé tikety od toho istého nového hosťa skončia pri jednom hosťovi.

find($fields) hľadá presne ako rozpoznanie, no nikdy nič nevytvorí, nedoplní ani nezvaliduje: neznáme názvy ignoruje, soft-deleted hosťa nevráti a bez identifikačnej hodnoty odpovie null. Je to čítanie, preto ho fake nezaznamená.

Konverzia

convert($guest, $user) v jednej transakcii presmeruje žiadateľa každého tiketu a každý riadok sledovania z hosťa na používateľa (kde už používateľ tiket sleduje, sledovanie hosťa sa zahodí), zapíše aktivitu requester_changed, uvoľní identifikačné hodnoty hosťa, hosťa soft-deletne a spustí GuestConverted. Komentáre, ktoré hosť napísal, majú ako autora naďalej hosťa.

Odkazy pre hostí

Žiadateľ-hosť — alebo hosť medzi sledujúcimi, kým je zapnuté tickets.watchers.can_view — otvorí tiket cez dočasný podpísaný odkaz:

$url = Tickets::for($ticket)->guestLink();          // the guest requester
$url = Tickets::for($ticket)->guestLink($ccGuest);  // a guest watcher; anyone else is refused
Tickets::for($ticket)->revokeGuestAccess();         // voids every link issued so far

Predvolený Guests\SignedRouteLinkGenerator podpíše tickets.guest.show s číslom tiketu, kľúčom hosťa a v = guest_access_version tiketu, s platnosťou tickets.guests.link_ttl (P30D). Potrebuje routy pre hostí (tickets.routes.enabled aj tickets.guests.enabled); keď sú vypnuté, vyhodí InvalidTicketsConfigurationException s návodom na opravu. Notifikácie pre hostí zakaždým vložia novo vygenerovaný odkaz.

Podpis pokrýva jednu routu, takže odkaz z e-mailu otvorí len GET /tickets/guest/{ticket}. Jeho odpoveď obsahuje podpísané URL akcií, každú podpísanú pre ten istý tiket, hosťa, v a platnosť:

{
  "data": { "reference": "TCK-7", "subject": "…", "status": {…}, "fields": [], "attachments": [] },
  "messages": [ { "id": 12, "body": "…", "role": "agent", … } ],
  "links": {
    "self": "https://…/api/tickets/guest/TCK-7?guest=…&v=1&expires=…&signature=…",
    "reply": "https://…/api/tickets/guest/TCK-7/replies?…",
    "transitions": { "close": "https://…/transitions/close?…" },
    "attachments": { "<uuid>": "https://…/attachments/<uuid>?…" }
  }
}

links.reply je null, keď je tiket uzavretý; links.transitions uvádza len práve povolené requester_transitions. Odpovede sa odosielajú ako hosť, s rovnakými automatizáciami.

Jedna odpoveď pre každý zlý odkaz: EnsureGuestTicketAccess overí podpis sám, potom či je hosť žiadateľom-hosťom alebo hosťom medzi sledujúcimi a či je v aktuálne. Expirované, upravené, zneplatnené odkazy, odkazy iného tiketu, iného hosťa aj zmazaného tiketu dostanú rovnakú odpoveď 403 {message, code: guest_link_invalid} — nie je čo skúmať. revokeGuestAccess(), zlúčenie alebo uzavretie pri tickets.guests.revoke_on_close zvýšia v a zneplatnia každý odkaz aj každú vloženú URL akcie.

Samostatný frontend

Keď hostia používajú vašu SPA namiesto surového API, naviažte generátor, ktorý podpísanú URL API zabalí do odkazu na frontend. Frontend volá vložené URL presne tak, ako sú — nikdy ich neskladá nanovo —, takže podpis zostane platný:

use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\Tickets\Contracts\GuestLinkGenerator;
use RoundlyConsulting\Tickets\Guests\SignedRouteLinkGenerator;
use RoundlyConsulting\Tickets\Models\Ticket;

final readonly class FrontendGuestLinks implements GuestLinkGenerator
{
    public function __construct(private SignedRouteLinkGenerator $signed) {}

    public function for(Ticket $ticket, Model $recipient): string
    {
        return 'https://help.example.com/guest?link='.rawurlencode($this->signed->for($ticket, $recipient));
    }
}
// config/tickets.php
'guests' => ['link_generator' => App\Tickets\FrontendGuestLinks::class, /* … */],

Frontend prečíta link, zavolá naň GET, vykreslí data a messages a posiela POST na links.reply ({body, attachments[]?}) alebo na URL z links.transitions.* ({reason?, payload?}). Tento generátor stále potrebuje routy pre hostí, pretože ich balí. Frontend, ktorý sa endpointov balíka pre hostí nikdy nedotkne, môže vracať akúkoľvek URL, ktorú si vyhodnotí sám — potom routy pre hostí vypnite.

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.