Skip to content

Commit a062a24

Browse files
committed
Merge branch 'main' of github.com:devforth/adminforth
2 parents 0228d44 + 8f9bcfe commit a062a24

File tree

27 files changed

+395
-112
lines changed

27 files changed

+395
-112
lines changed

adminforth/commands/createResource/templates/resource.ts.hbs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export default {
1414
components: {
1515
list: "@/renderers/CompactUUID.vue",
1616
}{{/if}},
17+
showIn: {
18+
all:true,
19+
}
1720
}{{#unless @last}},{{/unless}}
1821
{{/each}}
1922
],

adminforth/dataConnectors/postgres.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
400400
}
401401
const primaryKey = this.getPrimaryKey(resource);
402402
const q = `INSERT INTO "${tableName}" (${columns.join(', ')}) VALUES (${placeholders}) RETURNING "${primaryKey}"`;
403+
// console.log('\n🔵 [PG INSERT]:', q);
404+
// console.log('📦 [VALUES]:', JSON.stringify(values, null, 2));
403405
if (process.env.HEAVY_DEBUG_QUERY) {
404406
console.log('🪲📜 PG Q:', q, 'values:', values);
405407
}

adminforth/dataConnectors/sqlite.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
143143
} else {
144144
return value;
145145
}
146+
}
147+
else if (field.isArray?.enabled) {
148+
if (value === null || value === undefined) {
149+
return null;
150+
}
151+
return JSON.stringify(value);
146152
} else if (field.type == AdminForthDataTypes.BOOLEAN) {
147153
return value === null ? null : (value ? 1 : 0);
148154
} else if (field.type == AdminForthDataTypes.JSON) {
@@ -322,7 +328,14 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
322328
const columns = Object.keys(record);
323329
const placeholders = columns.map(() => '?').join(', ');
324330
const values = columns.map((colName) => record[colName]);
325-
const q = this.client.prepare(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`);
331+
// const q = this.client.prepare(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`);
332+
const sql = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`;
333+
//console.log('\n🟢 [SQLITE INSERT]:', sql);
334+
//console.log('📦 [VALUES]:', JSON.stringify(values, null, 2));
335+
const q = this.client.prepare(sql);
336+
if (process.env.HEAVY_DEBUG_QUERY) {
337+
console.log('🪲📜 SQL Q:', q, 'values:', values);
338+
}
326339
const ret = await q.run(values);
327340
return ret.lastInsertRowid;
328341
}

adminforth/documentation/docs/tutorial/03-Customization/10-menuConfiguration.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Menu Configuration
1+
# Menu & Header
22

33

44
## Icons
@@ -253,3 +253,26 @@ import adminforth from '@/adminforth';
253253
adminforth.menu.refreshMenuBadges()
254254
```
255255

256+
## Avatars
257+
258+
If you want your user to have custom avatar you can use avatarUrl:
259+
260+
```ts title='./index.ts'
261+
262+
auth: {
263+
264+
...
265+
266+
avatarUrl: async (adminUser)=> {
267+
return `https://${process.env.STORAGE_PROVIDER_PATH}/${adminUser.dbUser.avatar_path}`
268+
},
269+
270+
...
271+
272+
}
273+
274+
```
275+
276+
This syntax can be use to get unique avatar for each user of hardcode avatar, but it makes more sense to use it with [upload plugin](https://adminforth.dev/docs/tutorial/Plugins/upload/#using-plugin-for-uploading-avatar)
277+
278+

adminforth/documentation/docs/tutorial/07-Plugins/04-RichEditor.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -221,18 +221,13 @@ export default {
221221
"exe",
222222
"webp",
223223
],
224-
maxFileSize: 1024 * 1024 * 20, // 5MB
224+
maxFileSize: 1024 * 1024 * 20, // 20MB
225225

226226

227227
filePath: ({ originalFilename, originalExtension, contentType }) =>
228228
`description_images/${new Date().getFullYear()}/${uuid()}/${originalFilename}.${originalExtension}`,
229229

230-
preview: {
231-
// Used to display preview (if it is image) in list and show views instead of just path
232-
// previewUrl: ({s3Path}) => `https://tmpbucket-adminforth.s3.eu-central-1.amazonaws.com/${s3Path}`,
233-
// show image preview instead of path in list view
234-
// showInList: false,
235-
},
230+
236231
}),
237232
],
238233
} as AdminForthResourceInput;

adminforth/documentation/docs/tutorial/07-Plugins/05-upload.md

Lines changed: 154 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ Leave all settings unchanged (ACL Disabled, Block all public access - checked)
3131
],
3232
"AllowedMethods": [
3333
"HEAD",
34-
"PUT"
34+
"PUT",
35+
"GET"
3536
],
3637
"AllowedOrigins": [
3738
"http://localhost:3500"
@@ -507,4 +508,155 @@ You can set the maximum width for the preview image in the `./resources/apartmen
507508
...
508509

509510
});
510-
```
511+
```
512+
513+
## Using plugin for uploading avatar
514+
515+
Let's say, that you want to use upload plugin for uploading avatar for each user.
516+
To do this add avatar column to the user resource:
517+
518+
519+
```ts title="./schema.prisma"
520+
model adminuser {
521+
id String @id
522+
email String @unique
523+
password_hash String
524+
role String
525+
created_at DateTime
526+
//diff-add
527+
avatar ?String
528+
}
529+
```
530+
531+
Then make migration:
532+
533+
```bash
534+
npm run makemigration -- --name add-user-avatar-field ; npm run migrate:local
535+
```
536+
537+
Add this column to the users resource:
538+
539+
```ts title="./resources/adminuser.ts"
540+
541+
...
542+
543+
columns: [
544+
545+
...
546+
547+
//diff-add
548+
{
549+
//diff-add
550+
name: "avatar",
551+
//diff-add
552+
type: AdminForthDataTypes.STRING,
553+
//diff-add
554+
showIn: ["show", "edit", "create" ],
555+
//diff-add
556+
},
557+
558+
...
559+
560+
]
561+
562+
...
563+
564+
plugins: [
565+
566+
...
567+
568+
//diff-add
569+
new UploadPlugin({
570+
//diff-add
571+
pathColumnName: "avatar",
572+
//diff-add
573+
storageAdapter: new AdminForthAdapterS3Storage({
574+
//diff-add
575+
bucket: process.env.AWS_BUCKET_NAME,
576+
//diff-add
577+
region: process.env.AWS_REGION,
578+
//diff-add
579+
accessKeyId: process.env.AWS_ACCESS_KEY_ID as string,
580+
//diff-add
581+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string,
582+
//diff-add
583+
}),
584+
//diff-add
585+
allowedFileExtensions: [
586+
//diff-add
587+
"jpg",
588+
//diff-add
589+
"jpeg",
590+
//diff-add
591+
"png",
592+
//diff-add
593+
"gif",
594+
//diff-add
595+
"webm",
596+
//diff-add
597+
"exe",
598+
//diff-add
599+
"webp",
600+
//diff-add
601+
],
602+
//diff-add
603+
maxFileSize: 1024 * 1024 * 20, // 20MB
604+
//diff-add
605+
filePath: ({ originalFilename, originalExtension, contentType, record }) => {
606+
//diff-add
607+
return `aparts/${new Date().getFullYear()}/${originalFilename}.${originalExtension}`
608+
//diff-add
609+
},
610+
//diff-add
611+
preview: {
612+
//diff-add
613+
maxWidth: "200px",
614+
//diff-add
615+
},
616+
//diff-add
617+
}),
618+
619+
...
620+
621+
]
622+
623+
```
624+
625+
And finally add this callback:
626+
627+
```ts title="./index.ts"
628+
629+
auth: {
630+
631+
...
632+
//diff-add
633+
avatarUrl: async (adminUser)=>{
634+
//diff-add
635+
const plugin = admin.getPluginsByClassName('UploadPlugin').find(p => p.pluginOptions.pathColumnName === 'avatar') as any;
636+
//diff-add
637+
if (!plugin) {
638+
//diff-add
639+
throw new Error('Upload plugin for avatar not found');
640+
//diff-add
641+
}
642+
//diff-add
643+
if (adminUser.dbUser.avatar === null || adminUser.dbUser.avatar === undefined || adminUser.dbUser.avatar === '') {
644+
//diff-add
645+
return '';
646+
//diff-add
647+
}
648+
//diff-add
649+
const imageUrl = await plugin.getFileDownloadUrl(adminUser.dbUser.avatar || '', 3600);
650+
//diff-add
651+
return imageUrl;
652+
//diff-add
653+
},
654+
655+
656+
...
657+
658+
}
659+
660+
```
661+
662+
And now you can easily update avatar for each user

adminforth/documentation/docs/tutorial/07-Plugins/11-oauth.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,4 +350,43 @@ Links to adapters:
350350
[Google](https://github.com/devforth/adminforth-google-oauth-adapter)
351351
[GitHub](https://github.com/devforth/adminforth-github-oauth-adapter)
352352
[Facebook](https://github.com/devforth/adminforth-facebook-oauth-adapter)
353-
[Keycloak](https://github.com/devforth/adminforth-keycloak-oauth-adapter)
353+
[Keycloak](https://github.com/devforth/adminforth-keycloak-oauth-adapter)
354+
355+
356+
## Fill user full name
357+
358+
If you have a fullName field in your users resource, you can add it to the plugin setup:
359+
360+
```ts
361+
362+
plugins: [
363+
...
364+
365+
new OAuthPlugin({
366+
367+
...
368+
369+
userFullNameField: 'fullName'
370+
371+
...
372+
373+
}),
374+
]
375+
376+
```
377+
378+
This field will be automatically filled with the name that the provider returns, if this field was empty.
379+
380+
> ☝️Not all providers return full name or even if they do, there is no guarantee that they will be correct
381+
382+
> Google Adapter: returns fullName, but if there is no last name - it will return only first name
383+
384+
>Facebook: returns fullName
385+
386+
>Github: returns name or fullName (depends of what user added in name field)
387+
388+
>Keycloak: returns fullName
389+
390+
>Microsoft: returns fullName
391+
392+
>Twitch: return only users display name

adminforth/documentation/docs/tutorial/07-Plugins/14-markdown.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export default {
113113
"exe",
114114
"webp",
115115
],
116-
maxFileSize: 1024 * 1024 * 20, // 5MB
116+
maxFileSize: 1024 * 1024 * 20, // 20MB
117117

118118

119119
filePath: ({ originalFilename, originalExtension, contentType }) =>

adminforth/modules/configValidator.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,18 @@ export default class ConfigValidator implements IConfigValidator {
11591159
} else {
11601160
newConfig.auth.beforeLoginConfirmation = blc;
11611161
}
1162+
1163+
// normalize adminUserAuthorize hooks
1164+
const aua = this.inputConfig.auth.adminUserAuthorize;
1165+
if (!Array.isArray(aua)) {
1166+
if (aua) {
1167+
newConfig.auth.adminUserAuthorize = [aua];
1168+
} else {
1169+
newConfig.auth.adminUserAuthorize = [];
1170+
}
1171+
} else {
1172+
newConfig.auth.adminUserAuthorize = aua;
1173+
}
11621174
}
11631175

11641176
// check for duplicate resourceIds and show which ones are duplicated

0 commit comments

Comments
 (0)