util.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. const jwt = require('jsonwebtoken');
  2. const sdk = require('@baiducloud/sdk');
  3. const config = require('../config');
  4. const { Keyv } = require('keyv');
  5. const keyv = new Keyv();
  6. const request = require('./request');
  7. /**
  8. * 工具函数
  9. */
  10. module.exports = {
  11. /**
  12. * 接口成功输出
  13. * @param {*} ctx 上下文对象
  14. * @param {*} data 返回结果
  15. * @param {*} code 返回状态码
  16. */
  17. success(ctx, data = '', code = 0) {
  18. ctx.body = {
  19. code,
  20. data,
  21. message: '操作成功',
  22. };
  23. },
  24. /**
  25. * 接口失败输出
  26. * @param {*} ctx 上下文对象
  27. * @param {*} message 返回信息
  28. * @param {*} code 返回状态码
  29. */
  30. fail(ctx, message = '', code = -1, data = '') {
  31. ctx.body = {
  32. code,
  33. data,
  34. message,
  35. };
  36. },
  37. /**
  38. * 判断是否为空
  39. * @param {*} val 判断值
  40. * @returns
  41. */
  42. isNotEmpty(val) {
  43. if (val === undefined || val == null || val === '') {
  44. return false;
  45. } else if (typeof val === 'string') {
  46. if (val.trim() === '') {
  47. return false;
  48. } else {
  49. return true;
  50. }
  51. } else {
  52. return true;
  53. }
  54. },
  55. /**
  56. * 判断是否为数字
  57. * @param {*} val 判断值
  58. * @returns
  59. */
  60. isNumber(val) {
  61. const isTrue = this.isNotEmpty(val);
  62. return isTrue && (typeof val === 'number' || isNaN(val) === false);
  63. },
  64. /**
  65. * 验证环境是否合法
  66. * @param {*} env 环境名称
  67. * @returns
  68. */
  69. checkEnv(env) {
  70. if (['stg', 'pre', 'prd'].includes(env)) {
  71. return true;
  72. }
  73. return false;
  74. },
  75. /**
  76. * 获取cookie
  77. * @param {*} ctx 上下文对象
  78. * @param {*} name cookie名称
  79. * @returns
  80. */
  81. getCookie(ctx, name) {
  82. return ctx.cookies.get(name);
  83. },
  84. /**
  85. * 生成jwt-token
  86. * @param {*} payload 参数对象
  87. * @returns jwt-token
  88. */
  89. createToken(payload) {
  90. return jwt.sign(payload, config.JWT_SECRET, {
  91. expiresIn: config.JWT_EXPIRES_IN,
  92. });
  93. },
  94. /**
  95. * 解密jwt-token
  96. * @param {*} ctx 上下文对象
  97. * @returns 解密后对象
  98. */
  99. decodeToken(ctx) {
  100. try {
  101. let [, authorization] = (ctx.request.headers?.authorization || '').split(' ');
  102. if (!authorization) {
  103. return ctx.throw(400, '账号信息异常,请重新登录');
  104. }
  105. return jwt.verify(authorization, config.JWT_SECRET);
  106. } catch (error) {
  107. return ctx.throw(401, '账号信息异常,请重新登录');
  108. }
  109. },
  110. // 解密重置密码对应的token
  111. decodeResetToken(token) {
  112. return jwt.verify(token, config.JWT_SECRET);
  113. },
  114. /**
  115. * 上传文件,用于自定义组件内容上传到bos
  116. * @param {*} fileName 文件名称
  117. * @param {*} content 文件内容
  118. * @returns 上传后云地址
  119. */
  120. async uploadString(userId, fileName, content) {
  121. let client = null;
  122. if (config.OSS_TYPE === 'minio') {
  123. // 创建 MinIO 客户端
  124. client = new Minio.Client({
  125. endPoint: config.OSS_ENDPOINT,
  126. port: config.OSS_PORT, // MinIO 默认端口
  127. useSSL: config.OSS_USESSL, // 如果使用 HTTPS,请设置为 true
  128. accessKey: config.OSS_ACCESSKEY,
  129. secretKey: config.OSS_ACCESSKEYSECRET,
  130. });
  131. } else if (config.OSS_TYPE === 'baidu') {
  132. const ossConfig = {
  133. endpoint: config.OSS_ENDPOINT, //传入Bucket所在区域域名
  134. credentials: {
  135. ak: config.OSS_ACCESSKEY, //您的AccessKey
  136. sk: config.OSS_ACCESSKEYSECRET, //您的SecretAccessKey
  137. },
  138. };
  139. client = new sdk.BosClient(ossConfig);
  140. } else {
  141. client = new OSS({
  142. // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  143. region: config.OSS_REGION,
  144. // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  145. accessKeyId: config.OSS_ACCESSKEY,
  146. accessKeySecret: config.OSS_ACCESSKEYSECRET,
  147. authorizationV4: true,
  148. // 填写Bucket名称。
  149. bucket: config.OSS_BUCKET,
  150. });
  151. }
  152. let key = `libs/${userId}/${fileName}`;
  153. let ContentType = '';
  154. if (fileName.endsWith('.js')) {
  155. ContentType = 'application/javascript; charset=utf-8';
  156. } else if (fileName.endsWith('.html')) {
  157. ContentType = 'text/html; charset=utf-8';
  158. } else if (fileName.endsWith('.json')) {
  159. ContentType = 'application/json; charset=utf-8';
  160. } else if (fileName.endsWith('.css')) {
  161. ContentType = 'text/css; charset=utf-8';
  162. }
  163. // 以字符串形式上传
  164. if (config.OSS_TYPE === 'aliyun') {
  165. await client.put(key, Buffer.from(content, 'utf8'));
  166. } else {
  167. await client.putObject(config.OSS_BUCKET, key, Buffer.from(content, 'utf8'), {
  168. 'Content-Type': ContentType, // 添加http header
  169. 'Cache-Control': 'public, max-age=31536000', // 指定缓存指令
  170. 'x-bce-acl': 'public-read',
  171. });
  172. }
  173. },
  174. // 获取用户IP
  175. getClientIp(ctx) {
  176. let ip = ctx.request.headers['x-forwarded-for'] || ctx.request.headers['x-real-ip'] || ctx.request.headers['x-cluster-client-ip'];
  177. // 如果没有上述头,则使用ctx.request.ip(可能是本地IP或代理服务器的IP)
  178. if (!ip) {
  179. ip = ctx.request.ip;
  180. }
  181. // 由于X-Forwarded-For可能包含多个IP(逗号分隔),我们取第一个
  182. if (ip && ip.includes(',')) {
  183. ip = ip.split(',')[0];
  184. }
  185. return ip;
  186. },
  187. };