@casual-simulation/aux-records 2.0.22-alpha.1651045562

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.
@@ -0,0 +1,9 @@
1
+ import { AddFileResult, FileRecordsStore, GetFileRecordResult, MarkFileRecordAsUploadedResult, PresignFileUploadRequest, PresignFileUploadResult } from './FileRecordsStore';
2
+ export declare class MemoryFileRecordsStore implements FileRecordsStore {
3
+ private _files;
4
+ presignFileUpload(request: PresignFileUploadRequest): Promise<PresignFileUploadResult>;
5
+ getFileRecord(recordName: string, fileName: string): Promise<GetFileRecordResult>;
6
+ addFileRecord(recordName: string, fileName: string, publisherId: string, subjectId: string, sizeInBytes: number, description: string): Promise<AddFileResult>;
7
+ setFileRecordAsUploaded(recordName: string, fileName: string): Promise<MarkFileRecordAsUploadedResult>;
8
+ }
9
+ //# sourceMappingURL=MemoryFileRecordsStore.d.ts.map
@@ -0,0 +1,83 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ export class MemoryFileRecordsStore {
11
+ constructor() {
12
+ this._files = new Map();
13
+ }
14
+ presignFileUpload(request) {
15
+ throw new Error('Method not implemented.');
16
+ }
17
+ getFileRecord(recordName, fileName) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ let file = this._files.get(fileName);
20
+ if (file) {
21
+ return {
22
+ success: true,
23
+ fileName: file.fileName,
24
+ recordName: file.recordName,
25
+ publisherId: file.publisherId,
26
+ subjectId: file.subjectId,
27
+ sizeInBytes: file.sizeInBytes,
28
+ uploaded: file.uploaded,
29
+ description: file.description,
30
+ url: `${file.recordName}/${file.fileName}`,
31
+ };
32
+ }
33
+ else {
34
+ return {
35
+ success: false,
36
+ errorCode: 'file_not_found',
37
+ errorMessage: 'The file was not found in the store.',
38
+ };
39
+ }
40
+ });
41
+ }
42
+ addFileRecord(recordName, fileName, publisherId, subjectId, sizeInBytes, description) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ if (this._files.has(fileName)) {
45
+ return {
46
+ success: false,
47
+ errorCode: 'file_already_exists',
48
+ errorMessage: 'The file already exists in the store.',
49
+ };
50
+ }
51
+ let file = {
52
+ fileName: fileName,
53
+ recordName: recordName,
54
+ publisherId,
55
+ subjectId,
56
+ sizeInBytes,
57
+ description,
58
+ uploaded: false,
59
+ };
60
+ this._files.set(fileName, file);
61
+ return {
62
+ success: true,
63
+ };
64
+ });
65
+ }
66
+ setFileRecordAsUploaded(recordName, fileName) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ let file = this._files.get(fileName);
69
+ if (!file) {
70
+ return {
71
+ success: false,
72
+ errorCode: 'file_not_found',
73
+ errorMessage: 'The file was not found in the store.',
74
+ };
75
+ }
76
+ file.uploaded = true;
77
+ return {
78
+ success: true,
79
+ };
80
+ });
81
+ }
82
+ }
83
+ //# sourceMappingURL=MemoryFileRecordsStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryFileRecordsStore.js","sourceRoot":"","sources":["MemoryFileRecordsStore.ts"],"names":[],"mappings":";;;;;;;;;AASA,MAAM,OAAO,sBAAsB;IAAnC;QACY,WAAM,GAA4B,IAAI,GAAG,EAAE,CAAC;IAuFxD,CAAC;IArFG,iBAAiB,CACb,OAAiC;QAEjC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IAEK,aAAa,CACf,UAAkB,EAClB,QAAgB;;YAEhB,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAErC,IAAI,IAAI,EAAE;gBACN,OAAO;oBACH,OAAO,EAAE,IAAI;oBACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,QAAQ,EAAE;iBAC7C,CAAC;aACL;iBAAM;gBACH,OAAO;oBACH,OAAO,EAAE,KAAK;oBACd,SAAS,EAAE,gBAAgB;oBAC3B,YAAY,EAAE,sCAAsC;iBACvD,CAAC;aACL;QACL,CAAC;KAAA;IAEK,aAAa,CACf,UAAkB,EAClB,QAAgB,EAChB,WAAmB,EACnB,SAAiB,EACjB,WAAmB,EACnB,WAAmB;;YAEnB,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;gBAC3B,OAAO;oBACH,OAAO,EAAE,KAAK;oBACd,SAAS,EAAE,qBAAqB;oBAChC,YAAY,EAAE,uCAAuC;iBACxD,CAAC;aACL;YAED,IAAI,IAAI,GAAe;gBACnB,QAAQ,EAAE,QAAQ;gBAClB,UAAU,EAAE,UAAU;gBACtB,WAAW;gBACX,SAAS;gBACT,WAAW;gBACX,WAAW;gBACX,QAAQ,EAAE,KAAK;aAClB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAEhC,OAAO;gBACH,OAAO,EAAE,IAAI;aAChB,CAAC;QACN,CAAC;KAAA;IAEK,uBAAuB,CACzB,UAAkB,EAClB,QAAgB;;YAEhB,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAErC,IAAI,CAAC,IAAI,EAAE;gBACP,OAAO;oBACH,OAAO,EAAE,KAAK;oBACd,SAAS,EAAE,gBAAgB;oBAC3B,YAAY,EAAE,sCAAsC;iBACvD,CAAC;aACL;YAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,OAAO;gBACH,OAAO,EAAE,IAAI;aAChB,CAAC;QACN,CAAC;KAAA;CACJ"}
@@ -0,0 +1,8 @@
1
+ import { Record, RecordsStore } from './RecordsStore';
2
+ export declare class MemoryRecordsStore implements RecordsStore {
3
+ private _records;
4
+ getRecordByName(name: string): Promise<Record>;
5
+ updateRecord(record: Record): Promise<void>;
6
+ addRecord(record: Record): Promise<void>;
7
+ }
8
+ //# sourceMappingURL=MemoryRecordsStore.d.ts.map
@@ -0,0 +1,37 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ export class MemoryRecordsStore {
11
+ constructor() {
12
+ this._records = [];
13
+ }
14
+ getRecordByName(name) {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const record = this._records.find((r) => r.name === name);
17
+ return record;
18
+ });
19
+ }
20
+ updateRecord(record) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const existingRecordIndex = this._records.findIndex((r) => r.name === record.name);
23
+ if (existingRecordIndex >= 0) {
24
+ this._records[existingRecordIndex] = record;
25
+ }
26
+ });
27
+ }
28
+ addRecord(record) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ const existingRecordIndex = this._records.findIndex((r) => r.name === record.name);
31
+ if (existingRecordIndex < 0) {
32
+ this._records.push(record);
33
+ }
34
+ });
35
+ }
36
+ }
37
+ //# sourceMappingURL=MemoryRecordsStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryRecordsStore.js","sourceRoot":"","sources":["MemoryRecordsStore.ts"],"names":[],"mappings":";;;;;;;;;AAEA,MAAM,OAAO,kBAAkB;IAA/B;QACY,aAAQ,GAAa,EAAE,CAAC;IAwBpC,CAAC;IAtBS,eAAe,CAAC,IAAY;;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAC1D,OAAO,MAAM,CAAC;QAClB,CAAC;KAAA;IAEK,YAAY,CAAC,MAAc;;YAC7B,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAC/C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAChC,CAAC;YACF,IAAI,mBAAmB,IAAI,CAAC,EAAE;gBAC1B,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC;aAC/C;QACL,CAAC;KAAA;IAEK,SAAS,CAAC,MAAc;;YAC1B,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAC/C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAChC,CAAC;YACF,IAAI,mBAAmB,GAAG,CAAC,EAAE;gBACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aAC9B;QACL,CAAC;KAAA;CACJ"}
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Records
2
+
3
+ A set of helpers and managers for the CasualOS records system.
@@ -0,0 +1,121 @@
1
+ import { RecordsStore } from './RecordsStore';
2
+ import { ServerError } from './Errors';
3
+ /**
4
+ * Defines a class that manages records and their keys.
5
+ */
6
+ export declare class RecordsController {
7
+ private _store;
8
+ constructor(store: RecordsStore);
9
+ /**
10
+ * Creates a new public record key for the given bucket name.
11
+ * @param name The name of the record.
12
+ * @param userId The ID of the user that is creating the public record.
13
+ * @returns
14
+ */
15
+ createPublicRecordKey(name: string, userId: string): Promise<CreatePublicRecordKeyResult>;
16
+ /**
17
+ * Validates the given record key. Returns success if the key is valid and can be used to publish things to its bucket.
18
+ * @param key The key that should be validated.
19
+ * @returns
20
+ */
21
+ validatePublicRecordKey(key: string): Promise<ValidatePublicRecordKeyResult>;
22
+ }
23
+ export declare type ValidatePublicRecordKeyResult = ValidatePublicRecordKeySuccess | ValidatePublicRecordKeyFailure;
24
+ /**
25
+ * Defines an interface that represents the result of a "validate public record key" operation.
26
+ */
27
+ export interface ValidatePublicRecordKeySuccess {
28
+ success: true;
29
+ /**
30
+ * The name of the record that the key is for.
31
+ */
32
+ recordName: string;
33
+ /**
34
+ * The ID of the user that owns the record.
35
+ */
36
+ ownerId: string;
37
+ }
38
+ /**
39
+ * Defines an interface that represents a failed "validate public record key" result.
40
+ */
41
+ export interface ValidatePublicRecordKeyFailure {
42
+ /**
43
+ * Whether the operation was successful.
44
+ */
45
+ success: false;
46
+ /**
47
+ * The type of error that occurred.
48
+ */
49
+ errorCode: InvalidRecordKey | ServerError | 'record_not_found';
50
+ /**
51
+ * The error message.
52
+ */
53
+ errorMessage: string;
54
+ }
55
+ /**
56
+ * Defines an interface that represents the result of a "create public record key" operation.
57
+ */
58
+ export declare type CreatePublicRecordKeyResult = CreatePublicRecordKeySuccess | CreatePublicRecordKeyFailure;
59
+ /**
60
+ * Defines an interface that represents a successful "create public record key" result.
61
+ */
62
+ export interface CreatePublicRecordKeySuccess {
63
+ /**
64
+ * Whether the operation was successful.
65
+ */
66
+ success: true;
67
+ /**
68
+ * The key that was created.
69
+ */
70
+ recordKey: string;
71
+ /**
72
+ * The name of the record the key was created for.
73
+ */
74
+ recordName: string;
75
+ }
76
+ /**
77
+ * Defines an interface that represents a failed "create public record key" result.
78
+ */
79
+ export interface CreatePublicRecordKeyFailure {
80
+ /**
81
+ * Whether the operation was successful.
82
+ */
83
+ success: false;
84
+ /**
85
+ * The type of error that occurred.
86
+ */
87
+ errorCode: UnauthorizedToCreateRecordKeyError | ServerError;
88
+ /**
89
+ * The error message.
90
+ */
91
+ errorMessage: string;
92
+ }
93
+ /**
94
+ * Defines an error that occurs when a user is not authorized to create a key for the public record.
95
+ * This may happen when the user is not the owner of the record.
96
+ */
97
+ export declare type UnauthorizedToCreateRecordKeyError = 'unauthorized_to_create_record_key';
98
+ /**
99
+ * Defines an error that occurs when an unspecified error occurs while creating a public record key.
100
+ */
101
+ export declare type InvalidRecordKey = 'invalid_record_key';
102
+ /**
103
+ * Formats the given record name and record secret into a record key.
104
+ * @param recordName The name of the record.
105
+ * @param recordSecret The secret that is used to access the record.
106
+ */
107
+ export declare function formatRecordKey(recordName: string, recordSecret: string): string;
108
+ /**
109
+ * Parses the given record key into a name and password pair.
110
+ * Returns null if the key cannot be parsed.
111
+ * @param key The key to parse.
112
+ * @returns
113
+ */
114
+ export declare function parseRecordKey(key: string): [name: string, password: string];
115
+ /**
116
+ * Determines if the given value is a record key.
117
+ * @param key The value to check.
118
+ * @returns
119
+ */
120
+ export declare function isRecordKey(key: unknown): key is string;
121
+ //# sourceMappingURL=RecordsController.d.ts.map
@@ -0,0 +1,178 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { toBase64String, fromBase64String } from './Utils';
11
+ import { hashPasswordWithSalt, verifyPasswordAgainstHashes, } from '@casual-simulation/crypto';
12
+ import { randomBytes } from 'tweetnacl';
13
+ import { fromByteArray } from 'base64-js';
14
+ /**
15
+ * Defines a class that manages records and their keys.
16
+ */
17
+ export class RecordsController {
18
+ constructor(store) {
19
+ this._store = store;
20
+ }
21
+ /**
22
+ * Creates a new public record key for the given bucket name.
23
+ * @param name The name of the record.
24
+ * @param userId The ID of the user that is creating the public record.
25
+ * @returns
26
+ */
27
+ createPublicRecordKey(name, userId) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ try {
30
+ const record = yield this._store.getRecordByName(name);
31
+ if (record) {
32
+ if (record.ownerId !== userId) {
33
+ return {
34
+ success: false,
35
+ errorCode: 'unauthorized_to_create_record_key',
36
+ errorMessage: 'Another user has already created this record.',
37
+ };
38
+ }
39
+ const passwordBytes = randomBytes(16);
40
+ const password = fromByteArray(passwordBytes); // convert to human-readable string
41
+ const salt = record.secretSalt;
42
+ const passwordHash = hashPasswordWithSalt(password, salt);
43
+ yield this._store.updateRecord(Object.assign(Object.assign({}, record), { secretHashes: [...record.secretHashes, passwordHash] }));
44
+ return {
45
+ success: true,
46
+ recordKey: formatRecordKey(name, password),
47
+ recordName: name,
48
+ };
49
+ }
50
+ else {
51
+ const passwordBytes = randomBytes(16);
52
+ const password = fromByteArray(passwordBytes); // convert to human-readable string
53
+ const salt = fromByteArray(randomBytes(16));
54
+ const passwordHash = hashPasswordWithSalt(password, salt);
55
+ yield this._store.addRecord({
56
+ name,
57
+ ownerId: userId,
58
+ secretHashes: [passwordHash],
59
+ secretSalt: salt,
60
+ });
61
+ return {
62
+ success: true,
63
+ recordKey: formatRecordKey(name, password),
64
+ recordName: name,
65
+ };
66
+ }
67
+ }
68
+ catch (err) {
69
+ console.error(err);
70
+ return {
71
+ success: false,
72
+ errorCode: 'server_error',
73
+ errorMessage: err.toString(),
74
+ };
75
+ }
76
+ });
77
+ }
78
+ /**
79
+ * Validates the given record key. Returns success if the key is valid and can be used to publish things to its bucket.
80
+ * @param key The key that should be validated.
81
+ * @returns
82
+ */
83
+ validatePublicRecordKey(key) {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ try {
86
+ const parseResult = parseRecordKey(key);
87
+ if (!parseResult) {
88
+ return {
89
+ success: false,
90
+ errorCode: 'invalid_record_key',
91
+ errorMessage: 'Invalid record key.',
92
+ };
93
+ }
94
+ const [name, password] = parseResult;
95
+ const record = yield this._store.getRecordByName(name);
96
+ if (!record) {
97
+ return {
98
+ success: false,
99
+ errorCode: 'record_not_found',
100
+ errorMessage: 'Record not found.',
101
+ };
102
+ }
103
+ const result = verifyPasswordAgainstHashes(password, record.secretSalt, record.secretHashes);
104
+ if (result) {
105
+ return {
106
+ success: true,
107
+ recordName: name,
108
+ ownerId: record.ownerId,
109
+ };
110
+ }
111
+ else {
112
+ return {
113
+ success: false,
114
+ errorCode: 'invalid_record_key',
115
+ errorMessage: 'Invalid record key.',
116
+ };
117
+ }
118
+ }
119
+ catch (err) {
120
+ console.error(err);
121
+ return {
122
+ success: false,
123
+ errorCode: 'server_error',
124
+ errorMessage: err.toString(),
125
+ };
126
+ }
127
+ });
128
+ }
129
+ }
130
+ /**
131
+ * Formats the given record name and record secret into a record key.
132
+ * @param recordName The name of the record.
133
+ * @param recordSecret The secret that is used to access the record.
134
+ */
135
+ export function formatRecordKey(recordName, recordSecret) {
136
+ return `vRK1.${toBase64String(recordName)}.${toBase64String(recordSecret)}`;
137
+ }
138
+ /**
139
+ * Parses the given record key into a name and password pair.
140
+ * Returns null if the key cannot be parsed.
141
+ * @param key The key to parse.
142
+ * @returns
143
+ */
144
+ export function parseRecordKey(key) {
145
+ if (!key) {
146
+ return null;
147
+ }
148
+ if (!key.startsWith('vRK1.')) {
149
+ return null;
150
+ }
151
+ const withoutVersion = key.slice('vRK1.'.length);
152
+ let nextPeriod = withoutVersion.indexOf('.');
153
+ if (nextPeriod < 0) {
154
+ return null;
155
+ }
156
+ const nameBase64 = withoutVersion.slice(0, nextPeriod);
157
+ const passwordBase64 = withoutVersion.slice(nextPeriod + 1);
158
+ if (nameBase64.length <= 0 || passwordBase64.length <= 0) {
159
+ return null;
160
+ }
161
+ try {
162
+ const name = fromBase64String(nameBase64);
163
+ const password = fromBase64String(passwordBase64);
164
+ return [name, password];
165
+ }
166
+ catch (err) {
167
+ return null;
168
+ }
169
+ }
170
+ /**
171
+ * Determines if the given value is a record key.
172
+ * @param key The value to check.
173
+ * @returns
174
+ */
175
+ export function isRecordKey(key) {
176
+ return typeof key === 'string' && parseRecordKey(key) !== null;
177
+ }
178
+ //# sourceMappingURL=RecordsController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecordsController.js","sourceRoot":"","sources":["RecordsController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Defines an interface for objects that can store records.
3
+ */
4
+ export interface RecordsStore {
5
+ /**
6
+ * Updates the given record.
7
+ * @param record The record that should be updated.
8
+ */
9
+ updateRecord(record: Record): Promise<void>;
10
+ /**
11
+ * Adds the given record to the store.
12
+ * @param record The record to add.
13
+ */
14
+ addRecord(record: Record): Promise<void>;
15
+ /**
16
+ * Gets the record with the given name.
17
+ * @param name The name of the record.
18
+ */
19
+ getRecordByName(name: string): Promise<Record>;
20
+ }
21
+ /**
22
+ * Defines an interface for record objects.
23
+ */
24
+ export interface Record {
25
+ /**
26
+ * The name of the record.
27
+ */
28
+ name: string;
29
+ /**
30
+ * The ID of the user that created the record.
31
+ */
32
+ ownerId: string;
33
+ /**
34
+ * The scrypt hashes of the secrets that allow access to the record.
35
+ */
36
+ secretHashes: string[];
37
+ /**
38
+ * The salt that is used to hash the secrets.
39
+ *
40
+ * Normally it is bad to share a salt between multiple secrets but in this case
41
+ * it is fine because there are very few secrets per salt (i.e. not 1 salt per million users but 1 salt per couple record keys) and the secrets are randomly generated.
42
+ */
43
+ secretSalt: string;
44
+ }
45
+ //# sourceMappingURL=RecordsStore.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=RecordsStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecordsStore.js","sourceRoot":"","sources":["RecordsStore.ts"],"names":[],"mappings":""}
package/Utils.d.ts ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Converts the given string into a base64 string.
3
+ * @param str The string to convert.
4
+ */
5
+ export declare function toBase64String(str: string): string;
6
+ /**
7
+ * Converts the given string from a base64 string.
8
+ * @param base64
9
+ */
10
+ export declare function fromBase64String(base64: string): string;
11
+ /**
12
+ * Signs the given request and adds the related headers to it.
13
+ * @param request The request to sign.
14
+ * @param secretAccessKey The secret access key to use.
15
+ * @param accessKeyId The ID of the access key that is being used.
16
+ * @param date The date to use for signing.
17
+ * @param region The AWS region.
18
+ * @param service The AWS service.
19
+ */
20
+ export declare function signRequest(request: CanonicalRequest, secretAccessKey: string, accessKeyId: string, date: Date, region: string, service: string): CanonicalRequest;
21
+ /**
22
+ * Constructs a string that can be signed from the given request, date, AWS region, and AWS Service.
23
+ * @param canonicalRequest The canonical request to include.
24
+ * @param date The date that the signature is happening on.
25
+ * @param region The region that the signature is for.
26
+ * @param service The service that the signature is for.
27
+ */
28
+ export declare function createStringToSign(canonicalRequest: string, date: Date, region: string, service: string): string;
29
+ /**
30
+ * Creates a signature using the given secret access key and additional info.
31
+ * @param stringToSign The string that should be signed.
32
+ * @param secretAccessKey The secret access key.
33
+ * @param date The date that the signature is happening on.
34
+ * @param region The AWS region.
35
+ * @param service The AWS Service.
36
+ */
37
+ export declare function createAWS4Signature(stringToSign: string, secretAccessKey: string, date: Date, region: string, service: string): string;
38
+ /**
39
+ * Creates a canonical request string that can be used to create a AWS Signature for the given request.
40
+ *
41
+ * See https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
42
+ * @param request The request to create the canonical request for.
43
+ */
44
+ export declare function createCanonicalRequest(request: CanonicalRequest): string;
45
+ export interface CanonicalRequest {
46
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
47
+ uri: string;
48
+ headers: {
49
+ [name: string]: string;
50
+ };
51
+ queryString: {
52
+ [name: string]: string;
53
+ };
54
+ payloadSha256Hex: string;
55
+ }
56
+ /**
57
+ * URI Encodes the given string according to AWS Signature Version 4.
58
+ * See https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
59
+ * @param input The string to URI encode.
60
+ * @param encodeSlash Whether to encode slashes as %2F.
61
+ */
62
+ export declare function canonicalUriEncode(input: string, encodeSlash: boolean): string;
63
+ /**
64
+ * Encodes the given character code as a URI hex string.
65
+ * @param char The character to encode.
66
+ */
67
+ export declare function encodeHexUtf8(char: number): string;
68
+ //# sourceMappingURL=Utils.d.ts.map