Skip to content

Commit e67046f

Browse files
committed
Merge branch 'next' of github.com:devforth/adminforth into feature/AdminForth/893/bug-with-login-via-google
2 parents 1db029f + 3d499d0 commit e67046f

File tree

27 files changed

+1259
-774
lines changed

27 files changed

+1259
-774
lines changed

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# AdminForth - fully free Node.js admin panel framework on Vue & Tailwind
1+
# AdminForth - free powerfull Node.js admin panel framework on Vue & Tailwind
22

33

44
<a href="https://adminforth.dev"><img src="https://img.shields.io/badge/website-adminforth.dev-blue" style="height:24px"/></a> <a href="https://adminforth.dev"><img src="https://img.shields.io/npm/dw/adminforth" style="height:24px"/></a> <a href="https://devforth.io"><img src="https://raw.githubusercontent.com/devforth/OnLogs/e97944fffc24fec0ce2347b205c9bda3be8de5c5/.assets/df_powered_by.svg" style="height:28px"/></a>
@@ -20,12 +20,15 @@
2020
<br/>
2121

2222
Why AdminForth:
23-
* AdminForth is always free and open-source (no paid versions, no cloud subscriptions sh*t)
24-
* Init AdminForth with your database URL in Node.js file, easily describe the tables you wish to see in admin, and get fully functional UI for your data (filter, create, edit, remove)
25-
* Define Vue components to change look of various parts of admin (place in data cell, instead of row, add something above the table, inject something to header or sidebar, add custom page with charts or custom components)
26-
* Rich build-in Components library (AdminForth AFCL) with premade easy-to-use build-blocks which follow your theme
23+
24+
* Init AdminForth project with `npx adminforth create-app` and pass your database URL, import the tables you wish to see in admin using `npx adminforth resource`, and get fully functional UI for your data (filter, create, edit, remove)
25+
* Modern look and simple Tailwind-ish ability to adjust it
26+
* Supports Postgres, MySQL, Mongo, SQLite, Clickhouse
27+
* Define Vue components to change look of various parts of admin using `npx adminforth component` (edit data cells, edit fields, add something above the table, inject something to header or sidebar, add custom page with charts or custom components)
28+
* Build-in Components library (AdminForth AFCL) with premade easy-to-use build-blocks which follow your theme
2729
* Define express APIs and call them from your components and pages
28-
* Use various modern back-office-must-have plugins like audit log, files/image upload, TOTP 2FA, I18N, Copilot-style AI writing and image generation
30+
* Use various modern back-office-must-have plugins like audit log, files/image upload, TOTP 2FA, I18N, Copilot-style AI writing and image generation and many more
31+
* AdminForth is always free and open-source (no paid versions, no cloud subscriptions sh*t)
2932

3033

3134
## Project initialisation
@@ -79,6 +82,9 @@ npm run install-plugins
7982
npm run install-adapters
8083

8184
npm ci
85+
86+
./run_inventory.sh
87+
8288
npm run migrate:local
8389
npm start
8490
```
@@ -117,4 +123,4 @@ Then, go to testing app, e.g. created with CLI, and use next command:
117123
npx -g adminforth <your command under development>
118124
```
119125

120-
This will always run latest version of adminforth package.
126+
This will always run latest version of adminforth package.

adminforth/documentation/blog/authors.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ivanb:
44
url: https://github.com/ivictbor
55
image_url: https://avatars.githubusercontent.com/u/1838656?v=4
66
mpipkun:
7-
name: Maxim Pypkun
7+
name: Maksym Pipkun
88
title: Developer of AdminForth
99
url: https://github.com/NoOne7135
1010
image_url: https://avatars.githubusercontent.com/u/120279695?v=4
@@ -22,4 +22,4 @@ kirilldorr:
2222
name: Kyrylo Doropii
2323
title: DevOps Engineer of AdminForth
2424
url: https://github.com/kirilldorr
25-
image_url: https://avatars.githubusercontent.com/u/181721742?s=96&v=4
25+
image_url: https://avatars.githubusercontent.com/u/181721742?s=96&v=4

adminforth/documentation/docs/tutorial/03-Customization/04-hooks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ For example we can prevent the user to see Apartments created by other users. Su
137137
}
138138

139139
// this function will skip existing realtor_id filter if it supplied already from UI or previous hook, and will add new one for realtor_id
140-
query.filterTools.replaceOrAddTopFilter(Filters.EQ('realtor_id', adminUser.dbUser.id).
140+
query.filterTools.replaceOrAddTopFilter(Filters.EQ('realtor_id', adminUser.dbUser.id)
141141

142142
return { ok: true };
143143
},

adminforth/documentation/docs/tutorial/03-Customization/15-afcl.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,26 @@ import { IconSearchOutline } from '@iconify-prerendered/vue-flowbite'
333333
</div>
334334
</div>
335335

336+
## Textarea
337+
<div class="split-screen" >
338+
<div >
339+
```ts
340+
import { Textarea } from '@/afcl'
341+
```
342+
343+
```ts
344+
<Textarea
345+
v-model="textAreaInput"
346+
placeholder="Enter some text..."
347+
class="w-64"
348+
/>
349+
```
350+
</div>
351+
<div>
352+
![AFCL Textarea](textarea.png)
353+
</div>
354+
</div>
355+
336356
## Tooltip
337357

338358
Wrap an element on which you would like to show a tooltip with the `Tooltip` component and add a `tooltip` slot to it.
6.38 KB
Loading
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Email Invite
2+
3+
Email Invite plugin allows administrators to create users without setting passwords. Instead, the plugin sends an email invitation to the newly created user, asking them to set their own password. This is more secure and user-friendly than having administrators set passwords for users.
4+
5+
## Installation
6+
7+
To install the plugin:
8+
9+
```bash
10+
npm install @adminforth/email-invite --save
11+
```
12+
13+
You'll also need an email adapter. For AWS SES:
14+
15+
```bash
16+
npm install @adminforth/email-adapter-aws-ses --save
17+
```
18+
19+
## SES
20+
21+
To Setup SES, you need to have an AWS account and SES service enabled. You can follow the steps below to setup SES.
22+
23+
1. Go to the AWS Management Console and open the Amazon SES console at [https://console.aws.amazon.com/ses/](https://console.aws.amazon.com/ses/).
24+
2. Make sure you are in the correct region. You can change the region from the top right corner. For example, if you are in the `us-east-1` region, you can see the region name US East (N. Virginia) in the top right corner.
25+
26+
3. Add your email address (any email), and verify it.
27+
4. Add some domain you own and verify it by creating DNS records which AWS suggests. This will be used as the domain for sending emails. e.g. if you want to send from no-reply@devforth.io you need to verify `devforth.io`.
28+
29+
## Basic Usage
30+
31+
```typescript title="./resources/adminuser.ts"
32+
import EmailInvitePlugin from '@adminforth/email-invite';
33+
import EmailAdapterAwsSes from '@adminforth/email-adapter-aws-ses';
34+
35+
export default {
36+
dataSource: 'maindb',
37+
table: 'adminuser',
38+
resourceId: 'adminuser',
39+
columns: [
40+
{ name: 'id', primaryKey: true },
41+
{ name: 'email', required: true },
42+
{ name: 'password_hash', showIn: [] }, // Hide from UI
43+
44+
{ name: 'role' },
45+
46+
{
47+
name: 'password',
48+
virtual: true,
49+
required: { create: true },
50+
editingNote: { edit: 'Leave empty to keep password unchanged' },
51+
minLength: 8,
52+
type: AdminForthDataTypes.STRING,
53+
showIn: {
54+
// hide password column - but don't remove whole column it because it has constrains for password field!
55+
// diff-remove
56+
show: false,
57+
// diff-remove
58+
list: false,
59+
// diff-remove
60+
filter: false,
61+
// diff-add
62+
all: false,
63+
},
64+
masked: true,
65+
},
66+
67+
// ... other columns
68+
],
69+
hooks: {
70+
create: {
71+
beforeSave: async ({ record, adminUser, resource }: { record: any, adminUser: AdminUser, resource: AdminForthResource }) => {
72+
// since we don't show password input in resource - no sense to hande it in hook anymore!
73+
//diff-remove
74+
record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);
75+
return { ok: true };
76+
}
77+
},
78+
edit: {
79+
beforeSave: async ({ oldRecord, updates, adminUser, resource }: { oldRecord: any, updates: any, adminUser: AdminUser, resource: AdminForthResource }) => {
80+
console.log('Updating user', updates);
81+
if (oldRecord.id === adminUser.dbUser.id && updates.role) {
82+
return { ok: false, error: 'You cannot change your own role' };
83+
}
84+
// also no sense to have updatres - we dont allow edit password by admin anymore
85+
//diff-remove
86+
if (updates.password) {
87+
//diff-remove
88+
updates.password_hash = await AdminForth.Utils.generatePasswordHash(updates.password);
89+
//diff-remove
90+
}
91+
return { ok: true }
92+
},
93+
},
94+
},
95+
plugins: [
96+
new EmailInvitePlugin({
97+
emailField: 'email',
98+
sendFrom: 'noreply@yourapp.com',
99+
adapter: new EmailAdapterAwsSes({
100+
region: 'us-east-1',
101+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
102+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
103+
}),
104+
}),
105+
],
106+
};
107+
```
108+
109+
Please note that previously (in defauklt CLI setup) we needed it to allow admins to set passwords when created new users (to invite them). Also Admens were able to edit passwords of users.
110+
Now since we added this plugin, user will have email link on which he will get form to enter password by hiumself.
111+
Please note that the form for user will still use constraints from password virtual field, that is why we just hid it using showIn - not remove it.
112+
113+
To allow users to edit their passwords please use [email password reset plugin](https://adminforth.dev/docs/tutorial/Plugins/email-password-reset/)
114+
115+
## Email Confirmation boolean flag
116+
117+
This plugin can write into the database the fact that invited user was able to set password and as a result confirmed that he owns his email.
118+
To enable email this behaviour, first add a boolean field to your user table:
119+
120+
```prisma title="./schema.prisma"
121+
model adminuser {
122+
id String @id @default(cuid())
123+
email String @unique
124+
password_hash String
125+
role String @default("user")
126+
//diff-add
127+
email_confirmed Boolean? @default(false)
128+
// ... other fields
129+
}
130+
```
131+
132+
Run the migration:
133+
134+
```bash
135+
npx prisma migrate dev --name add-email-confirmed
136+
```
137+
138+
Then update your resource configuration:
139+
140+
```typescript title="./resources/adminuser.ts"
141+
export default {
142+
// ... existing config
143+
columns: [
144+
{ name: 'id', primaryKey: true },
145+
{ name: 'email', required: true },
146+
{ name: 'password_hash', showIn: [] },
147+
{ name: 'role' },
148+
//diff-add
149+
{ name: 'email_confirmed', type: AdminForthDataTypes.BOOLEAN },
150+
// ... other columns
151+
],
152+
plugins: [
153+
new EmailInvitePlugin({
154+
emailField: 'email',
155+
sendFrom: 'noreply@yourapp.com',
156+
adapter: new EmailAdapterAwsSes(/* ... */),
157+
//diff-add
158+
emailConfirmedField: 'email_confirmed', // Enable email confirmation
159+
}),
160+
],
161+
};
162+
```
163+

adminforth/documentation/docs/tutorial/07-Plugins/03-ForeignInlineList.md

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,119 @@ Add to your `'adminuser'` resource configuration the plugin instance:
7272
}
7373
```
7474

75-
You can use `modifyTableResourceConfig` callback to modify what columns to show in the list and filter of the foreign table.
75+
You can use the `modifyTableResourceConfig` callback to modify which columns to show in the list and filter of the foreign table.
7676

7777
![alt text](ForeignInlineList.png)
7878

7979
> 👆 To make plugin work, the specified resource (defined with `foreignResourceId`) should have one (and only one) column that refers to the current resource on which you add a plugin.
80-
> In our case we add plugin to `adminuser` resource, so the `aparts` resource should have one column with `foreignResource.resourceId` equal to `adminuser` resourceId.
80+
> In our case we add plugin to `adminuser` resource, so the `aparts` resource should have one column with `foreignResource.resourceId` equal to `adminuser` resourceId.
81+
82+
## Default filters
83+
84+
If you need to add default filters for the foreign resource based on your current record (for example show apartment only from Italy, when user have country Italy), you can use defaultFilters callback:
85+
>👆 This example won't work until you'll add counrty field in your adminuser resource and it's only for demonstrating concept of callback
86+
87+
```ts title="./resources/adminuser.ts"
88+
89+
...
90+
91+
new ForeignInlineListPlugin({
92+
93+
...
94+
//diff-add
95+
defaultFilters: (record: any) => {
96+
//diff-add
97+
return [
98+
//diff-add
99+
{
100+
//diff-add
101+
field: "country",
102+
//diff-add
103+
operator: AdminForthFilterOperators.EQ,
104+
//diff-add
105+
value: record.country,
106+
//diff-add
107+
}
108+
//diff-add
109+
]
110+
//diff-add
111+
}
112+
113+
...
114+
115+
})
116+
117+
...
118+
119+
```
120+
121+
>👆It also makes sense to modify the table resource and hide the country field from filters, because this value is hardcoded and equals the country from the record:
122+
123+
124+
```ts title="./resources/adminuser.ts"
125+
126+
...
127+
128+
new ForeignInlineListPlugin({
129+
130+
...
131+
132+
//diff-add
133+
modifyTableResourceConfig: (resourceConfig: AdminForthResource) => {
134+
//diff-add
135+
const column = resourceConfig.columns.find((c: AdminForthResourceColumn) => c.name === 'country')!.showIn = {
136+
//diff-add
137+
list: true,
138+
//diff-add
139+
show: true,
140+
//diff-add
141+
edit: true,
142+
//diff-add
143+
create: true,
144+
//diff-add
145+
filter: false
146+
//diff-add
147+
};
148+
//diff-add
149+
},
150+
151+
defaultFilters: (record: any) => {
152+
return [
153+
{
154+
field: "country",
155+
operator: AdminForthFilterOperators.EQ,
156+
value: record.country,
157+
}
158+
]
159+
}
160+
161+
...
162+
163+
})
164+
165+
...
166+
167+
```
168+
169+
170+
## Show table from another resource without any filters applied
171+
172+
There might be cases when you want to remove the default filter applied by the plugin and then use the `defaultFilters` callback to apply your own custom filters.
173+
174+
```ts title="./resources/adminuser.ts"
175+
176+
plugins: [
177+
//diff-add
178+
new ForeignInlineListPlugin({
179+
//diff-add
180+
foreignResourceId: 'aparts',
181+
//diff-add
182+
disableForeignListResourceRefColumn: true
183+
//diff-add
184+
}),
185+
//diff-add
186+
],
187+
188+
```
189+
190+
This setup will show, in the show view for each record, the `aparts` resource without any filters. And you don’t have to modify the `aparts` resource.

0 commit comments

Comments
 (0)