Prezentare generală
Conexiunile sunt acreditări pe care un utilizator le deține pentru un serviciu extern (Linear, GitHub, Slack, …). Aplicația ta declară cum sunt obținute acele acreditări — un furnizor de conexiune — și le folosește în timpul execuției pentru a efectua apeluri autentificate către API-ul terț. OAuth 2.0 este integrat. Serviciile cu propriul flux de conectare — o pagină de autentificare găzduită, un ID de cont transmis prin webhook — folosesc un furnizorcustom, unde aplicația ta gestionează fluxul, iar Twenty păstrează utilizatorul, spațiul de lucru și conexiunea salvată. Tipurile viitoare de acreditări (jetoane de acces personale, chei API, autentificare de bază) se vor integra în aceeași interfață — aplicațiile care deja folosesc defineConnectionProvider({ type: 'oauth', ... }) nu vor trebui să migreze.
defineConnectionProvider
Declară cum sunt obținute conexiunile aplicației tale
defineConnectionProvider
Declară cum sunt obținute conexiunile aplicației tale
WORKSPACE (implicit), un membru face clic pe “Adaugă conexiune” în setările aplicației tale, completează ecranul de consimțământ al furnizorului și este creată o înregistrare ConnectedAccount în spațiul său de lucru. Consultă „Conexiuni de spațiu de lucru sau personale” pentru furnizorii USER.O configurație funcțională are nevoie de două fișiere — furnizorul de conexiune și o declarație serverVariables corespunzătoare în defineApplication care conține acreditările clientului OAuth.nameeste șirul identificator unic folosit înlistConnections({ providerName })(kebab-case, trebuie să corespundă^[a-z][a-z0-9-]*$).displayNameapare în fila General a aplicației și în lista de instrumente AI.scopestabilește cine se conectează:'WORKSPACE'(implicit) pentru conexiuni partajate cu întregul spațiu de lucru,'USER'pentru conexiunile pe care fiecare membru le realizează pentru sine. Consultă mai jos „Conexiuni de spațiu de lucru sau personale”.logoeste o cale către un activ inclus în pachet în folderulpublic/al aplicației dvs., servit prin activele publice ale aplicației. Când este omis, fila General revine la un substituent generat dindisplayName.clientIdVariable/clientSecretVariablesunt nume, nu valori — trebuie să se potrivească cheilor declarate îndefineApplication.serverVariables. Valorile realeclient_idșiclient_secretsunt introduse de administratorul serverului prin interfața de înregistrare a aplicației și nu sunt niciodată comise în repo-ul tău.- Folosește
serverVariables(nuapplicationVariables) — acreditările OAuth sunt la nivel de server și există o singură aplicație OAuth pentru fiecare server Twenty. - Până când ambele
serverVariablessunt completate, fila General a aplicației afișează un indiciu „necesită administrator de server”, iar butonul „Adaugă conexiune” este dezactivat. typeeste'oauth'(cu un blocoauth) sau'custom'(cu un bloccustom, consultați “Fluxuri de conexiune personalizate”). Discriminatorul este compatibil cu versiuni viitoare: tipurile viitoare ('pat','api-key', …) vor adăuga blocuri noi de sub-configurație alături de acestea.
Fluxuri de conectare personalizate
Conectați servicii care nu sunt furnizori OAuth
Fluxuri de conectare personalizate
Conectați servicii care nu sunt furnizori OAuth
type: 'custom' și două funcții logice:authorizeLogicFunction cu un callbackUrl care o conține. Returnați unde să fie trimis utilizatorul:callbackUrl serviciului fără modificări. Twenty o acceptă ca redirecționare din browser (GET) și ca notificare de la server (POST) și rulează callbackLogicFunction pentru fiecare solicitare cu metoda sa, parametrii de interogare (fără state), antetele, corpul analizat și rawBody (octeții exacți ai solicitării, null pentru GET). Returnează contul pe care îl dovedește cererea sau null atunci când nu conține niciunul — de obicei, când browserul revine, în timp ce ID-ul contului este transmis prin notificare:callbackUrl dovedește doar că solicitarea conține acel URL, nu că serviciul a trimis-o. Când serviciul își semnează notificările, verificați semnătura pentru rawBody înainte de a avea încredere în corp. Antetele sunt scrise cu litere mici, iar cookie, authorization și proxy-authorization nu sunt niciodată transmise:onConnectLogicFunction nu rulează. onConnectLogicFunction rulează când o conexiune este creată, reconectată sau restaurată, dar nu rulează din nou când serviciul raportează un cont deja conectat. Starea expiră după o oră, astfel încât o notificare sosită mai târziu este respinsă. Serviciile reîncearcă frecvent notificările: o repetare pentru un cont deja conectat actualizează acea conexiune, astfel încât returnarea din nou a aceluiași cont este sigură.Twenty nu reîmprospătează și nu revocă conexiunile personalizate. Eliberați ceea ce deține serviciul pentru cont în onDisconnectLogicFunction.type al unui furnizor, precum scope al acestuia, nu se poate modifica după ce este sincronizat: pentru a muta un serviciu între oauth și custom, declarați un furnizor nou cu un universalIdentifier nou.Furnizorii personalizați sunt disponibili în Twenty 2.52.0.Identificați contul conectat
Împiedicați o reconectare să schimbe în mod silențios conturile sursă
Identificați contul conectat
Împiedicați o reconectare să schimbe în mod silențios conturile sursă
identifyAccountLogicFunction la o funcție logică din aceeași aplicație care returnează un ID stabil pentru contul asociat tokenului proaspăt emis:timeoutSeconds al funcției la 10, indiferent de ce declară manifestul; păstrați-l la o singură cerere către endpointul furnizorului „cine sunt eu”. Hookul on-connect, dacă există, rulează totuși ulterior, după ce conexiunea este salvată.Încărcătură utilă. Handlerul primește tokenul de acces provizoriu. Nu a fost încă persistat, deci getConnection nu îl poate returna; utilizați-l direct și nu îl înregistrați în jurnal.externalAccountIdtrebuie să fie stabil pe durata de viață a contului din amonte (un id de echipă, un id de organizație, un id de utilizator), niciodată un nume pe care utilizatorul îl poate modifica. Twenty îl elimină de spațiile de la început și de la sfârșit și îl stochează în conexiune la prima conectare.handle, atunci când este returnat, înlocuiește handle-ul pe care Twenty l-ar deduce altfel (e-mailul OIDC dinid_tokensau e-mailul utilizatorului care se conectează). Returnați ceva ce recunoaște un utilizator, cum ar fi numele spațiului de lucru Slack.- Returnați
{ externalAccountId: null }atunci când furnizorul nu are un id stabil de oferit. Twenty se comportă apoi ca și cum nu ar fi fost declarată nicio funcție de identificare: nu este stocat niciun id, o reconectare șterge orice id stocat anterior, iar reconectările nu sunt verificate. Un simplunullsau lipsa unei valori returnate este tratată ca o eroare, astfel încât un handler care uită să returneze o valoare nu poate dezactiva verificarea în mod silențios. - Dacă funcția generează o excepție, expiră sau returnează orice altceva, conexiunea nu este salvată, iar utilizatorul revine pe pagina de setări cu o eroare. Generați o excepție doar atunci când chiar nu puteți identifica contul.
externalAccountId returnat cu cel stocat în conexiune. Dacă diferă, callback-ul este refuzat înainte de a se scrie ceva: tokenurile, handle-ul și domeniul de aplicare existente rămân neschimbate, hook-ul on-connect nu se execută, iar utilizatorul vede ce cont a autorizat și cărui cont îi aparține conexiunea. Conexiunile create înainte ca aplicația dvs. să declare funcția nu au încă un id stocat; următoarea lor reconectare îl stochează.Twenty nu elimină duplicatele pe baza externalAccountId: conectarea aceluiași cont din amonte de două ori prin Adăugare conexiune creează două conexiuni. Id-ul este expus în listConnections și getConnection, astfel încât o aplicație care dorește o conexiune per cont din amonte poate detecta ea însăși duplicatele (de exemplu, în hookul său on-connect).Scrierea funcției. Majoritatea furnizorilor expun un singur endpoint care descrie tokenul curent. Pentru Slack, acesta este auth.test, care returnează spațiul de lucru (team_id, team) și utilizatorul din spatele tokenului:String(id).Identificarea este disponibilă în Twenty 2.48.0. Dacă aplicația dvs. se bazează pe aceasta, declarați "engines": { "twenty": ">=2.48.0" } în package.json al acesteia.Rulează o funcție logică la conectare
Reacționează în momentul în care o conexiune este stabilită
Rulează o funcție logică la conectare
Reacționează în momentul în care o conexiune este stabilită
team_id al spațiului de lucru după care vor fi indexate evenimentele primite. Setează onConnectLogicFunction pentru a face referire la o funcție logică din aceeași aplicație (prin universalIdentifier), iar aceasta rulează imediat după ce ConnectedAccount este creat.getConnection(connectedAccountId) pentru a citi tokenul de acces proaspăt și a apela API-ul furnizorului (de ex. Slack auth.test) sau pentru a stoca o mapare în magazinul cheie–valoare.Rulează o funcție logică la deconectare
Curăță resursele atunci când o conexiune este deconectată sau eliminată.
Rulează o funcție logică la deconectare
Curăță resursele atunci când o conexiune este deconectată sau eliminată.
team_id la conectare, de exemplu, trebuie să elibereze acea revendicare astfel încât un alt spațiu de lucru să poată conecta aceeași echipă Slack. Setează onDisconnectLogicFunction pentru a face referire la o funcție logică din aceeași aplicație, iar aceasta rulează când conexiunea este deconectată și din nou când este ștearsă.ConnectedAccount și tokenul său sunt încă prezente, astfel încât getConnection(connectedAccountId) se rezolvă, iar handlerul poate elibera orice a înregistrat de la distanță. În cazul unei ștergeri, datele de autentificare pot fi deja eliminate (un membru poate șterge o conexiune pe care a deconectat-o anterior), așa că fă gestionarul idempotent și păstrează starea de care are nevoie (un team_id, un ID extern de abonament) în magazinul cheie-valoare, scrisă la conectare și având drept cheie connectedAccountId. Păstrează-l scurt: rulează în cadrul cererii, astfel încât timeoutSeconds reprezintă limita superioară a duratei acestei cereri.Hook-ul este declanșat atunci când o conexiune este deconectată sau eliminată de la sine. Dezinstalarea aplicației elimină conexiunile acesteia printr-un mecanism în cascadă în baza de date, astfel încât hook-ul nu rulează în acest caz. Declară un uninstallLogicFunction pe defineApplication pentru acel flux: acesta rulează înainte ca metadatele aplicației să fie șterse, astfel încât poate apela în continuare listConnections și poate curăța tot ce a mai rămas.listConnections / getConnection
Folosește conexiunile dintr-o funcție logică
listConnections / getConnection
Folosește conexiunile dintr-o funcție logică
listConnections({ providerName }) returnează înregistrările ConnectedAccount ale acestei aplicații pentru furnizorul dat, cu tokenuri de acces reîmprospătate.- Pasează
{ providerName }pentru a filtra după furnizor; omite-l pentru a obține toate conexiunile pe care această aplicație le deține la toți furnizorii. - Serverul reîmprospătează transparent tokenul de acces înainte de a returna. Handlerul tău vede întotdeauna un token utilizabil (sau
authFailedAtsetat). getConnection(id)este echivalentul pentru o singură înregistrare.
reportConnectionAuthFailure
Indică platformei că o acreditare a expirat
reportConnectionAuthFailure
Indică platformei că o acreditare a expirat
authFailedAt numai atunci când reîmprospătarea OAuth eșuează. Furnizorii ale căror tokenuri nu sunt reîmprospătate niciodată (de exemplu, un token de bot Slack) eșuează doar în momentul apelului, în gestionarele dvs., astfel încât rândul conexiunii din setări va continua să afișeze Conectat, în timp ce fiecare apel eșuează. Când codul dvs. întâlnește o respingere definitivă a autentificării, raportați-o:authFailedAt și motivul opțional pentru conexiune. Rândul din setări devine Este necesară reconectarea cu un buton Reconectare, pagina cu detaliile conexiunii afișează motivul, iar getConnection începe să lanseze AppConnectionAuthFailedError pentru acel rând. Indicatorul și motivul se șterg automat când utilizatorul se reconectează. Un reason mai lung de 1000 de caractere este respins, așa că trunchiați datele utile ale furnizorului înainte de a le transmite.Raportați numai eșecurile pe care o reconectare le-ar remedia efectiv (o respingere de tip invalid_auth de la furnizor), niciodată erorile de rețea tranzitorii. O aplicație își poate raporta numai propriile conexiuni, iar un utilizator al cererii își poate raporta numai propriile acreditări personale.Mutația din spatele acestei funcții auxiliare este livrată odată cu Twenty 2.40.0, astfel că apelarea ei către un server mai vechi eșuează. Dacă aplicația dvs. o utilizează, declarați dependența în package.json: "engines": { "twenty": ">=2.40.0" }.Conexiuni de spațiu de lucru sau personale
Alege cine se conectează cu domeniul de aplicare al furnizorului
Conexiuni de spațiu de lucru sau personale
Alege cine se conectează cu domeniul de aplicare al furnizorului
- Partajată la nivel de spațiu de lucru (
'WORKSPACE') — orice membru al spațiului de lucru poate folosi acreditarea. Declanșatoarele cron / din bază de date o văd, de asemenea, deoarece nu au un utilizator al cererii. - Doar pentru mine (
'USER') — acreditarea aparține membrului care se conectează. În rulările efectuate în numele unui membru (declanșator de rută HTTP cuisAuthRequired: true),listConnectionsreturnează conexiunile partajate plus conexiunile proprii ale acelui membru, iarfindConnectionForRequestalege conexiunea personală a membrului, recurgând la una partajată atunci când acesta nu are niciuna. În rulările fără un utilizator al cererii (de exemplu, declanșatoare cron),listConnectionsreturnează fiecare conexiune, inclusiv conexiunile personale ale fiecărui membru.
scope al furnizorului stabilește pe care îl primesc noile sale conexiuni:scope: 'WORKSPACE'(implicit) — aplicația funcționează cu conexiuni partajate cu spațiul de lucru. Adăugare conexiune în setările spațiului de lucru ale aplicației creează o conexiune partajată în spațiul de lucru.scope: 'USER'— fiecare membru își conectează propriul cont, creând conexiuni personale. Membrii le adaugă, le reconectează și le elimină din pagina aplicației, în Setări > Utilizator > Preferințe aplicații, ceea ce necesită permisiunea Aplicații utilizator. Setările spațiului de lucru ale aplicației nu au un buton Adăugare conexiune pentru un furnizorUSER.
USER, așa că nu vă bazați pe una pentru
o funcționalitate de care fiecare spațiu de lucru are nevoie acum.scope al unui furnizor existent, iar actualizarea este refuzată dacă încearcă acest lucru. Pentru a muta un serviciu dintr-un scop în altul, declarați un furnizor nou cu un universalIdentifier nou și eliminați-l pe cel vechi. Actualizarea elimină apoi furnizorul vechi și fiecare conexiune realizată cu acesta prin fluxul obișnuit de deconectare (onDisconnectLogicFunction, revocarea tokenului, curățarea canalului), iar membrii se conectează din nou prin noul furnizor.Adăugarea sau reconectarea unei conexiuni Doar pentru mine necesită permisiunea Aplicații utilizator, iar adăugarea sau reconectarea uneia Partajată în spațiul de lucru necesită permisiunea Aplicații spațiu de lucru.Folosește conexiunea potrivită pentru fiecare handler:scope, declară "engines": { "twenty": ">=2.49.0" } în package.json al acesteia. În aceeași versiune, scope al unei conexiuni înlocuiește visibility, care rămâne disponibil ca alias depreciat cu litere mici. listConnections și getConnection din twenty-sdk 2.49.0 citesc scope, astfel încât aplicațiile construite cu acesta necesită un server 2.49.0.Configurare unică a furnizorului
Înregistrează-ți aplicația OAuth la serviciul terț
Configurare unică a furnizorului
Înregistrează-ți aplicația OAuth la serviciul terț
- Mergi la setările pentru dezvoltatori ale furnizorului (de ex. https://linear.app/settings/api/applications/new).
- Setează Redirect URI la
\<SERVER_URL>/auth/apps/callback. - Copiază Client ID și Client Secret generate.
- Deschide aplicația instalată în Twenty ca administrator de server → setează valorile pe
serverVariablescorespunzătoare. - Membrii spațiului de lucru pot apoi să adauge conexiuni la furnizori
WORKSPACEdin secțiunea Conexiuni a fiecărei aplicații.