@ruiapp/rapid-core 0.9.7 → 0.10.0

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.
@@ -435,6 +435,57 @@ declare const _default: {
435
435
  description?: undefined;
436
436
  })[];
437
437
  indexes?: undefined;
438
+ } | {
439
+ maintainedBy: string;
440
+ namespace: string;
441
+ name: string;
442
+ code: string;
443
+ singularCode: string;
444
+ pluralCode: string;
445
+ schema: string;
446
+ tableName: string;
447
+ properties: ({
448
+ name: string;
449
+ code: string;
450
+ columnName: string;
451
+ type: "integer";
452
+ required: true;
453
+ autoIncrement: true;
454
+ } | {
455
+ name: string;
456
+ code: string;
457
+ columnName: string;
458
+ type: "text";
459
+ required: true;
460
+ autoIncrement?: undefined;
461
+ } | {
462
+ name: string;
463
+ code: string;
464
+ columnName: string;
465
+ type: "text";
466
+ required: false;
467
+ autoIncrement?: undefined;
468
+ } | {
469
+ name: string;
470
+ code: string;
471
+ columnName: string;
472
+ type: "json";
473
+ required: false;
474
+ autoIncrement?: undefined;
475
+ })[];
476
+ indexes: ({
477
+ name: string;
478
+ properties: {
479
+ code: string;
480
+ }[];
481
+ unique: true;
482
+ } | {
483
+ name: string;
484
+ properties: {
485
+ code: string;
486
+ }[];
487
+ unique?: undefined;
488
+ })[];
438
489
  })[];
439
490
  dataDictionaries: any[];
440
491
  routes: {
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export { default as EntityManager } from "./dataAccess/entityManager";
13
13
  export * from "./dataAccess/entityManager";
14
14
  export * from "./utilities/accessControlUtility";
15
15
  export * from "./utilities/entityUtility";
16
+ export * from "./utilities/fsUtility";
16
17
  export * from "./utilities/jwtUtility";
17
18
  export * from "./utilities/timeUtility";
18
19
  export * from "./utilities/passwordUtility";
package/dist/index.js CHANGED
@@ -7,11 +7,11 @@ var events = require('events');
7
7
  var Router = require('koa-tree-router');
8
8
  var qs = require('qs');
9
9
  var dayjs = require('dayjs');
10
+ var fs = require('fs');
11
+ var path = require('path');
10
12
  var jsonwebtoken = require('jsonwebtoken');
11
13
  var crypto = require('crypto');
12
14
  var bcrypt = require('bcryptjs');
13
- var path = require('path');
14
- var fs = require('fs');
15
15
  var uuid = require('uuid');
16
16
  var nodemailer = require('nodemailer');
17
17
  var cron = require('cron');
@@ -22,10 +22,10 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
22
22
  var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
23
23
  var qs__default = /*#__PURE__*/_interopDefaultLegacy(qs);
24
24
  var dayjs__default = /*#__PURE__*/_interopDefaultLegacy(dayjs);
25
+ var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
26
+ var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
25
27
  var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
26
28
  var bcrypt__default = /*#__PURE__*/_interopDefaultLegacy(bcrypt);
27
- var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
28
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
29
29
  var nodemailer__default = /*#__PURE__*/_interopDefaultLegacy(nodemailer);
30
30
 
31
31
  function fixBigIntJSONSerialize() {
@@ -1968,6 +1968,114 @@ var bootstrapApplicationConfig = {
1968
1968
  },
1969
1969
  ],
1970
1970
  },
1971
+ {
1972
+ maintainedBy: "metaManager",
1973
+ namespace: "meta",
1974
+ name: "page",
1975
+ code: "Page",
1976
+ singularCode: "page",
1977
+ pluralCode: "pages",
1978
+ schema: "public",
1979
+ tableName: "meta_pages",
1980
+ properties: [
1981
+ {
1982
+ name: "id",
1983
+ code: "id",
1984
+ columnName: "id",
1985
+ type: "integer",
1986
+ required: true,
1987
+ autoIncrement: true,
1988
+ },
1989
+ {
1990
+ name: "code",
1991
+ code: "code",
1992
+ columnName: "code",
1993
+ type: "text",
1994
+ required: true,
1995
+ },
1996
+ {
1997
+ name: "parentCode",
1998
+ code: "parentCode",
1999
+ columnName: "parent_code",
2000
+ type: "text",
2001
+ required: false,
2002
+ },
2003
+ {
2004
+ name: "subSystem",
2005
+ code: "subSystem",
2006
+ columnName: "sub_system",
2007
+ type: "text",
2008
+ required: false,
2009
+ },
2010
+ {
2011
+ name: "appCode",
2012
+ code: "appCode",
2013
+ columnName: "app_code",
2014
+ type: "text",
2015
+ required: false,
2016
+ },
2017
+ {
2018
+ name: "routePath",
2019
+ code: "routePath",
2020
+ columnName: "route_path",
2021
+ type: "text",
2022
+ required: false,
2023
+ },
2024
+ {
2025
+ name: "name",
2026
+ code: "name",
2027
+ columnName: "name",
2028
+ type: "text",
2029
+ required: false,
2030
+ },
2031
+ {
2032
+ name: "title",
2033
+ code: "title",
2034
+ columnName: "title",
2035
+ type: "text",
2036
+ required: false,
2037
+ },
2038
+ {
2039
+ name: "config",
2040
+ code: "config",
2041
+ columnName: "config",
2042
+ type: "json",
2043
+ required: false,
2044
+ },
2045
+ {
2046
+ name: "permissionCheck",
2047
+ code: "permissionCheck",
2048
+ columnName: "permission_check",
2049
+ type: "json",
2050
+ required: false,
2051
+ },
2052
+ ],
2053
+ indexes: [
2054
+ {
2055
+ name: "meta_pages_code_uindex",
2056
+ properties: [
2057
+ {
2058
+ code: "code",
2059
+ },
2060
+ ],
2061
+ unique: true,
2062
+ },
2063
+ {
2064
+ name: "meta_pages_subsystem_appcode_code_idx",
2065
+ properties: [
2066
+ {
2067
+ code: "subSystem",
2068
+ },
2069
+ {
2070
+ code: "appCode",
2071
+ },
2072
+ {
2073
+ code: "code",
2074
+ },
2075
+ ],
2076
+ },
2077
+ ],
2078
+ },
1971
2079
  ],
1972
2080
  dataDictionaries: [],
1973
2081
  routes: [
@@ -4941,6 +5049,128 @@ function getEntityRelationTargetId(entity, propName, targetColumnName) {
4941
5049
  }
4942
5050
  }
4943
5051
 
5052
+ async function readFile(path) {
5053
+ return new Promise((resolve, reject) => {
5054
+ fs__default["default"].readFile(path, null, (err, data) => {
5055
+ if (err) {
5056
+ reject(err);
5057
+ }
5058
+ else {
5059
+ resolve(data);
5060
+ }
5061
+ });
5062
+ });
5063
+ }
5064
+ async function copyFile(fromPath, toPath) {
5065
+ return new Promise((resolve, reject) => {
5066
+ fs__default["default"].copyFile(fromPath, toPath, (err) => {
5067
+ if (err) {
5068
+ reject(err);
5069
+ }
5070
+ else {
5071
+ resolve();
5072
+ }
5073
+ });
5074
+ });
5075
+ }
5076
+ async function removeFile(path) {
5077
+ return new Promise((resolve, reject) => {
5078
+ fs__default["default"].rm(path, (err) => {
5079
+ if (err) {
5080
+ reject(err);
5081
+ }
5082
+ else {
5083
+ resolve();
5084
+ }
5085
+ });
5086
+ });
5087
+ }
5088
+ async function moveFile(fromPath, toPath) {
5089
+ return new Promise((resolve, reject) => {
5090
+ fs__default["default"].rename(fromPath, toPath, (err) => {
5091
+ if (err) {
5092
+ reject(err);
5093
+ }
5094
+ else {
5095
+ resolve();
5096
+ }
5097
+ });
5098
+ });
5099
+ }
5100
+ async function appendFile(path, data) {
5101
+ return new Promise((resolve, reject) => {
5102
+ fs__default["default"].appendFile(path, Buffer.from(data), (err) => {
5103
+ if (err) {
5104
+ reject(err);
5105
+ }
5106
+ else {
5107
+ resolve();
5108
+ }
5109
+ });
5110
+ });
5111
+ }
5112
+ async function writeFile(path, data) {
5113
+ return new Promise((resolve, reject) => {
5114
+ fs__default["default"].writeFile(path, Buffer.from(data), (err) => {
5115
+ if (err) {
5116
+ reject(err);
5117
+ }
5118
+ else {
5119
+ resolve();
5120
+ }
5121
+ });
5122
+ });
5123
+ }
5124
+ function ensureDirectoryExists(dirPath) {
5125
+ if (!fs__default["default"].existsSync(dirPath)) {
5126
+ const parentDirPath = path__default["default"].dirname(dirPath);
5127
+ if (parentDirPath == dirPath) {
5128
+ return;
5129
+ }
5130
+ ensureDirectoryExists(parentDirPath);
5131
+ fs__default["default"].mkdirSync(dirPath);
5132
+ }
5133
+ }
5134
+ function enumFileBaseNamesInDirectory(options) {
5135
+ const { dirPath, prefix, fileNameFilter } = options;
5136
+ let fileNames = [];
5137
+ let resolvedDirPath = dirPath;
5138
+ const isRelative = dirPath.startsWith(".") || dirPath.startsWith("..");
5139
+ if (isRelative) {
5140
+ resolvedDirPath = path__default["default"].join(process.cwd(), dirPath);
5141
+ }
5142
+ if (!fs__default["default"].existsSync(resolvedDirPath)) {
5143
+ console.warn(`Directory '${resolvedDirPath}' not found.`);
5144
+ return [];
5145
+ }
5146
+ const files = fs__default["default"].readdirSync(resolvedDirPath);
5147
+ for (const fileName of files) {
5148
+ const filePathName = path__default["default"].join(resolvedDirPath, fileName);
5149
+ const fileStat = fs__default["default"].statSync(filePathName);
5150
+ if (fileStat.isDirectory()) {
5151
+ fileNames = fileNames.concat(enumFileBaseNamesInDirectory({
5152
+ dirPath: filePathName,
5153
+ prefix: prefix ? `${prefix}/${fileName}` : fileName,
5154
+ fileNameFilter,
5155
+ }));
5156
+ }
5157
+ else if (fileStat.isFile()) {
5158
+ if (fileNameFilter && !fileNameFilter(fileName)) {
5159
+ continue;
5160
+ }
5161
+ const baseName = path__default["default"].parse(fileName).name;
5162
+ if (prefix) {
5163
+ fileNames.push(`${prefix}/${baseName}`);
5164
+ }
5165
+ else {
5166
+ fileNames.push(baseName);
5167
+ }
5168
+ }
5169
+ }
5170
+ fileNames.sort();
5171
+ return fileNames;
5172
+ }
5173
+
4944
5174
  // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
4945
5175
  // This module is browser compatible.
4946
5176
  /**
@@ -5460,7 +5690,7 @@ class MetaService {
5460
5690
  const tablesInDb = await server.queryDatabaseObject(sqlQueryTableInformations);
5461
5691
  const { queryBuilder } = server;
5462
5692
  for (const model of applicationConfig.models) {
5463
- logger.debug(`Checking data table for '${model.namespace}.${model.singularCode}'...`);
5693
+ logger.info(`Checking data table for '${model.namespace}.${model.singularCode}'...`);
5464
5694
  const expectedTableSchema = model.schema || server.databaseConfig.dbDefaultSchema;
5465
5695
  const expectedTableName = model.tableName;
5466
5696
  const tableInDb = lodash.find(tablesInDb, { table_schema: expectedTableSchema, table_name: expectedTableName });
@@ -5477,7 +5707,7 @@ class MetaService {
5477
5707
  LEFT JOIN pg_catalog.pg_description d ON (d.objoid = st.relid and d.objsubid = c.ordinal_position);`;
5478
5708
  const columnsInDb = await server.queryDatabaseObject(sqlQueryColumnInformations, []);
5479
5709
  for (const model of applicationConfig.models) {
5480
- logger.debug(`Checking data columns for '${model.namespace}.${model.singularCode}'...`);
5710
+ logger.info(`Checking data columns for '${model.namespace}.${model.singularCode}'...`);
5481
5711
  for (const property of model.properties) {
5482
5712
  let columnDDL = "";
5483
5713
  if (isRelationProperty(property)) {
@@ -5618,7 +5848,7 @@ class MetaService {
5618
5848
  const expectedTableSchema = model.schema || server.databaseConfig.dbDefaultSchema;
5619
5849
  const expectedTableName = model.tableName;
5620
5850
  const expectedContraintName = `${expectedTableName}_pk`;
5621
- logger.debug(`Checking pk for '${expectedTableSchema}.${expectedTableName}'...`);
5851
+ logger.info(`Checking pk for '${expectedTableSchema}.${expectedTableName}'...`);
5622
5852
  const constraintInDb = lodash.find(constraintsInDb, {
5623
5853
  table_schema: expectedTableSchema,
5624
5854
  table_name: expectedTableName,
@@ -5634,7 +5864,7 @@ class MetaService {
5634
5864
  if (!model.indexes || !model.indexes.length) {
5635
5865
  continue;
5636
5866
  }
5637
- logger.debug(`Creating indexes of table ${queryBuilder.quoteTable(model)}`);
5867
+ logger.info(`Creating indexes of table ${queryBuilder.quoteTable(model)}`);
5638
5868
  for (const index of model.indexes) {
5639
5869
  const sqlCreateIndex = generateTableIndexDDL(queryBuilder, server, model, index);
5640
5870
  try {
@@ -7094,19 +7324,8 @@ async function handler$c(plugin, ctx, options) {
7094
7324
  };
7095
7325
  return;
7096
7326
  }
7097
- const userEntitySingularCode = plugin.options?.userEntitySingularCode || "oc_user";
7098
- const profilePropertyCodes = plugin.options?.profilePropertyCodes || ["id", "name", "login", "email", "department", "roles", "state", "createdAt"];
7099
- const entityManager = server.getEntityManager(userEntitySingularCode);
7100
- const user = await entityManager.findEntity({
7101
- filters: [
7102
- {
7103
- operator: "eq",
7104
- field: "id",
7105
- value: userId,
7106
- },
7107
- ],
7108
- properties: profilePropertyCodes,
7109
- });
7327
+ const authService = server.getService("authService");
7328
+ const user = await authService.getProfileOfUser(userId);
7110
7329
  ctx.output = {
7111
7330
  user,
7112
7331
  };
@@ -7285,9 +7504,13 @@ var pluginRoutes$7 = [changePassword, getMyProfile$1, resetPassword, signin$1, s
7285
7504
  class AuthService {
7286
7505
  #server;
7287
7506
  #jwtKey;
7288
- constructor(server, jwtKey) {
7507
+ #userEntitySingularCode;
7508
+ #profilePropertyCodes;
7509
+ constructor(server, options) {
7289
7510
  this.#server = server;
7290
- this.#jwtKey = jwtKey;
7511
+ this.#jwtKey = options.jwtKey;
7512
+ this.#userEntitySingularCode = options.userEntitySingularCode;
7513
+ this.#profilePropertyCodes = options.profilePropertyCodes;
7291
7514
  }
7292
7515
  createUserAccessToken(options) {
7293
7516
  const secretKey = Buffer.from(this.#jwtKey, "base64");
@@ -7300,6 +7523,22 @@ class AuthService {
7300
7523
  }, secretKey);
7301
7524
  return token;
7302
7525
  }
7526
+ async getProfileOfUser(userId) {
7527
+ const userEntitySingularCode = this.#userEntitySingularCode || "oc_user";
7528
+ const profilePropertyCodes = this.#profilePropertyCodes || ["id", "name", "login", "email", "department", "roles", "state", "createdAt"];
7529
+ const entityManager = this.#server.getEntityManager(userEntitySingularCode);
7530
+ const user = await entityManager.findEntity({
7531
+ filters: [
7532
+ {
7533
+ operator: "eq",
7534
+ field: "id",
7535
+ value: userId,
7536
+ },
7537
+ ],
7538
+ properties: profilePropertyCodes,
7539
+ });
7540
+ return user;
7541
+ }
7303
7542
  }
7304
7543
 
7305
7544
  /**
@@ -7338,7 +7577,11 @@ class AuthPlugin {
7338
7577
  server.appendApplicationConfig({ models: pluginModels$6 });
7339
7578
  }
7340
7579
  async configureServices(server, applicationConfig) {
7341
- this.#authService = new AuthService(server, server.config.jwtKey);
7580
+ this.#authService = new AuthService(server, {
7581
+ jwtKey: server.config.jwtKey,
7582
+ userEntitySingularCode: this.#options.userEntitySingularCode,
7583
+ profilePropertyCodes: this.#options.profilePropertyCodes,
7584
+ });
7342
7585
  server.registerService("authService", this.#authService);
7343
7586
  }
7344
7587
  async configureRoutes(server, applicationConfig) {
@@ -7373,31 +7616,6 @@ class AuthPlugin {
7373
7616
  }
7374
7617
  }
7375
7618
 
7376
- async function readFile(path) {
7377
- return new Promise((resolve, reject) => {
7378
- fs__default["default"].readFile(path, null, (err, data) => {
7379
- if (err) {
7380
- reject(err);
7381
- }
7382
- else {
7383
- resolve(data);
7384
- }
7385
- });
7386
- });
7387
- }
7388
- async function appendFile(path, data) {
7389
- return new Promise((resolve, reject) => {
7390
- fs__default["default"].appendFile(path, Buffer.from(data), (err) => {
7391
- if (err) {
7392
- reject(err);
7393
- }
7394
- else {
7395
- resolve();
7396
- }
7397
- });
7398
- });
7399
- }
7400
-
7401
7619
  function getFileBaseName(pathname) {
7402
7620
  const extName = path__default["default"].extname(pathname);
7403
7621
  return path__default["default"].basename(pathname, extName);
@@ -7511,7 +7729,7 @@ async function handler$8(plugin, ctx, options) {
7511
7729
  const fileKey = `${uuid.v1()}${extName}`;
7512
7730
  const filePathName = path__default["default"].join(server.config.localFileStoragePath, fileKey);
7513
7731
  const fileBuffer = await file.arrayBuffer();
7514
- await appendFile(filePathName, fileBuffer);
7732
+ await writeFile(filePathName, fileBuffer);
7515
7733
  ctx.output = { ok: true, fileKey };
7516
7734
  }
7517
7735
 
@@ -9706,12 +9924,16 @@ exports.ServerOperationPlugin = ServerOperationPlugin;
9706
9924
  exports.SettingPlugin = SettingPlugin;
9707
9925
  exports.StateMachinePlugin = StateMachinePlugin;
9708
9926
  exports.WebhooksPlugin = WebhooksPlugin;
9927
+ exports.appendFile = appendFile;
9709
9928
  exports.bootstrapApplicationConfig = bootstrapApplicationConfig$1;
9929
+ exports.copyFile = copyFile;
9710
9930
  exports.createJwt = createJwt;
9711
9931
  exports.decodeJwt = decodeJwt;
9712
9932
  exports.deleteCookie = deleteCookie;
9713
9933
  exports.detectChangedFieldsOfEntity = detectChangedFieldsOfEntity;
9934
+ exports.ensureDirectoryExists = ensureDirectoryExists;
9714
9935
  exports.entityHelper = entityHelper;
9936
+ exports.enumFileBaseNamesInDirectory = enumFileBaseNamesInDirectory;
9715
9937
  exports.formatDateTimeWithTimezone = formatDateTimeWithTimezone;
9716
9938
  exports.generateJwtSecretKey = generateJwtSecretKey;
9717
9939
  exports.generatePasswordHash = generatePasswordHash;
@@ -9725,8 +9947,12 @@ exports.isAccessAllowed = isAccessAllowed;
9725
9947
  exports.licenseHelper = licenseHelper;
9726
9948
  exports.mapDbRowToEntity = mapDbRowToEntity;
9727
9949
  exports.metaHelper = metaHelper;
9950
+ exports.moveFile = moveFile;
9951
+ exports.readFile = readFile;
9952
+ exports.removeFile = removeFile;
9728
9953
  exports.setCookie = setCookie;
9729
9954
  exports.tryValidateLicense = tryValidateLicense;
9730
9955
  exports.validateLicense = validateLicense;
9731
9956
  exports.validatePassword = validatePassword;
9732
9957
  exports.verifyJwt = verifyJwt;
9958
+ exports.writeFile = writeFile;
@@ -1,4 +1,9 @@
1
1
  import { IRpdServer } from "../../../core/server";
2
+ export type AuthServiceOptions = {
3
+ jwtKey: string;
4
+ userEntitySingularCode?: string;
5
+ profilePropertyCodes?: string[];
6
+ };
2
7
  export interface UserAccessToken {
3
8
  sub: "userAccessToken";
4
9
  aud: string;
@@ -10,6 +15,7 @@ export interface CreateUserAccessTokenOptions {
10
15
  }
11
16
  export default class AuthService {
12
17
  #private;
13
- constructor(server: IRpdServer, jwtKey: string);
18
+ constructor(server: IRpdServer, options: AuthServiceOptions);
14
19
  createUserAccessToken(options: CreateUserAccessTokenOptions): string;
20
+ getProfileOfUser(userId: number): Promise<any>;
15
21
  }
@@ -4,3 +4,11 @@ export declare function copyFile(fromPath: string, toPath: string): Promise<void
4
4
  export declare function removeFile(path: string): Promise<void>;
5
5
  export declare function moveFile(fromPath: string, toPath: string): Promise<void>;
6
6
  export declare function appendFile(path: string, data: ArrayBuffer): Promise<void>;
7
+ export declare function writeFile(path: string, data: ArrayBuffer): Promise<void>;
8
+ export declare function ensureDirectoryExists(dirPath: string): void;
9
+ export type EnumFileBaseNamesOptions = {
10
+ dirPath: string;
11
+ prefix?: string;
12
+ fileNameFilter?: (fileName: string) => boolean;
13
+ };
14
+ export declare function enumFileBaseNamesInDirectory(options: EnumFileBaseNamesOptions): string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.9.7",
3
+ "version": "0.10.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -736,6 +736,114 @@ export default {
736
736
  },
737
737
  ],
738
738
  },
739
+ {
740
+ maintainedBy: "metaManager",
741
+ namespace: "meta",
742
+ name: "page",
743
+ code: "Page",
744
+ singularCode: "page",
745
+ pluralCode: "pages",
746
+ schema: "public",
747
+ tableName: "meta_pages",
748
+ properties: [
749
+ {
750
+ name: "id",
751
+ code: "id",
752
+ columnName: "id",
753
+ type: "integer",
754
+ required: true,
755
+ autoIncrement: true,
756
+ },
757
+ {
758
+ name: "code",
759
+ code: "code",
760
+ columnName: "code",
761
+ type: "text",
762
+ required: true,
763
+ },
764
+ {
765
+ name: "parentCode",
766
+ code: "parentCode",
767
+ columnName: "parent_code",
768
+ type: "text",
769
+ required: false,
770
+ },
771
+ {
772
+ name: "subSystem",
773
+ code: "subSystem",
774
+ columnName: "sub_system",
775
+ type: "text",
776
+ required: false,
777
+ },
778
+ {
779
+ name: "appCode",
780
+ code: "appCode",
781
+ columnName: "app_code",
782
+ type: "text",
783
+ required: false,
784
+ },
785
+ {
786
+ name: "routePath",
787
+ code: "routePath",
788
+ columnName: "route_path",
789
+ type: "text",
790
+ required: false,
791
+ },
792
+ {
793
+ name: "name",
794
+ code: "name",
795
+ columnName: "name",
796
+ type: "text",
797
+ required: false,
798
+ },
799
+ {
800
+ name: "title",
801
+ code: "title",
802
+ columnName: "title",
803
+ type: "text",
804
+ required: false,
805
+ },
806
+ {
807
+ name: "config",
808
+ code: "config",
809
+ columnName: "config",
810
+ type: "json",
811
+ required: false,
812
+ },
813
+ {
814
+ name: "permissionCheck",
815
+ code: "permissionCheck",
816
+ columnName: "permission_check",
817
+ type: "json",
818
+ required: false,
819
+ },
820
+ ],
821
+ indexes: [
822
+ {
823
+ name: "meta_pages_code_uindex",
824
+ properties: [
825
+ {
826
+ code: "code",
827
+ },
828
+ ],
829
+ unique: true,
830
+ },
831
+ {
832
+ name: "meta_pages_subsystem_appcode_code_idx",
833
+ properties: [
834
+ {
835
+ code: "subSystem",
836
+ },
837
+ {
838
+ code: "appCode",
839
+ },
840
+ {
841
+ code: "code",
842
+ },
843
+ ],
844
+ },
845
+ ],
846
+ },
739
847
  ],
740
848
  dataDictionaries: [],
741
849
  routes: [
package/src/index.ts CHANGED
@@ -20,6 +20,7 @@ export * from "./dataAccess/entityManager";
20
20
 
21
21
  export * from "./utilities/accessControlUtility";
22
22
  export * from "./utilities/entityUtility";
23
+ export * from "./utilities/fsUtility";
23
24
  export * from "./utilities/jwtUtility";
24
25
  export * from "./utilities/timeUtility";
25
26
  export * from "./utilities/passwordUtility";
@@ -62,7 +62,11 @@ class AuthPlugin implements RapidPlugin {
62
62
  }
63
63
 
64
64
  async configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
65
- this.#authService = new AuthService(server, server.config.jwtKey);
65
+ this.#authService = new AuthService(server, {
66
+ jwtKey: server.config.jwtKey,
67
+ userEntitySingularCode: this.#options.userEntitySingularCode,
68
+ profilePropertyCodes: this.#options.profilePropertyCodes,
69
+ });
66
70
  server.registerService("authService", this.#authService);
67
71
  }
68
72
 
@@ -1,6 +1,7 @@
1
1
  import { ActionHandlerContext } from "~/core/actionHandler";
2
2
  import { RapidPlugin } from "~/core/server";
3
3
  import AuthPlugin from "../AuthPlugin";
4
+ import AuthService from "../services/AuthService";
4
5
 
5
6
  export const code = "getMyProfile";
6
7
 
@@ -18,19 +19,8 @@ export async function handler(plugin: AuthPlugin, ctx: ActionHandlerContext, opt
18
19
  return;
19
20
  }
20
21
 
21
- const userEntitySingularCode = plugin.options?.userEntitySingularCode || "oc_user";
22
- const profilePropertyCodes = plugin.options?.profilePropertyCodes || ["id", "name", "login", "email", "department", "roles", "state", "createdAt"];
23
- const entityManager = server.getEntityManager(userEntitySingularCode);
24
- const user = await entityManager.findEntity({
25
- filters: [
26
- {
27
- operator: "eq",
28
- field: "id",
29
- value: userId,
30
- },
31
- ],
32
- properties: profilePropertyCodes,
33
- });
22
+ const authService = server.getService<AuthService>("authService");
23
+ const user = await authService.getProfileOfUser(userId);
34
24
 
35
25
  ctx.output = {
36
26
  user,
@@ -1,6 +1,12 @@
1
1
  import { IRpdServer } from "~/core/server";
2
2
  import { createJwt } from "~/utilities/jwtUtility";
3
3
 
4
+ export type AuthServiceOptions = {
5
+ jwtKey: string;
6
+ userEntitySingularCode?: string;
7
+ profilePropertyCodes?: string[];
8
+ };
9
+
4
10
  export interface UserAccessToken {
5
11
  sub: "userAccessToken";
6
12
  aud: string;
@@ -15,10 +21,14 @@ export interface CreateUserAccessTokenOptions {
15
21
  export default class AuthService {
16
22
  #server: IRpdServer;
17
23
  #jwtKey: string;
24
+ #userEntitySingularCode?: string;
25
+ #profilePropertyCodes?: string[];
18
26
 
19
- constructor(server: IRpdServer, jwtKey: string) {
27
+ constructor(server: IRpdServer, options: AuthServiceOptions) {
20
28
  this.#server = server;
21
- this.#jwtKey = jwtKey;
29
+ this.#jwtKey = options.jwtKey;
30
+ this.#userEntitySingularCode = options.userEntitySingularCode;
31
+ this.#profilePropertyCodes = options.profilePropertyCodes;
22
32
  }
23
33
 
24
34
  createUserAccessToken(options: CreateUserAccessTokenOptions): string {
@@ -36,4 +46,21 @@ export default class AuthService {
36
46
 
37
47
  return token;
38
48
  }
49
+
50
+ async getProfileOfUser(userId: number) {
51
+ const userEntitySingularCode = this.#userEntitySingularCode || "oc_user";
52
+ const profilePropertyCodes = this.#profilePropertyCodes || ["id", "name", "login", "email", "department", "roles", "state", "createdAt"];
53
+ const entityManager = this.#server.getEntityManager(userEntitySingularCode);
54
+ const user = await entityManager.findEntity({
55
+ filters: [
56
+ {
57
+ operator: "eq",
58
+ field: "id",
59
+ value: userId,
60
+ },
61
+ ],
62
+ properties: profilePropertyCodes,
63
+ });
64
+ return user;
65
+ }
39
66
  }
@@ -1,5 +1,5 @@
1
1
  import { v1 as uuidv1 } from "uuid";
2
- import { appendFile } from "~/utilities/fsUtility";
2
+ import { writeFile } from "~/utilities/fsUtility";
3
3
  import { ActionHandlerContext } from "~/core/actionHandler";
4
4
  import path from "path";
5
5
  import { isArray } from "lodash";
@@ -27,7 +27,7 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
27
27
  const filePathName = path.join(server.config.localFileStoragePath, fileKey);
28
28
 
29
29
  const fileBuffer = await file.arrayBuffer();
30
- await appendFile(filePathName, fileBuffer);
30
+ await writeFile(filePathName, fileBuffer);
31
31
 
32
32
  ctx.output = { ok: true, fileKey };
33
33
  }
@@ -156,7 +156,7 @@ export default class MetaService {
156
156
  const { queryBuilder } = server;
157
157
 
158
158
  for (const model of applicationConfig.models) {
159
- logger.debug(`Checking data table for '${model.namespace}.${model.singularCode}'...`);
159
+ logger.info(`Checking data table for '${model.namespace}.${model.singularCode}'...`);
160
160
 
161
161
  const expectedTableSchema = model.schema || server.databaseConfig.dbDefaultSchema;
162
162
  const expectedTableName = model.tableName;
@@ -176,7 +176,7 @@ export default class MetaService {
176
176
  const columnsInDb: ColumnInformation[] = await server.queryDatabaseObject(sqlQueryColumnInformations, []);
177
177
 
178
178
  for (const model of applicationConfig.models) {
179
- logger.debug(`Checking data columns for '${model.namespace}.${model.singularCode}'...`);
179
+ logger.info(`Checking data columns for '${model.namespace}.${model.singularCode}'...`);
180
180
 
181
181
  for (const property of model.properties) {
182
182
  let columnDDL = "";
@@ -336,7 +336,7 @@ export default class MetaService {
336
336
  const expectedTableSchema = model.schema || server.databaseConfig.dbDefaultSchema;
337
337
  const expectedTableName = model.tableName;
338
338
  const expectedContraintName = `${expectedTableName}_pk`;
339
- logger.debug(`Checking pk for '${expectedTableSchema}.${expectedTableName}'...`);
339
+ logger.info(`Checking pk for '${expectedTableSchema}.${expectedTableName}'...`);
340
340
  const constraintInDb = find(constraintsInDb, {
341
341
  table_schema: expectedTableSchema,
342
342
  table_name: expectedTableName,
@@ -357,7 +357,7 @@ export default class MetaService {
357
357
  continue;
358
358
  }
359
359
 
360
- logger.debug(`Creating indexes of table ${queryBuilder.quoteTable(model)}`);
360
+ logger.info(`Creating indexes of table ${queryBuilder.quoteTable(model)}`);
361
361
  for (const index of model.indexes) {
362
362
  const sqlCreateIndex = generateTableIndexDDL(queryBuilder, server, model, index);
363
363
  try {
@@ -1,4 +1,5 @@
1
1
  import fs from "fs";
2
+ import path from "path";
2
3
 
3
4
  export async function readFile(path: string): Promise<Buffer> {
4
5
  return new Promise((resolve, reject) => {
@@ -59,3 +60,78 @@ export async function appendFile(path: string, data: ArrayBuffer): Promise<void>
59
60
  });
60
61
  });
61
62
  }
63
+
64
+ export async function writeFile(path: string, data: ArrayBuffer): Promise<void> {
65
+ return new Promise((resolve, reject) => {
66
+ fs.writeFile(path, Buffer.from(data), (err) => {
67
+ if (err) {
68
+ reject(err);
69
+ } else {
70
+ resolve();
71
+ }
72
+ });
73
+ });
74
+ }
75
+
76
+ export function ensureDirectoryExists(dirPath: string) {
77
+ if (!fs.existsSync(dirPath)) {
78
+ const parentDirPath = path.dirname(dirPath);
79
+ if (parentDirPath == dirPath) {
80
+ return;
81
+ }
82
+ ensureDirectoryExists(parentDirPath);
83
+
84
+ fs.mkdirSync(dirPath);
85
+ }
86
+ }
87
+
88
+ export type EnumFileBaseNamesOptions = {
89
+ dirPath: string;
90
+ prefix?: string;
91
+ fileNameFilter?: (fileName: string) => boolean;
92
+ };
93
+
94
+ export function enumFileBaseNamesInDirectory(options: EnumFileBaseNamesOptions): string[] {
95
+ const { dirPath, prefix, fileNameFilter } = options;
96
+ let fileNames = [];
97
+
98
+ let resolvedDirPath = dirPath;
99
+ const isRelative = dirPath.startsWith(".") || dirPath.startsWith("..");
100
+ if (isRelative) {
101
+ resolvedDirPath = path.join(process.cwd(), dirPath);
102
+ }
103
+
104
+ if (!fs.existsSync(resolvedDirPath)) {
105
+ console.warn(`Directory '${resolvedDirPath}' not found.`);
106
+ return [];
107
+ }
108
+
109
+ const files = fs.readdirSync(resolvedDirPath);
110
+ for (const fileName of files) {
111
+ const filePathName = path.join(resolvedDirPath, fileName);
112
+ const fileStat = fs.statSync(filePathName);
113
+ if (fileStat.isDirectory()) {
114
+ fileNames = fileNames.concat(
115
+ enumFileBaseNamesInDirectory({
116
+ dirPath: filePathName,
117
+ prefix: prefix ? `${prefix}/${fileName}` : fileName,
118
+ fileNameFilter,
119
+ }),
120
+ );
121
+ } else if (fileStat.isFile()) {
122
+ if (fileNameFilter && !fileNameFilter(fileName)) {
123
+ continue;
124
+ }
125
+
126
+ const baseName = path.parse(fileName).name;
127
+ if (prefix) {
128
+ fileNames.push(`${prefix}/${baseName}`);
129
+ } else {
130
+ fileNames.push(baseName);
131
+ }
132
+ }
133
+ }
134
+
135
+ fileNames.sort();
136
+ return fileNames;
137
+ }