midway-fatcms 0.0.1-beta.41 → 0.0.1-beta.44

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.
@@ -35,11 +35,7 @@ exports.default = (appInfo) => {
35
35
  jsonLimit: '10mb',
36
36
  textLimit: '10mb',
37
37
  xmlLimit: '10mb',
38
- ignore: [
39
- '/ns/gw/proxy/*',
40
- '/ns/gw/file/uploadFile',
41
- '/ns/api/manage/deploy/uploadAssets',
42
- ], // 忽略代理路径的 body 解析
38
+ ignore: ['/ns/gw/proxy/*', '/ns/gw/file/uploadFile', '/ns/api/manage/deploy/uploadAssets'], // 忽略代理路径的 body 解析
43
39
  },
44
40
  mysql2: {
45
41
  fatcms: {
@@ -115,34 +111,7 @@ exports.default = (appInfo) => {
115
111
  fileSize: '20mb',
116
112
  limit: '20mb',
117
113
  // whitelist: string[],文件扩展名白名单
118
- whitelist: [
119
- '.jpg',
120
- '.jpeg',
121
- '.png',
122
- '.gif',
123
- '.pdf',
124
- '.zip',
125
- '.xlsx',
126
- '.docx',
127
- '.pptx',
128
- '.txt',
129
- '.md',
130
- '.json',
131
- '.js',
132
- '.cjs',
133
- '.ejs',
134
- '.jsx',
135
- '.css',
136
- '.java',
137
- '.ts',
138
- '.tsx',
139
- '.less',
140
- '.scss',
141
- '.html',
142
- '.ttf',
143
- '.map',
144
- '.svg',
145
- ],
114
+ whitelist: ['.jpg', '.jpeg', '.png', '.gif', '.pdf', '.zip', '.xlsx', '.docx', '.pptx', '.txt', '.md', '.json', '.js', '.cjs', '.ejs', '.jsx', '.css', '.java', '.ts', '.tsx', '.less', '.scss', '.html', '.ttf', '.map', '.svg'],
146
115
  // tmpdir: string,上传的文件临时存储路径
147
116
  tmpdir: (0, path_1.join)((0, os_1.tmpdir)(), 'fatcms-upload-files'),
148
117
  // cleanTimeout: number,上传的文件在临时目录中多久之后自动删除,默认为 5 分钟
@@ -186,6 +155,6 @@ exports.default = (appInfo) => {
186
155
  // Excel导出文件的临时目录
187
156
  fatcmsExportExcelTmpFilePath: (0, path_1.join)((0, os_1.tmpdir)(), 'fatcms-export-excel'),
188
157
  // 在某些场景下,只有一个workbench code。如果启用了此配置,则不再根据域名配置识别Workbench.
189
- fatcmsTargetWorkbenchCode: null
158
+ fatcmsTargetWorkbenchCode: null,
190
159
  };
191
160
  };
@@ -20,7 +20,7 @@ const view = require("@midwayjs/view-ejs");
20
20
  const redis = require("@midwayjs/redis");
21
21
  const crossDomain = require("@midwayjs/cross-domain");
22
22
  const _ = require("lodash");
23
- const path_1 = require("path");
23
+ const node_path_1 = require("node:path");
24
24
  // import { DefaultErrorFilter } from './filter/default.filter';
25
25
  // import { NotFoundFilter } from './filter/notfound.filter';
26
26
  const global_middleware_1 = require("./middleware/global.middleware");
@@ -107,7 +107,7 @@ ContainerLifeCycle = __decorate([
107
107
  component: info,
108
108
  },
109
109
  ],
110
- importConfigs: [(0, path_1.join)(__dirname, './config')],
110
+ importConfigs: [(0, node_path_1.join)(__dirname, './config')],
111
111
  })
112
112
  ], ContainerLifeCycle);
113
113
  exports.ContainerLifeCycle = ContainerLifeCycle;
@@ -28,7 +28,7 @@ function checkAccountCreateBlacklist(value) {
28
28
  throw new exceptions_1.CommonException(exceptions_1.Exceptions.VALIDATE_EXCEPTION, '用户名或昵称不能使用具有管理员歧义的词语');
29
29
  }
30
30
  }
31
- const LOGIN_NAME_VALIDATE = [keys_1.KeysOfValidators.STRING, keys_1.KeysOfValidators.NAME, 'length:6,50', checkAccountCreateBlacklist];
31
+ const LOGIN_NAME_VALIDATE = [keys_1.KeysOfValidators.STRING, keys_1.KeysOfValidators.NAME, 'length:5,50', checkAccountCreateBlacklist];
32
32
  let UserAccountManageApi = class UserAccountManageApi extends BaseApiController_1.BaseApiController {
33
33
  async getUserAccountList() {
34
34
  return this.executeSysSimpleSQL(SystemTables_1.SystemTables.sys_user_account, keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE, {
package/dist/index.d.ts CHANGED
@@ -41,6 +41,7 @@ export * from './middleware/forbidden.middleware';
41
41
  export * from './middleware/global.middleware';
42
42
  export * from './middleware/tx.middleware';
43
43
  export * from './middleware/permission.middleware';
44
+ export * from './middleware/redislock.middleware';
44
45
  export * from './service/AuthService';
45
46
  export * from './service/EnumInfoService';
46
47
  export * from './service/FileCenterService';
package/dist/index.js CHANGED
@@ -59,6 +59,7 @@ __exportStar(require("./middleware/forbidden.middleware"), exports);
59
59
  __exportStar(require("./middleware/global.middleware"), exports);
60
60
  __exportStar(require("./middleware/tx.middleware"), exports);
61
61
  __exportStar(require("./middleware/permission.middleware"), exports);
62
+ __exportStar(require("./middleware/redislock.middleware"), exports);
62
63
  __exportStar(require("./service/AuthService"), exports);
63
64
  __exportStar(require("./service/EnumInfoService"), exports);
64
65
  __exportStar(require("./service/FileCenterService"), exports);
@@ -34,6 +34,10 @@ interface IGlobalStaticConfig {
34
34
  toFatcmsUserAccountId(bizTableUserId: any): string;
35
35
  SystemDbName: string;
36
36
  SystemDbType: SqlDbType;
37
+ /**
38
+ * Excel导出时,每页查询的最大数量
39
+ */
40
+ maxPageSizeOfExportExcel: number;
37
41
  }
38
42
  declare class GlobalStaticConfig {
39
43
  private configObject;
@@ -17,6 +17,7 @@ class GlobalStaticConfig {
17
17
  },
18
18
  SystemDbName: 'fatcms',
19
19
  SystemDbType: keys_1.SqlDbType.mysql,
20
+ maxPageSizeOfExportExcel: 1000
20
21
  };
21
22
  }
22
23
  getConfig() {
@@ -20,7 +20,7 @@ let ForbiddenMiddleware = class ForbiddenMiddleware {
20
20
  if (path === '/') {
21
21
  return false;
22
22
  }
23
- if (path.startsWith('/ns/')) {
23
+ if (path.startsWith('/ns/') || path.startsWith('/pages/')) {
24
24
  return false;
25
25
  }
26
26
  for (let i = 0; i < blackEqualList.length; i++) {
@@ -35,7 +35,7 @@ let ForbiddenMiddleware = class ForbiddenMiddleware {
35
35
  return true;
36
36
  }
37
37
  }
38
- return !!(path.includes('/wp-includes/') || path.endsWith('.php') || path.endsWith('/.git/config'));
38
+ return !!(path.includes('/wp-includes/') || path.includes('/wp-admin/') || path.includes('/wp-content/') || path.endsWith('.php') || path.endsWith('/.git/config'));
39
39
  }
40
40
  resolve() {
41
41
  return async (ctx, next) => {
@@ -0,0 +1,3 @@
1
+ import { NextFunction, Context } from '@midwayjs/koa';
2
+ declare function redisCache(cacheKeyConfigList: string[], cacheTimeSecond: number): (ctx: Context, next: NextFunction) => Promise<any>;
3
+ export { redisCache };
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.redisCache = void 0;
4
+ const redis_1 = require("@midwayjs/redis");
5
+ const _ = require("lodash");
6
+ const md5 = require("md5");
7
+ const RedisKeys_1 = require("../models/RedisKeys");
8
+ const exceptions_1 = require("../libs/crud-pro/exceptions");
9
+ const getRedisService = async (ctx) => {
10
+ const service = await ctx.requestContext.getAsync(redis_1.RedisService);
11
+ if (!service) {
12
+ return await ctx.requestContext.getAsync('redisService');
13
+ }
14
+ };
15
+ const createError = () => {
16
+ return new exceptions_1.CommonException('redis_cache_middleware_error_config', 'redisCache中间件的第一个参数必须是一个字符串数组, 并且以“query.”或“body.”开头');
17
+ };
18
+ const checkCacheKeyConfigList = (cacheKeyConfigList) => {
19
+ if (!Array.isArray(cacheKeyConfigList)) {
20
+ throw createError();
21
+ }
22
+ for (let i = 0; i < cacheKeyConfigList.length; i++) {
23
+ const cacheKeyConfig = cacheKeyConfigList[i];
24
+ if (typeof cacheKeyConfig !== 'string') {
25
+ throw createError();
26
+ }
27
+ if (!cacheKeyConfig.startsWith('query.') && !cacheKeyConfig.startsWith('body.')) {
28
+ throw createError();
29
+ }
30
+ }
31
+ };
32
+ // {middleware:[redisCache(['query.id', 'body.id'])]}
33
+ const toCacheKey = (ctx, cacheKeyConfigList) => {
34
+ checkCacheKeyConfigList(cacheKeyConfigList);
35
+ const path = ctx.path;
36
+ const query = ctx.query || {};
37
+ const body = ctx.request.body || {};
38
+ const newCtx = { path, query, body };
39
+ // 至少要根据path缓存
40
+ const cacheKeyConfigList2 = ['path', ...cacheKeyConfigList];
41
+ const strArray = cacheKeyConfigList2.map((key) => {
42
+ const value = _.get(newCtx, key);
43
+ return { key, value };
44
+ });
45
+ const strArrayStr = JSON.stringify(strArray);
46
+ const strMd5 = md5(strArrayStr);
47
+ return RedisKeys_1.RedisKeys.REDIS_LOCK_MIDDILEWARE + strMd5;
48
+ };
49
+ function toCacheDataString(resData) {
50
+ throw new Error('Function not implemented.');
51
+ }
52
+ function parseCacheData(cacheData) {
53
+ throw new Error('Function not implemented.');
54
+ }
55
+ function redisCache(cacheKeyConfigList, cacheTimeSecond) {
56
+ return async (ctx, next) => {
57
+ const redisService = await getRedisService(ctx);
58
+ const cacheKey = toCacheKey(ctx, cacheKeyConfigList);
59
+ let cacheTime = typeof cacheTimeSecond === 'number' ? cacheTimeSecond : 60; // 默认缓存1分钟
60
+ cacheTime = Math.max(cacheTimeSecond, 1); // 至少缓存1秒。
61
+ cacheTime = Math.min(cacheTimeSecond, 60 * 60); // 最长缓存1小时
62
+ const cacheData = await redisService.get(cacheKey);
63
+ if (cacheData) {
64
+ return parseCacheData(cacheData);
65
+ }
66
+ try {
67
+ const resData = await next();
68
+ const resDataStr = toCacheDataString(resData);
69
+ await redisService.set(cacheKey, resDataStr, 'EX', cacheTime);
70
+ return resData;
71
+ }
72
+ catch (e) {
73
+ console.error('redisCache', e);
74
+ }
75
+ };
76
+ }
77
+ exports.redisCache = redisCache;
@@ -0,0 +1,7 @@
1
+ import { NextFunction, Context } from '@midwayjs/koa';
2
+ declare function redisLock(lockKeyConfigList: string[], lockTimeSecond: number): (ctx: Context, next: NextFunction) => Promise<{
3
+ success: boolean;
4
+ message: string;
5
+ code: string;
6
+ }>;
7
+ export { redisLock };
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.redisLock = void 0;
4
+ const redis_1 = require("@midwayjs/redis");
5
+ const _ = require("lodash");
6
+ const md5 = require("md5");
7
+ const RedisKeys_1 = require("../models/RedisKeys");
8
+ const exceptions_1 = require("../libs/crud-pro/exceptions");
9
+ const getRedisService = async (ctx) => {
10
+ const service = await ctx.requestContext.getAsync(redis_1.RedisService);
11
+ if (!service) {
12
+ return await ctx.requestContext.getAsync('redisService');
13
+ }
14
+ };
15
+ const createError = () => {
16
+ return new exceptions_1.CommonException('redis_lock_middleware_error_config', 'redisLock中间件的第一个参数必须是一个字符串数组, 并且以“query.”或“body.”开头');
17
+ };
18
+ const checkLockKeyConfigList = (lockKeyConfigList) => {
19
+ if (!Array.isArray(lockKeyConfigList)) {
20
+ throw createError();
21
+ }
22
+ for (let i = 0; i < lockKeyConfigList.length; i++) {
23
+ const lockKeyConfig = lockKeyConfigList[i];
24
+ if (typeof lockKeyConfig !== 'string') {
25
+ throw createError();
26
+ }
27
+ if (!lockKeyConfig.startsWith('query.') && !lockKeyConfig.startsWith('body.')) {
28
+ throw createError();
29
+ }
30
+ }
31
+ };
32
+ // {middleware:[redisLock(['query.id', 'body.id'])]}
33
+ const toLockKey = (ctx, lockKeyConfigList) => {
34
+ checkLockKeyConfigList(lockKeyConfigList);
35
+ const path = ctx.path;
36
+ const query = ctx.query || {};
37
+ const body = ctx.request.body || {};
38
+ const newCtx = { path, query, body };
39
+ // 至少要根据path锁
40
+ const lockKeyConfigList2 = ['path', ...lockKeyConfigList];
41
+ const strArray = lockKeyConfigList2.map((key) => {
42
+ const value = _.get(newCtx, key);
43
+ return { key, value };
44
+ });
45
+ const strArrayStr = JSON.stringify(strArray);
46
+ const strMd5 = md5(strArrayStr);
47
+ return RedisKeys_1.RedisKeys.REDIS_LOCK_MIDDILEWARE + strMd5;
48
+ };
49
+ function redisLock(lockKeyConfigList, lockTimeSecond) {
50
+ return async (ctx, next) => {
51
+ const redisService = await getRedisService(ctx);
52
+ const lockKey = toLockKey(ctx, lockKeyConfigList);
53
+ let lockTime = typeof lockTimeSecond === 'number' ? lockTimeSecond : 60; // 默认锁住1分钟(失败的情况)
54
+ lockTime = Math.max(lockTimeSecond, 1); // 至少锁一秒 (失败的情况)
55
+ lockTime = Math.min(lockTimeSecond, 5 * 60); // 最长锁 5分钟(失败的情况)
56
+ const lock = await redisService.set(lockKey, 1, 'EX', lockTime, 'NX');
57
+ if (lock !== 'OK') {
58
+ return {
59
+ success: false,
60
+ message: '您请求的接口当前正在处理中,请稍后再试',
61
+ code: 'redis_lock_middleware_error_locked',
62
+ };
63
+ }
64
+ try {
65
+ await next();
66
+ }
67
+ finally {
68
+ await redisService.del(lockKey); // 正常运行完成,立即释放锁。
69
+ }
70
+ };
71
+ }
72
+ exports.redisLock = redisLock;
@@ -10,5 +10,6 @@ declare const RedisKeys: {
10
10
  LINK_TO_CUSTOM_PREFIX: string;
11
11
  CURD_MIX_BY_DICT_PREFIX: string;
12
12
  QUERY_ENUM_INFO_PREFIX: string;
13
+ REDIS_LOCK_MIDDILEWARE: string;
13
14
  };
14
15
  export { RedisKeys };
@@ -13,5 +13,6 @@ const RedisKeys = {
13
13
  LINK_TO_CUSTOM_PREFIX: 'FatLinkToCustom@@',
14
14
  CURD_MIX_BY_DICT_PREFIX: 'FatCurdMixByDict@@',
15
15
  QUERY_ENUM_INFO_PREFIX: 'FatQueryEnum@@',
16
+ REDIS_LOCK_MIDDILEWARE: 'FatRedisLock@@',
16
17
  };
17
18
  exports.RedisKeys = RedisKeys;
@@ -66,6 +66,7 @@ export interface IVisitorExt extends IVisitor {
66
66
  workbenchCode: string;
67
67
  avatar: string;
68
68
  accountType: string;
69
+ bizExt?: any;
69
70
  }
70
71
  export declare const FILE_GET_TYPES: string[];
71
72
  /**
@@ -17,6 +17,7 @@ interface ISessionInfo {
17
17
  accountId: string;
18
18
  workbenchCode: string;
19
19
  accountType: string;
20
+ bizExt?: any;
20
21
  }
21
22
  interface IConsumerUserInfo {
22
23
  workbenchCode: string;
@@ -10,7 +10,8 @@ export declare class UserSessionService {
10
10
  */
11
11
  private getSessionKeepTimeSecond;
12
12
  /**
13
- * 保存用户会话信息
13
+ * 保存用户会话信息。
14
+ * 用户登录后,在业务的项目中,可以调用此函数,更新bizExt字段
14
15
  * @param sessionInfo
15
16
  */
16
17
  saveUserSession(sessionInfo: ISessionInfo): Promise<void>;
@@ -61,7 +61,8 @@ let UserSessionService = class UserSessionService {
61
61
  return SESSION_KEEP_TIME_SECOND;
62
62
  }
63
63
  /**
64
- * 保存用户会话信息
64
+ * 保存用户会话信息。
65
+ * 用户登录后,在业务的项目中,可以调用此函数,更新bizExt字段
65
66
  * @param sessionInfo
66
67
  */
67
68
  async saveUserSession(sessionInfo) {
@@ -6,6 +6,7 @@ const axios_1 = require("axios");
6
6
  const AsyncTaskModel_1 = require("../../../models/AsyncTaskModel");
7
7
  const schedule_1 = require("../../../schedule");
8
8
  const functions_1 = require("../../../libs/utils/functions");
9
+ const global_config_1 = require("../../../libs/global-config/global-config");
9
10
  function pickData(a, key) {
10
11
  if (a && typeof a.getResModel === 'function') {
11
12
  const s = a.getResModel();
@@ -29,8 +30,9 @@ class ExportExcelByInnerHttpHandler {
29
30
  this.appCode = this.inputParams.appCode;
30
31
  }
31
32
  async getPageSize() {
33
+ const maxPageSizeOfExportExcel = global_config_1.GLOBAL_STATIC_CONFIG.getConfig().maxPageSizeOfExportExcel;
32
34
  if (typeof this.inputParams.pageSize === 'number') {
33
- return Math.min(this.inputParams.pageSize, 1000);
35
+ return Math.min(this.inputParams.pageSize, maxPageSizeOfExportExcel);
34
36
  }
35
37
  return 1000;
36
38
  }
@@ -4,6 +4,7 @@ exports.ExportExcelByStdCrudHandler = void 0;
4
4
  const _ = require("lodash");
5
5
  const CrudStdService_1 = require("../../../service/crudstd/CrudStdService");
6
6
  const keys_1 = require("../../../libs/crud-pro/models/keys");
7
+ const global_config_1 = require("../../../libs/global-config/global-config");
7
8
  function pickData(a, key) {
8
9
  if (a && typeof a.getResModel === 'function') {
9
10
  const s = a.getResModel();
@@ -27,8 +28,9 @@ class ExportExcelByStdCrudHandler {
27
28
  this.appCode = this.inputParams.appCode;
28
29
  }
29
30
  async getPageSize() {
31
+ const maxPageSizeOfExportExcel = global_config_1.GLOBAL_STATIC_CONFIG.getConfig().maxPageSizeOfExportExcel;
30
32
  if (typeof this.inputParams.pageSize === 'number') {
31
- return Math.min(this.inputParams.pageSize, 1000);
33
+ return Math.min(this.inputParams.pageSize, maxPageSizeOfExportExcel);
32
34
  }
33
35
  return 1000;
34
36
  }
@@ -37,6 +37,7 @@ function toVisitor(ctx) {
37
37
  roleCodes: [],
38
38
  functionCodes: [],
39
39
  workbenchCode: (workbenchInfo === null || workbenchInfo === void 0 ? void 0 : workbenchInfo.workbench_code) || '',
40
+ bizExt: {}
40
41
  };
41
42
  }
42
43
  const sessionInfo = userSession.getSessionInfo();
@@ -50,6 +51,7 @@ function toVisitor(ctx) {
50
51
  roleCodes: sessionInfo.roleCodes || [],
51
52
  functionCodes: sessionInfo.functionCodes || [],
52
53
  workbenchCode: (workbenchInfo === null || workbenchInfo === void 0 ? void 0 : workbenchInfo.workbench_code) || '',
54
+ bizExt: sessionInfo.bizExt || {}
53
55
  };
54
56
  }
55
57
  class MyContextFunc extends ExecuteContextFunc_1.BaseExecuteContextFunc {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midway-fatcms",
3
- "version": "0.0.1-beta.41",
3
+ "version": "0.0.1-beta.44",
4
4
  "description": "This is a midway component sample",
5
5
  "main": "dist/index.js",
6
6
  "typings": "index.d.ts",