@oneuptime/common 7.0.3250 → 7.0.3260

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.
@@ -4,8 +4,7 @@ import {
4
4
  dataSourceOptions,
5
5
  testDataSourceOptions,
6
6
  } from "./ClickhouseConfig";
7
- import { PingResult, createClient } from "@clickhouse/client";
8
- import { ClickHouseClient } from "@clickhouse/client";
7
+ import { PingResult, createClient, ClickHouseClient } from "@clickhouse/client";
9
8
  import DatabaseNotConnectedException from "Common/Types/Exception/DatabaseNotConnectedException";
10
9
  import Sleep from "Common/Types/Sleep";
11
10
 
@@ -7,31 +7,35 @@ import {
7
7
  import Response from "../Utils/Response";
8
8
  import Dictionary from "Common/Types/Dictionary";
9
9
  import BadDataException from "Common/Types/Exception/BadDataException";
10
- import ObjectID from "Common/Types/ObjectID";
11
10
 
12
11
  export default class ClusterKeyAuthorization {
13
12
  public static getClusterKeyHeaders(): Dictionary<string> {
14
13
  return {
15
- clusterkey: ONEUPTIME_SECRET.toString(),
14
+ clusterkey: ClusterKeyAuthorization.getClusterKey(),
16
15
  };
17
16
  }
18
17
 
18
+ public static getClusterKey(): string {
19
+ // we encode uri component because a lot of people use special characters in their cluster key secret
20
+ return encodeURIComponent(ONEUPTIME_SECRET.toString());
21
+ }
22
+
19
23
  public static async isAuthorizedServiceMiddleware(
20
24
  req: ExpressRequest,
21
25
  res: ExpressResponse,
22
26
  next: NextFunction,
23
27
  ): Promise<void> {
24
- let clusterKey: ObjectID;
28
+ let clusterKey: string;
25
29
 
26
30
  if (req.params && req.params["clusterKey"]) {
27
- clusterKey = new ObjectID(req.params["clusterKey"]);
31
+ clusterKey = req.params["clusterKey"];
28
32
  } else if (req.query && req.query["clusterKey"]) {
29
- clusterKey = new ObjectID(req.query["clusterKey"] as string);
33
+ clusterKey = req.query["clusterKey"] as string;
30
34
  } else if (req.headers && req.headers["clusterkey"]) {
31
35
  // Header keys are automatically transformed to lowercase
32
- clusterKey = new ObjectID(req.headers["clusterkey"] as string);
36
+ clusterKey = req.headers["clusterkey"] as string;
33
37
  } else if (req.body && req.body.clusterKey) {
34
- clusterKey = new ObjectID(req.body.clusterKey);
38
+ clusterKey = req.body.clusterKey;
35
39
  } else {
36
40
  return Response.sendErrorResponse(
37
41
  req,
@@ -41,7 +45,7 @@ export default class ClusterKeyAuthorization {
41
45
  }
42
46
 
43
47
  const isAuthorized: boolean =
44
- clusterKey.toString() === ONEUPTIME_SECRET.toString();
48
+ clusterKey.toString() === ClusterKeyAuthorization.getClusterKey();
45
49
 
46
50
  if (!isAuthorized) {
47
51
  return Response.sendErrorResponse(
@@ -1 +1 @@
1
- {"version":3,"file":"ClickhouseDatabase.js","sourceRoot":"","sources":["../../../../Server/Infrastructure/ClickhouseDatabase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClickhouseDatabase.js","sourceRoot":"","sources":["../../../../Server/Infrastructure/ClickhouseDatabase.ts"],"names":[],"mappings":"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"}
@@ -1,32 +1,35 @@
1
1
  import { ClusterKey as ONEUPTIME_SECRET } from "../EnvironmentConfig";
2
2
  import Response from "../Utils/Response";
3
3
  import BadDataException from "Common/Types/Exception/BadDataException";
4
- import ObjectID from "Common/Types/ObjectID";
5
4
  export default class ClusterKeyAuthorization {
6
5
  static getClusterKeyHeaders() {
7
6
  return {
8
- clusterkey: ONEUPTIME_SECRET.toString(),
7
+ clusterkey: ClusterKeyAuthorization.getClusterKey(),
9
8
  };
10
9
  }
10
+ static getClusterKey() {
11
+ // we encode uri component because a lot of people use special characters in their cluster key secret
12
+ return encodeURIComponent(ONEUPTIME_SECRET.toString());
13
+ }
11
14
  static async isAuthorizedServiceMiddleware(req, res, next) {
12
15
  let clusterKey;
13
16
  if (req.params && req.params["clusterKey"]) {
14
- clusterKey = new ObjectID(req.params["clusterKey"]);
17
+ clusterKey = req.params["clusterKey"];
15
18
  }
16
19
  else if (req.query && req.query["clusterKey"]) {
17
- clusterKey = new ObjectID(req.query["clusterKey"]);
20
+ clusterKey = req.query["clusterKey"];
18
21
  }
19
22
  else if (req.headers && req.headers["clusterkey"]) {
20
23
  // Header keys are automatically transformed to lowercase
21
- clusterKey = new ObjectID(req.headers["clusterkey"]);
24
+ clusterKey = req.headers["clusterkey"];
22
25
  }
23
26
  else if (req.body && req.body.clusterKey) {
24
- clusterKey = new ObjectID(req.body.clusterKey);
27
+ clusterKey = req.body.clusterKey;
25
28
  }
26
29
  else {
27
30
  return Response.sendErrorResponse(req, res, new BadDataException("Cluster key not found."));
28
31
  }
29
- const isAuthorized = clusterKey.toString() === ONEUPTIME_SECRET.toString();
32
+ const isAuthorized = clusterKey.toString() === ClusterKeyAuthorization.getClusterKey();
30
33
  if (!isAuthorized) {
31
34
  return Response.sendErrorResponse(req, res, new BadDataException("Invalid cluster key provided"));
32
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ClusterKeyAuthorization.js","sourceRoot":"","sources":["../../../../Server/Middleware/ClusterKeyAuthorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMtE,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAEzC,OAAO,gBAAgB,MAAM,yCAAyC,CAAC;AACvE,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,uBAAuB;IACnC,MAAM,CAAC,oBAAoB;QAChC,OAAO;YACL,UAAU,EAAE,gBAAgB,CAAC,QAAQ,EAAE;SACxC,CAAC;IACJ,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAC/C,GAAmB,EACnB,GAAoB,EACpB,IAAkB;QAElB,IAAI,UAAoB,CAAC;QAEzB,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3C,UAAU,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QACtD,CAAC;aAAM,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAChD,UAAU,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAW,CAAC,CAAC;QAC/D,CAAC;aAAM,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YACpD,yDAAyD;YACzD,UAAU,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAW,CAAC,CAAC;QACjE,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC3C,UAAU,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,OAAO,QAAQ,CAAC,iBAAiB,CAC/B,GAAG,EACH,GAAG,EACH,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,CAC/C,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAChB,UAAU,CAAC,QAAQ,EAAE,KAAK,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAExD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,QAAQ,CAAC,iBAAiB,CAC/B,GAAG,EACH,GAAG,EACH,IAAI,gBAAgB,CAAC,8BAA8B,CAAC,CACrD,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;CACF"}
1
+ {"version":3,"file":"ClusterKeyAuthorization.js","sourceRoot":"","sources":["../../../../Server/Middleware/ClusterKeyAuthorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMtE,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAEzC,OAAO,gBAAgB,MAAM,yCAAyC,CAAC;AAEvE,MAAM,CAAC,OAAO,OAAO,uBAAuB;IACnC,MAAM,CAAC,oBAAoB;QAChC,OAAO;YACL,UAAU,EAAE,uBAAuB,CAAC,aAAa,EAAE;SACpD,CAAC;IACJ,CAAC;IAEM,MAAM,CAAC,aAAa;QACzB,qGAAqG;QACrG,OAAO,kBAAkB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAC/C,GAAmB,EACnB,GAAoB,EACpB,IAAkB;QAElB,IAAI,UAAkB,CAAC;QAEvB,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3C,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAChD,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAW,CAAC;QACjD,CAAC;aAAM,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YACpD,yDAAyD;YACzD,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,CAAW,CAAC;QACnD,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC3C,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,OAAO,QAAQ,CAAC,iBAAiB,CAC/B,GAAG,EACH,GAAG,EACH,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,CAC/C,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAChB,UAAU,CAAC,QAAQ,EAAE,KAAK,uBAAuB,CAAC,aAAa,EAAE,CAAC;QAEpE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,QAAQ,CAAC,iBAAiB,CAC/B,GAAG,EACH,GAAG,EACH,IAAI,gBAAgB,CAAC,8BAA8B,CAAC,CACrD,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneuptime/common",
3
- "version": "7.0.3250",
3
+ "version": "7.0.3260",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -77,7 +77,7 @@
77
77
  "airtable": "^0.12.2",
78
78
  "axios": "^1.7.2",
79
79
  "bullmq": "^5.3.3",
80
- "Common": "npm:@oneuptime/common@7.0.3250",
80
+ "Common": "npm:@oneuptime/common@7.0.3260",
81
81
  "cookie-parser": "^1.4.7",
82
82
  "cors": "^2.8.5",
83
83
  "cron-parser": "^4.8.1",