Skip to content

Commit 0b8981c

Browse files
committed
Merge branch 'main' of github.com:devforth/adminforth
2 parents 257b5e7 + b0015e0 commit 0b8981c

9 files changed

Lines changed: 318 additions & 134 deletions

File tree

adminforth/dataConnectors/sqlite.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,14 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
155155
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
156156
return value === null ? null : !!value;
157157
} else if (field.type == AdminForthDataTypes.JSON) {
158-
if (field._underlineType == 'text' || field._underlineType == 'varchar') {
158+
if (typeof value === 'string') {
159159
try {
160160
return JSON.parse(value);
161161
} catch (e) {
162162
return {'error': `Failed to parse JSON: ${e.message}`}
163163
}
164-
} else {
165-
afLogger.warn(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`);
166164
}
167165
}
168-
169166
return value;
170167
}
171168

@@ -192,12 +189,10 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
192189
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
193190
return value === null ? null : (value ? 1 : 0);
194191
} else if (field.type == AdminForthDataTypes.JSON) {
195-
// check underline type is text or string
196-
if (field._underlineType == 'text' || field._underlineType == 'varchar') {
197-
return JSON.stringify(value);
198-
} else {
199-
afLogger.warn(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`);
192+
if (value === null || value === undefined) {
193+
return null;
200194
}
195+
return typeof value === 'string' ? value : JSON.stringify(value);
201196
}
202197

203198
return value;

adminforth/documentation/docs/tutorial/05-Adapters/02-oauth2-adapters.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,47 +11,47 @@ Used to authenticate users via OAuth 2.0 providers.
1111
## Google OAuth Adapter
1212

1313
```bash
14-
pnpm i @adminforth/google-oauth-adapter
14+
pnpm i @adminforth/oauth-adapter-google
1515
```
1616

1717
Supports Google sign-in to allow users to authenticate using their Google or Google Workspaces accounts.
1818

1919
## GitHub OAuth Adapter
2020

2121
```bash
22-
pnpm i @adminforth/github-oauth-adapter
22+
pnpm i @adminforth/oauth-adapter-github
2323
```
2424

2525
Enables authentication via GitHub accounts, useful for developer tools and open-source apps.
2626

2727
## Facebook OAuth Adapter
2828

2929
```bash
30-
pnpm i @adminforth/facebook-oauth-adapter
30+
pnpm i @adminforth/oauth-adapter-facebook
3131
```
3232

3333
Allows users to log in with Facebook credentials. Facebook OAuth is commonly used for social media integrations.
3434

3535
## Keycloak OAuth Adapter
3636

3737
```bash
38-
pnpm i @adminforth/keycloak-oauth-adapter
38+
pnpm i @adminforth/oauth-adapter-keycloak
3939
```
4040

4141
Connects AdminForth to an open-source [Keycloak](https://www.keycloak.org/) identity provider for enterprise-grade SSO (Single Sign-On).
4242

4343
## Microsoft OAuth Adapter
4444

4545
```bash
46-
pnpm i @adminforth/microsoft-oauth-adapter
46+
pnpm i @adminforth/oauth-adapter-microsoft
4747
```
4848

4949
Supports login through Microsoft accounts including Azure AD, Office365, and Outlook.com.
5050

5151
## Twitch OAuth Adapter
5252

5353
```bash
54-
pnpm i @adminforth/twitch-oauth-adapter
54+
pnpm i @adminforth/oauth-adapter-twitch
5555
```
5656

5757
Adds support for Twitch authentication, useful for streaming or creator-oriented platforms.

adminforth/documentation/docs/tutorial/05-Adapters/09-chat-surface-adapters.md

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,23 @@ sidebar_position: 8
77

88
# Telegram Chat Surface Adapter
99

10-
Chat surface adapters connect external chat products to the [Agent plugin](/docs/tutorial/Plugins/agent/).
10+
Chat surface adapters connect external chat products to the [Agent plugin](/docs/tutorial/Plugins/agent/). They only receive and send chat messages. User linking is handled through OAuth connected accounts.
11+
12+
For Telegram you need both adapters:
1113

1214
```bash
1315
pnpm i @adminforth/chat-surface-adapter-telegram
16+
pnpm i @adminforth/oauth-adapter-telegram
1417
```
1518

16-
Create a Telegram bot with BotFather and add the token to `.env`:
19+
Create a Telegram bot with BotFather and copy the token:
20+
21+
1. Open [BotFather](https://t.me/BotFather).
22+
2. Click **Open** and open it in the Telegram app.
23+
3. Select or Create your bot.
24+
4. Copy the bot token shown at the top.
25+
26+
Add the token to `.env`:
1727

1828
```env title=".env"
1929
TELEGRAM_BOT_TOKEN=your_bot_token
@@ -23,57 +33,62 @@ TELEGRAM_WEBHOOK_SECRET=your_random_secret
2333

2434
The webhook secret confirms that the request came through Telegram.
2535

26-
## Admin user field `externalUserId`
36+
## External identity `externalUserId`
2737

28-
External chat accounts are linked by the Agent plugin, not by the Telegram adapter directly. The plugin stores linked external user ids in a JSON field on the AdminForth auth user resource.
38+
External chat accounts are resolved through OAuth connected accounts. The Telegram OAuth adapter writes the Telegram user id into `externalUserId` on the external identities resource. The Agent plugin then uses that field to map incoming Telegram messages to AdminForth users.
2939

30-
By default this field is named `externalUserId`. Add it to your `adminuser` resource:
40+
Add the field to your external identities resource:
3141

3242
```ts
3343
{
3444
name: 'externalUserId',
35-
type: AdminForthDataTypes.JSON,
45+
type: AdminForthDataTypes.STRING,
3646
},
3747
```
3848

3949
Also add the matching column to your database schema and run a migration. For example, with Prisma and PostgreSQL:
4050

4151
```prisma title="schema.prisma"
42-
model adminuser {
43-
// existing fields
44-
externalUserId Json?
45-
}
46-
```
47-
48-
For Prisma SQLite, store the same field as text:
49-
50-
```prisma title="schema.prisma"
51-
model adminuser {
52+
model AdminUserExternalIdentity {
5253
// existing fields
5354
externalUserId String?
5455
}
5556
```
5657

57-
AdminForth should still define this resource column as `AdminForthDataTypes.JSON`; the SQLite connector serializes it into the text column and parses it back.
58-
5958
Then create and apply the migration using your app's migration scripts:
6059

6160
```bash
62-
pnpm makemigration --name add-adminuser-external-user-id
61+
pnpm makemigration --name add-external-identity-external-user-id
6362
pnpm migrate:local
6463
```
6564

66-
When a Telegram account is linked, the field stores data like this:
65+
Configure the OAuth plugin with Telegram OAuth:
6766

68-
```json
69-
{
70-
"telegram": "123456789"
71-
}
72-
```
67+
```ts title="./resources/adminuser.ts"
68+
import OAuthPlugin from '@adminforth/oauth';
69+
import TelegramOauthAdapter from '@adminforth/oauth-adapter-telegram';
7370

74-
If your field is named differently, configure `chatExternalIdsField` on the Agent plugin.
71+
new OAuthPlugin({
72+
emailField: 'email',
73+
externalIdentityResource: {
74+
resourceId: 'admin_user_external_identities',
75+
phoneField: 'phone',
76+
fullNameField: 'fullName',
77+
avatarUrlField: 'avatarUrl',
78+
metaField: 'meta',
79+
},
80+
adapters: [
81+
new TelegramOauthAdapter({
82+
clientID: process.env.TELEGRAM_CLIENT_ID as string,
83+
clientSecret: process.env.TELEGRAM_CLIENT_SECRET as string,
84+
redirectUri: process.env.TELEGRAM_OAUTH_REDIRECT_URI as string,
85+
scopes: ['openid', 'profile', 'phone'],
86+
}),
87+
],
88+
});
89+
```
7590

76-
Register the adapter in the Agent plugin:
91+
Then register the Telegram chat surface adapter in the Agent plugin:
7792

7893
```ts
7994
import AdminForthAgent from '@adminforth/agent';
@@ -103,28 +118,35 @@ new AdminForthAgent({
103118
}),
104119
//diff-add
105120
],
106-
// optional, defaults to 'externalUserId'
107121
//diff-add
108-
chatExternalIdsField: 'externalUserId',
122+
chatExternalIdentityResource: {
123+
//diff-add
124+
resourceId: 'admin_user_external_identities',
125+
//diff-add
126+
surfaces: {
127+
//diff-add
128+
telegram: {
129+
//diff-add
130+
provider: 'AdminForthAdapterTelegramOauth2',
131+
//diff-add
132+
},
133+
//diff-add
134+
},
135+
//diff-add
136+
},
109137
});
110138
```
111139

112-
When `botUsername` is configured, the Agent plugin adds **Chat Surfaces** to the user menu settings pages. A logged-in AdminForth user can open that page and click **Connect**. The Telegram adapter returns a URL like:
113-
114-
```txt
115-
https://t.me/<botUsername>?start=<link-token>
116-
```
117-
118-
After the user starts the bot with that token, AdminForth stores the Telegram user id in `externalUserId.telegram`. The same page also supports reconnecting and disconnecting the Telegram account.
140+
External chat users are resolved through OAuth connected accounts. Configure OAuth `externalIdentityResource` and Agent `chatExternalIdentityResource`, then let users connect Telegram from **Connected Accounts**.
119141

120-
You can also prefill the JSON field manually if you do not want to use the connect page.
142+
The `provider` value must match the Telegram OAuth adapter class name. Users must connect Telegram in **Settings -> Connected Accounts** before the Telegram bot can identify them.
121143

122144
## Adapter options
123145

124146
All options for `new TelegramChatSurfaceAdapter(options)`:
125147

126148
- `botToken` (string, required) — Telegram bot token from BotFather.
127-
- `botUsername` (string, optional) — bot username used to build the account-link URL for the **Chat Surfaces** settings page.
149+
- `botUsername` (string, optional) — bot username. OAuth connected accounts are used for user linking.
128150
- `webhookSecret` (string, optional) — secret token configured in Telegram `setWebhook`.
129151
- `streamingMode` (`draft` | `typing` | `off`, optional) — streaming behavior for Telegram responses.
130152
- Default: `draft`.

adminforth/documentation/docs/tutorial/08-Plugins/01-agent.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,25 +287,41 @@ The plugin adds a chat surface to the admin UI, keeps session history per admin
287287
## Chat surfaces (Telegram, etc.)
288288

289289
By default, the Agent plugin exposes a chat surface inside the AdminForth admin UI.
290-
If you want to talk to the same agent from external chat products (Telegram, etc.), connect a **chat surface adapter**.
290+
If you want to talk to the same agent from external chat products (Telegram, Slack, Teams, etc.), configure both:
291+
292+
- a **chat surface adapter** that receives messages from the external chat product
293+
- an **OAuth adapter** for the same provider so users can connect that external account in **Connected Accounts**
294+
295+
For example, Telegram Agent access needs both `@adminforth/chat-surface-adapter-telegram` and `@adminforth/oauth-adapter-telegram`.
291296

292297
Register adapters through `chatSurfaceAdapters`:
293298

294299
```ts
295300
import AdminForthAgent from '@adminforth/agent';
296-
import SomeChatSurfaceAdapter from '@adminforth/some-chat-surface-adapter';
301+
import TelegramChatSurfaceAdapter from '@adminforth/chat-surface-adapter-telegram';
297302

298303
new AdminForthAgent({
299304
// ...modes, sessionResource, turnResource, etc.
300305
chatSurfaceAdapters: [
301-
new SomeChatSurfaceAdapter({
302-
// adapter-specific options
306+
new TelegramChatSurfaceAdapter({
307+
botToken: process.env.TELEGRAM_BOT_TOKEN as string,
308+
webhookSecret: process.env.TELEGRAM_WEBHOOK_SECRET,
303309
}),
304310
],
311+
chatExternalIdentityResource: {
312+
resourceId: 'admin_user_external_identities',
313+
surfaces: {
314+
telegram: {
315+
provider: 'AdminForthAdapterTelegramOauth2',
316+
},
317+
},
318+
},
305319
});
306320
```
307321

308-
When an adapter supports account linking, the Agent plugin adds a user menu settings page named **Chat Surfaces** where logged-in users can connect, reconnect, and disconnect external accounts.
322+
External chat users are resolved through the OAuth external identities resource. The `provider` value in `chatExternalIdentityResource.surfaces` must match the OAuth adapter class that writes connected accounts, for example `AdminForthAdapterTelegramOauth2`.
323+
324+
Users connect their Telegram account from **Settings -> Connected Accounts**. After that, messages from the Telegram bot can be matched to the AdminForth user through the external identity `externalUserId`.
309325

310326
For Telegram setup, including required user fields, webhook URL, environment variables, and adapter options, see:
311327

0 commit comments

Comments
 (0)