Open zoul opened 1 month ago
Rychlý technický test: Založil jsem tabulku Test registrace a udělal odpovídající formulář. V tom formuláři je pole User, ve kterém jde vybrat z naší tabulky uživatelů – což samo o sobě není nic moc, ale jde použít předvyplněné URL, kde toho uživatele vyplníme automaticky a zároveň to pole úplně schováme. Ve výsledku pak můžu do registrační tabulky přidat nový záznam, který se odkazuje na existující uživatelský profil a zároveň obsahuje dodatečné informace (potřebné například pro registraci na danou roli). Je to slibné, ale jsou tam dva háčky – jednak bezpečnost, jednak synchronizace do jiných databází. Ještě si s tím pohraju a napíšu.
Ty registrační formuláře se obvykle týkají projektů, a ty žijí v samostatných databázích (tedy nikoliv v databázi Users). A vazba z registračního formuláře na existující uživatelský profil nemůže vést napříč databázemi. Teď se často děje to, že databáze projektu (například App) má vlastní synchronizovanou tabulku uživatelských profilů. Takže bychom to chtěli udělat tak, aby byl registrační formulář vázaný na záznam z téhle synchronizované tabulky:
Databáze Users:
User Profiles
Databáze App:
User Profiles (synchronizovaná kopie z Users)
Jan Novák <-----+
Registration form: |
Jan Novák ------+
(…dodatečné info z registračního formuláře)
Teď bychom tedy chtěli změnit stránku s vypsanou rolí v aplikaci tak, aby hlavní CTA Mám zájem vedlo na nějaký takovýhle formulář a přidalo do URL databázové ID aktuálně přihlášeného uživatele. Tím by se to ID předvyplnilo do formuláře, vznikla by provazba na synchronizovanou kopii tabulky User Profiles a všecko by bylo krásné.
Ovšem ta synchronizovaná kopie tabulky User Profiles má odlišná databázová ID 💩 Takže zatímco v původní databázi User Profiles najdeme pod ID recmU8tKzog4merHh
můj profil, v té synchronizované kopii žádný záznam s tímhle ID neexistuje. Aby to automaticky fungovalo, museli bychom na té stránce s rolí vědět, jaké je databázové ID přihlášeného uživatele v databázi, kde žije registrační formulář. Není to jaderná fyzika, ale je to pruda a nejspíš to bude vyžadovat vyplnění nějakých extra informací k dotyčné roli.
PS. Zároveň platí, že když budeme vázat registrační info na záznam ze synchronizované kopie User Profiles, tak ta registrační data nebudou automaticky přístupná z opačné strany v tabulce User Profiles v databázi Users. Ale to je prozatím OK.
To předávání ID přihlášeného uživatele v URL pochopitelně není moc bezpečné, protože to ID může kdokoliv změnit. Na jednu stranu to bezvadně odpovídá současné situaci, kdy taky můžu formulář vyplnit jménem kohokoliv jiného, ale na druhou stranu nás to může furt někde nemile překvapit. Jednoduchá možnost by byla poslat společně s ID uživatele i nějaký kontrolní součet (vygenerovaný na serveru), který bychom pak ve formuláři zkontrolovali – tedy například bychom poslali něco à la User_ID + SHA1(User_ID + salt + secret) a následně ve formuláři zkontrolovali, že ta heš sedí. Což ale v Airtable neumíme (nemáme vzorec pro SHA1). Můžem podumat.
Přemýšlím, jestli se nedostáváme do situace, kdy by bylo jednodušší přemyslet celou architekturu těch databází tak, aby to co nejlépe sloužilo účelu sjednocování dat, než se snažit napasovat řešení na to stávající rozdělení. Co z toho má lepší poměr vloženého úsilí vs dlouhodobého gainu
Já jsem nad tímhle už trochu přemýšlel dřív a k ničemu kloudnému jsem nedošel. Ten model „každý projekt má vlastní databázi“ je v něčem velmi žádoucí, protože si pak lidi můžou hospodařit hodně nezávisle a nevznikají tím úzká hrdla. Na druhou stranu to „nezávislé hospodaření“ samozřejmě generuje ty nežádoucí divergence.
Proto mně tenhle drobný pragmatický posun ve stylu „nechte si svoje registrační formuláře a my vám je akorát zjednodušíme“ přijde docela dobrý. Z našeho pohledu (tedy celkového ekosystému) je za mě zásadní to, abychom už se nikdy lidí znova neptali, jak se jmenujou nebo jaký je jejich mail.
Pročítám si to ještě zpětně a nepochopila jsem přesně, jak by fungovalo toto:
jde použít předvyplněné URL, kde toho uživatele vyplníme automaticky a zároveň to pole úplně schováme
Nechápu ten usecase, kdy by to mohlo být dobré, tedy jak se jako někdo, kdo se hlásí na nějakou roli, dostanu k tomu personalizovanému URL. Bylo by to v rámci toho, že jsem přihlášená v app? Že by se u každé role do přihlašování už rovnou propsal můj základní profil?
Mám teď call s Marťou a Romčou, přinesu z toho nějaké vstupy, zároveň předám myšlenky z tohohle flow. A v každém případě tu úplně základní myšlenku:
za mě zásadní to, abychom už se nikdy lidí znova neptali, jak se jmenujou nebo jaký je jejich mail.
Je to myšlené přesně tak, jak píšeš – odpověď na roli by vyžadovala přihlášení do app. Takže když klikám na CTA „Mám zájem“, aplikace už by uměla předat do formuláře ID toho přihlášeného uživatele.
:information_source: teď ten reg form Nezsik.Digital je v Users bázi, to by pro nás mělo být výrazně jednodušší celé
Pro pilot jo, ale výhledově nechceme, aby nám kvůli tomu všechny registrační tabulky naskákaly do Users. Zejména pokud tam potřebujou vazby na nějaké další projektové tabulky, které by tím pádem chtěli stěhovat do Users. My chceme ta projektová data z Users spíš vystrnadit než naopak :)
:hourglass: Zvládneme za měsíc nasadit tu verzi tak, aby to mohly holky použít na další běh ND?
Jak si to představuju v rámci vhodného flow a předschválily jsme si s Marťou a Romčou:
Je to reálné?
Podle mě je to velmi reálné. V detailech se můžem někde šprajcnout, ale neposíláme raketu do vesmíru, určitě můžem dojít k něčemu zhruba v těchto intencích tak, aby to bylo lepší než současný stav.
OK, tak tomu dejme prioritu.
Doplňuju z dnešního syncu tři varianty reakce na roli nebo event, když jsem přihlášený: Co se stane po kliknutí na tlačítko Mám zájem?
U eventu ještě možnost přihlásit se jako Guest
requireSignIn
(„vyžaduje přihlášení v aplikaci“) a prefillUser
(„chci do formuláře automaticky vyplnit přihlášeného uživatele“).requireSignIn
, tak to hlavní CTA tlačítko se bude zobrazovat pouze přihlášeným (a povede tam, co doposud). Ostatním se ukáže něco ve smyslu Musíš se nejdřív přihlásit, po přihlášení nebo registraci do aplikace skončí uživatel tam, co prve, a uvidí už aktivní CTA tlačítko.prefillUser
, do URL vyplněného v poli RSVP URL
(jesus, pojďme ho při téhle příležitosti přejmenovat :) se při prokliku automaticky přidají parametry prefill_User
a hide_User
, které se na straně formuláře dají použít pro automatické napojení dat k přihlášenému uživateli.requireSignIn
a prefillUser
jsou navzájem nezávislé – dává smysl chtít přihlášení bez předávání ID (mám vlastní formulář, ale chci mít jistotu, že lidi, co ho vyplní, jsou registrovaní do č.d) i předávání ID bez přihlášení (formulář zvládá obě varianty, přihlášení lidi to mají jednodušší)?Máme vlastně tři možnosti, jak tu reakci jedním klikem reprezentovat:
registeredUsers
, role má pole interestedUsers
a uživatelský profil má příslušná pole registeredEvents
a registeredOpportunities
. Tohle je nejjednodušší z pohledu úvodní administrace – založím event a jdu od toho. Ale bude se s tím hůř pracovat v Airtable? Kdyby s každou reakcí vznikl/zanikl nový záznam, dá se na to snadno pověsit třeba notifikace. Když vznikne/zanikne vazba, tak se s tím bude dělat blbě. (Takhle je to teď implementované pro eventy, viz #760.)Meetup Registration
, kde mně budou naskakovat řádky se sloupci User
(vazba do User Profiles) a Timestamp
(čas přihlášení). Tohle dobře odpovídá tomu, jak s eventy pracujeme dneska, a uživatelé z naší strany si tam můžou snadno psát poznámky nebo zobrazit další relevantní pole z User Profiles. Na druhou stranu to znamená, že pro každý event dostaneme úplně nový sloupec v tabulce User Profiles, což je trochu pakárna a taky to komplikuje agregace („které všechny eventy uživatel navštívil?“, viz https://github.com/cesko-digital/app/issues/807). Navíc bychom museli u eventu nějak dát vědět, kam mají ty odpovědi v Airtable padat. Tahle varianta ovšem přesně odpovídá tomu, jak celá věc funguje při použití custom formuláře, což může být velká výhoda.Nemám v tomhle úplně jasno, můžem zkusit probrat s uživateli anebo (zatím preferuju) tu reakci jedním klikem zatím neimplementovat a počkat na zkušenosti z provozu.
Jak už jsem psal výše, to ID přihlášeného uživatele se bohužel liší podle cílové databáze, ve které žije synchronizovaná tabulka User Profiles. Takže když to CTA tlačítko odkazuje na cílové URL a přidává do něj ID přihlášeného uživatele, musíme nějak zjistit, jaké ID to je. Navíc na straně formuláře už neběží náš kód (který by mohl být nějak chytrý), ale jen Airtable, pro kterou je to čistě mechanická vazba.
Technicky jednoduchá varianta je přidat do popisu eventu nebo role políčko identifikující, ve které databázi žije ten registrační formulář. Tedy třeba single select s variantami Users
, App
, Nezisk.Digital kurz
a podobně. Pak by ten volající kód našel přihlášeného uživatele (třeba podle registračního mailu) v synchronizované kopii User Profiles z dotyčné databáze a poslal do formuláře správné ID. Tohle je dobré v tom, že je to technicky jednoduché a explicitní. Ale vyžaduje to nějakou spolupráci od uživatelů/editorů.
Pak je ještě možný drobný hack. Ono se totiž dá pro jedno pole předvyplnit víc hodnot. Takže bychom mohli najít přihlášeného uživatele ve všech relevantních databázích a poslat do formuláře seznam všech IDs ze všech databází, přičemž Airtable si z toho vybere to správné ID a ostatní ignoruje (zkoušel jsem). Nevýhoda je v tom, že spálíme víc API dotazů, není to evidentní pro uživatele (například to nebude fungovat v nových databázích, které nejsou explicitně zmíněné v kódu) a to pole User
v registračním formuláři musí být (nelogicky) nastavené, aby akceptovalo víc lidí. Zase to ale funguje automaticky.
Mírně preferuju udělat to tou první, explicitní variantou. Dá se sdružit s některým z těch checkboxů zmíněných v předchozí sekci, například místo prefillUser
může být místo checkboxu single select s variantami Předvyplnit ID uživatele (App), Předvyplnit ID uživatele (Nezisk.Digital) a podobně. To by nešlo minout, ale zase to nemusí být moc srozumitelné pro editory.
Od Romči:
Jeden z našich nejdůležitějších use casů je nabírání lidí na nějaké role. Nejčastěji to stále děláme přes ad-hoc formuláře v Airtable (příklad), protože lepší variantu nemáme. Ta současná varianta ale trpí velkou řadou problémů – zejména se ptáme lidí pořád dokola na to stejné, vytváříme duplicity a zadaná data nám končí v nějaké random tabulce:
Potřebujeme to změnit tak, aby přihlášený uživatel nemusel vyplňovat věci, které už o něm víme, a zároveň data z registračního formuláře zachovala nějakou vazbu na uživatelský profil:
Technicky se to nabízí udělat tak, že odpověď na dotyčnou pozici bude vyžadovat přihlášení (případně registraci) a následně… nevíme co. Ty formuláře v Airtable jsou super flexibilní, tým s nimi umí dobře zacházet, ale nevím, jestli jde nějak zařídit ta vazba na stávající data. Airtable nabízí nějakou možnost předvyplnit data přes URL, což je zajímavá cesta zhruba naším směrem – obávám se, že to nebude dost dobré, ale mrknu na to.