adminforth 1.2.98 → 1.2.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/auth.ts +6 -5
  2. package/dataConnectors/baseConnector.ts +91 -21
  3. package/dataConnectors/clickhouse.ts +58 -37
  4. package/dataConnectors/mongo.ts +44 -14
  5. package/dataConnectors/postgres.ts +53 -36
  6. package/dataConnectors/sqlite.ts +44 -35
  7. package/dist/auth.js +6 -6
  8. package/dist/dataConnectors/baseConnector.js +75 -17
  9. package/dist/dataConnectors/clickhouse.js +59 -48
  10. package/dist/dataConnectors/mongo.js +28 -12
  11. package/dist/dataConnectors/postgres.js +62 -52
  12. package/dist/dataConnectors/sqlite.js +62 -45
  13. package/dist/index.js +52 -33
  14. package/dist/modules/configValidator.js +25 -16
  15. package/dist/modules/operationalResource.js +88 -0
  16. package/dist/modules/restApi.js +106 -96
  17. package/dist/modules/utils.js +16 -0
  18. package/dist/types/AdminForthConfig.js +37 -0
  19. package/index.ts +76 -43
  20. package/modules/configValidator.ts +26 -21
  21. package/modules/operationalResource.ts +91 -0
  22. package/modules/restApi.ts +91 -80
  23. package/modules/utils.ts +20 -0
  24. package/package.json +3 -2
  25. package/spa/src/App.vue +12 -9
  26. package/spa/src/components/Filters.vue +1 -1
  27. package/spa/src/components/ResourceForm.vue +7 -4
  28. package/spa/src/components/ResourceListTable.vue +124 -112
  29. package/spa/src/components/SkeleteLoader.vue +4 -4
  30. package/spa/src/components/ValueRenderer.vue +1 -1
  31. package/spa/src/router/index.ts +0 -8
  32. package/spa/src/spa_types/core.ts +1 -0
  33. package/spa/src/stores/filters.ts +3 -2
  34. package/spa/src/views/ListView.vue +16 -25
  35. package/spa/src/views/LoginView.vue +26 -9
  36. package/types/AdminForthConfig.ts +140 -38
@@ -51,16 +51,18 @@ export interface IHttpServer {
51
51
 
52
52
  export type AdminUser = {
53
53
  /**
54
- * primaryKey field value of user in table which is defined by {@link AdminForthConfig.auth.resourceId}
55
- * or null if it is user logged in as {@link AdminForthConfig.rootUser}
54
+ * primaryKey field value of user in table which is defined by {@link AdminForthConfig.auth.usersResourceId}
56
55
  */
57
56
  pk: string | null,
58
57
 
59
58
  /**
60
- * Username which takend from {@link AdminForthConfig.auth.usernameField} field in user resource {@link AdminForthConfig.auth.resourceId}
59
+ * Username which taken from {@link AdminForthConfig.auth.usernameField} field in user resource {@link AdminForthConfig.auth.usersResourceId}
61
60
  */
62
61
  username: string,
63
- isRoot: boolean,
62
+
63
+ /**
64
+ * User record fetched from database, from resource defined in {@link AdminForthConfig.auth.usersResourceId}
65
+ */
64
66
  dbUser: any,
65
67
  }
66
68
 
@@ -90,6 +92,17 @@ export interface IExpressHttpServer extends IHttpServer {
90
92
  authorize(callable: Function): void;
91
93
  }
92
94
 
95
+ export interface IAdminForthFilter {
96
+ field: string;
97
+ operator: AdminForthFilterOperators;
98
+ value: any;
99
+ }
100
+
101
+ export interface IAdminForthSort {
102
+ field: string,
103
+ direction: AdminForthSortDirections
104
+ }
105
+
93
106
  export interface IAdminForthDataSourceConnector {
94
107
 
95
108
  /**
@@ -145,15 +158,21 @@ export interface IAdminForthDataSourceConnector {
145
158
  *
146
159
  * Fields are returned from db "as is" then {@link AdminForthBaseConnector.getData} will transform each field using {@link IAdminForthDataSourceConnector.getFieldValue}
147
160
  */
148
- getDataWithOriginalTypes({ resource, limit, offset, sort, filters, getTotals }: {
161
+ getDataWithOriginalTypes({ resource, limit, offset, sort, filters }: {
149
162
  resource: AdminForthResource,
150
163
  limit: number,
151
164
  offset: number,
152
- sort: { field: string, direction: AdminForthSortDirections }[],
153
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[],
154
- getTotals?: boolean
155
- }): Promise<{data: Array<any>, total: number}>;
165
+ sort: IAdminForthSort[],
166
+ filters: IAdminForthFilter[],
167
+ }): Promise<Array<any>>;
156
168
 
169
+ /**
170
+ * Used to get count of records in database.
171
+ */
172
+ getCount({ resource, filters }: {
173
+ resource: AdminForthResource,
174
+ filters: IAdminForthFilter[],
175
+ }): Promise<number>;
157
176
 
158
177
  /**
159
178
  * Optional method which used to get min and max values for columns in resource.
@@ -181,7 +200,7 @@ export interface IAdminForthDataSourceConnector {
181
200
  /**
182
201
  * Used to delete record in database.
183
202
  */
184
- deleteRecord({ resource, recordId }: { resource: AdminForthResource, recordId: any }): Promise<void>;
203
+ deleteRecord({ resource, recordId }: { resource: AdminForthResource, recordId: any }): Promise<boolean>;
185
204
  }
186
205
 
187
206
 
@@ -196,12 +215,19 @@ export interface IAdminForthDataSourceConnectorBase extends IAdminForthDataSourc
196
215
  resource: AdminForthResource,
197
216
  limit: number,
198
217
  offset: number,
199
- sort: { field: string, direction: AdminForthSortDirections }[],
200
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
218
+ sort: IAdminForthSort[],
219
+ filters: IAdminForthFilter[],
220
+ getTotals?: boolean,
201
221
  }): Promise<{ data: Array<any>, total: number }>;
202
222
 
203
223
  getRecordByPrimaryKey(resource: AdminForthResource, recordId: string): Promise<any>;
204
224
 
225
+ createRecord({ resource, record, adminUser }: {
226
+ resource: AdminForthResource,
227
+ record: any
228
+ adminUser: AdminUser
229
+ }): Promise<{ok: boolean, error?: string, createdRecord?: any}>;
230
+
205
231
  getMinMaxForColumns({ resource, columns }: { resource: AdminForthResource, columns: AdminForthResourceColumn[] }): Promise<{ [key: string]: { min: any, max: any } }>;
206
232
  }
207
233
 
@@ -238,7 +264,9 @@ export interface IAdminForth {
238
264
  [key: string]: IAdminForthDataSourceConnectorBase;
239
265
  };
240
266
 
241
- createResourceRecord(params: { resource: AdminForthResource, record: any, adminUser: AdminUser }): Promise<any>;
267
+ createResourceRecord(
268
+ params: { resource: AdminForthResource, record: any, adminUser: AdminUser }
269
+ ): Promise<{ ok: boolean, error?: string, createdRecord?: any }>;
242
270
 
243
271
  auth: IAdminForthAuth;
244
272
 
@@ -543,6 +571,10 @@ export type AdminForthResourceColumn = {
543
571
  */
544
572
  isUnique?: boolean,
545
573
 
574
+ /**
575
+ * Will automatically convert any capital letters to lowercase in input during editing
576
+ */
577
+ enforceLowerCase?: boolean,
546
578
 
547
579
  /**
548
580
  * Runtime validation Regexp rules for this field.
@@ -664,13 +696,13 @@ export type AfterDataSourceResponseFunction = (params: {resource: AdminForthReso
664
696
  * Modify record to change how data is saved to database.
665
697
  * Return ok: false and error: string to stop execution and show error message to user. Return ok: true to continue execution.
666
698
  */
667
- export type BeforeSaveFunction = (params:{resource: AdminForthResource, adminUser: AdminUser, record: any}) => Promise<{ok: boolean, error?: string}>;
699
+ export type BeforeSaveFunction = (params: {resource: AdminForthResource, recordId: any, adminUser: AdminUser, record: any}) => Promise<{ok: boolean, error?: string}>;
668
700
 
669
701
  /**
670
702
  * Modify record to change how data is saved to database.
671
703
  * Return ok: false and error: string to stop execution and show error message to user. Return ok: true to continue execution.
672
704
  */
673
- export type AfterSaveFunction = (params: {resource: AdminForthResource, adminUser: AdminUser, record: any}) => Promise<{ok: boolean, error?: string}>;
705
+ export type AfterSaveFunction = (params: {resource: AdminForthResource, recordId: any, adminUser: AdminUser, record: any}) => Promise<{ok: boolean, error?: string}>;
674
706
 
675
707
  /**
676
708
  * Allow to get user data before login confirmation, will triger when user try to login.
@@ -724,7 +756,7 @@ export type AdminForthBulkAction = {
724
756
  *
725
757
  * ```ts
726
758
  * allowed: async ({ resource, adminUser, selectedIds }) => {
727
- * if (adminUser.isRoot || adminUser.dbUser.role !== 'superadmin') {
759
+ * if (adminUser.dbUser.role !== 'superadmin') {
728
760
  * return false;
729
761
  * }
730
762
  * return true;
@@ -766,7 +798,7 @@ export type AdminForthBulkAction = {
766
798
  * ],
767
799
  * allowedActions: \{
768
800
  * edit: (\{ resource, adminUser, recordIds \}) => \{
769
- * return adminUser.isRoot || adminUser.dbUser.role === 'superadmin';
801
+ * return adminUser.dbUser.role === 'superadmin';
770
802
  * \}
771
803
  * \}
772
804
  * \}
@@ -959,8 +991,8 @@ export type AdminForthResource = {
959
991
  * ```ts
960
992
  * allowedActions: {
961
993
  * create: ({ resource, adminUser }) => {
962
- * // Allow only superadmin or root user to create records
963
- * return adminUser.isRoot || adminUser.dbUser.role === 'superadmin';
994
+ * // Allow only superadmin to create records
995
+ * return adminUser.dbUser.role === 'superadmin';
964
996
  * },
965
997
  * delete: false, // disable delete action for all users
966
998
  * }
@@ -1065,33 +1097,21 @@ export type AdminForthDataSource = {
1065
1097
  */
1066
1098
  export type AdminForthConfig = {
1067
1099
 
1068
- /**
1069
- * Root user should be used to login to the admin panel first time.
1070
- * Then you should create User for yourself using AdminForth (so it will be persisted in DB),
1071
- * and then disable this option as it is less secure
1072
- */
1073
- rootUser?: {
1074
- /**
1075
- * Username for root user
1076
- */
1077
- username: string,
1078
-
1079
- /**
1080
- * Password for root user
1081
- */
1082
- password: string,
1083
- },
1084
-
1085
1100
  /**
1086
1101
  * Authorization module configuration
1087
1102
  */
1088
1103
  auth?: {
1089
1104
  /**
1090
- * Resource ID for user resource.
1105
+ * Resource ID for resource which stores user table.
1091
1106
  * Resource is a table in database where users will be stored and fetched from. Resources and their ids are defined in resources section of the config.
1092
1107
  * In other words this setting is a reference to a table in database where users will be fetched from on login.
1093
1108
  */
1094
- resourceId: string,
1109
+ usersResourceId?: string,
1110
+
1111
+ /**
1112
+ * Legacy field left for backward compatibility. Use usersResourceId instead.
1113
+ */
1114
+ resourceId?: string,
1095
1115
 
1096
1116
  /**
1097
1117
  * Field name (column name) in user resource which will be used as username for searching user in database during login.
@@ -1116,6 +1136,16 @@ export type AdminForthConfig = {
1116
1136
  */
1117
1137
  loginBackgroundImage?: string,
1118
1138
 
1139
+
1140
+ /**
1141
+ * Position of background image on login page
1142
+ * 'over' - image will be displayed over full login page under login form
1143
+ * '1/2' - image will be displayed on left 1/2 of login page
1144
+ *
1145
+ * Default: '1/2'
1146
+ */
1147
+ loginBackgroundPosition?: 'over' | '1/2' | '1/3' | '2/3' | '3/4' | '2/5' | '3/5',
1148
+
1119
1149
  /**
1120
1150
  * Function or functions which will be called before user try to login.
1121
1151
  * Each function will resive User object as an argument
@@ -1179,6 +1209,13 @@ export type AdminForthConfig = {
1179
1209
  */
1180
1210
  brandName?: string,
1181
1211
 
1212
+
1213
+ /**
1214
+ * Whether to show brand name in sidebar
1215
+ * default is true
1216
+ */
1217
+ showBrandNameInSidebar?: boolean,
1218
+
1182
1219
  /**
1183
1220
  * Path to your app logo
1184
1221
  *
@@ -1302,10 +1339,75 @@ export type AdminForthConfig = {
1302
1339
  baseUrl?: string,
1303
1340
 
1304
1341
 
1342
+ /**
1343
+ * Whether to show delete confirmation dialog before deleting record.
1344
+ * By default it is true.
1345
+ */
1305
1346
  deleteConfirmation?: boolean,
1306
1347
 
1307
1348
 
1308
1349
  }
1350
+
1351
+ // define typescript objects which I can instantiate as Filters.EQ(field, value) and they woudl
1352
+ // return { field: field, operator: 'eq', value: value }. They should be exported with Filters namespace so I can import Filters from this file
1353
+ // and use Filters.EQ(field, value) in my code
1354
+
1355
+ export type FDataFilter = (field: string, value: any) => IAdminForthFilter;
1356
+
1357
+ export class Filters {
1358
+ static EQ(field: string, value: any): IAdminForthFilter {
1359
+ return { field, operator: AdminForthFilterOperators.EQ, value };
1360
+ }
1361
+ static NEQ(field: string, value: any): IAdminForthFilter {
1362
+ return { field, operator: AdminForthFilterOperators.NE, value };
1363
+ }
1364
+ static GT(field: string, value: any): IAdminForthFilter {
1365
+ return { field, operator: AdminForthFilterOperators.GT, value };
1366
+ }
1367
+ static GTE(field: string, value: any): IAdminForthFilter {
1368
+ return { field, operator: AdminForthFilterOperators.GTE, value };
1369
+ }
1370
+ static LT(field: string, value: any): IAdminForthFilter {
1371
+ return { field, operator: AdminForthFilterOperators.LT, value };
1372
+ }
1373
+ static LTE(field: string, value: any): IAdminForthFilter {
1374
+ return { field, operator: AdminForthFilterOperators.LTE, value };
1375
+ }
1376
+ static IN(field: string, value: any): IAdminForthFilter {
1377
+ return { field, operator: AdminForthFilterOperators.IN, value };
1378
+ }
1379
+ static NOT_IN(field: string, value: any): IAdminForthFilter {
1380
+ return { field, operator: AdminForthFilterOperators.NIN, value };
1381
+ }
1382
+ static LIKE(field: string, value: any): IAdminForthFilter {
1383
+ return { field, operator: AdminForthFilterOperators.LIKE, value };
1384
+ }
1385
+ }
1386
+
1387
+ export type FDataSort = (field: string, direction: AdminForthSortDirections) => IAdminForthSort;
1388
+
1389
+ export class Sorts {
1390
+ static ASC(field: string): IAdminForthSort {
1391
+ return { field, direction: AdminForthSortDirections.asc };
1392
+ }
1393
+ static DESC(field: string): IAdminForthSort {
1394
+ return { field, direction: AdminForthSortDirections.desc };
1395
+ }
1396
+ }
1397
+
1398
+ export interface IOperationalResource {
1399
+ get: (filter: IAdminForthFilter | IAdminForthFilter[]) => Promise<any | null>;
1400
+
1401
+ list: (filter: IAdminForthFilter | IAdminForthFilter[], limit: number, offset: number, sort: IAdminForthSort | IAdminForthSort[]) => Promise<any[]>;
1402
+
1403
+ count: (filter: IAdminForthFilter | IAdminForthFilter[]) => Promise<number>;
1404
+
1405
+ create: (record: any) => Promise<{ ok: boolean; createdRecord: any; error?: string; }>;
1406
+
1407
+ update: (primaryKey: any, record: any) => Promise<any>;
1408
+
1409
+ delete: (primaryKey: any) => Promise<boolean>;
1410
+ }
1309
1411
 
1310
1412
 
1311
1413
  export enum AllowedActionsEnum {