@nu-art/file-upload-backend 0.400.7
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.
- package/core/messages.d.ts +3 -0
- package/core/messages.js +2 -0
- package/core/module-pack.d.ts +1 -0
- package/core/module-pack.js +36 -0
- package/core/permissions.d.ts +6 -0
- package/core/permissions.js +52 -0
- package/index.d.ts +5 -0
- package/index.js +23 -0
- package/modules/ModuleBE_AssetUploader.d.ts +19 -0
- package/modules/ModuleBE_AssetUploader.js +45 -0
- package/modules/ModuleBE_AssetsAPI.d.ts +8 -0
- package/modules/ModuleBE_AssetsAPI.js +22 -0
- package/modules/ModuleBE_AssetsDB.d.ts +52 -0
- package/modules/ModuleBE_AssetsDB.js +243 -0
- package/modules/ModuleBE_AssetsDeleted.d.ts +6 -0
- package/modules/ModuleBE_AssetsDeleted.js +26 -0
- package/modules/ModuleBE_AssetsStorage.d.ts +17 -0
- package/modules/ModuleBE_AssetsStorage.js +77 -0
- package/modules/ModuleBE_AssetsTemp.d.ts +6 -0
- package/modules/ModuleBE_AssetsTemp.js +26 -0
- package/modules/ModuleBE_BucketListener.d.ts +14 -0
- package/modules/ModuleBE_BucketListener.js +54 -0
- package/package.json +77 -0
package/core/messages.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ModulePackBE_FileUploader: (import("../modules/ModuleBE_AssetsTemp.js").ModuleBE_AssetsTemp_Class | import("../modules/ModuleBE_BucketListener.js").ModuleBE_BucketListener_Class | import("../modules/ModuleBE_AssetsStorage.js").ModuleBE_AssetsStorage_Class | import("../modules/ModuleBE_AssetsDB.js").ModuleBE_AssetsDB_Class | import("@nu-art/push-pub-sub-backend").ModuleBE_PushPubSub_Class | import("@nu-art/push-pub-sub-backend/modules/ModuleBE_PushSessionDB").ModuleBE_PushSessionDB_Class | import("@nu-art/push-pub-sub-backend/modules/ModuleBE_PushSubscriptionDB").ModuleBE_PushSubscriptionDB_Class | import("@nu-art/thunderstorm-backend").ModuleBE_BaseApi_Class<import("@nu-art/push-pub-sub-shared/push-subscription/types").DBProto_PushSubscription> | import("@nu-art/push-pub-sub-backend/modules/ModuleBE_PushMessagesHistoryDB").ModuleBE_PushMessagesHistoryDB_Class | import("../modules/ModuleBE_AssetsDeleted.js").ModuleBE_AssetsDeleted_Class | import("../modules/ModuleBE_AssetUploader.js").ModuleBE_AssetUploader_Class | import("../modules/ModuleBE_AssetsAPI.js").ModuleBE_AssetsAPI_Class | import("@nu-art/thunderstorm-backend").ModuleBE_BaseApi_Class<import("@nu-art/file-upload-shared").DBProto_AssetsTemp>)[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Permissions management system, define access level for each of
|
|
3
|
+
* your server apis, and restrict users by giving them access levels
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { ModuleBE_AssetsTemp } from '../modules/ModuleBE_AssetsTemp.js';
|
|
20
|
+
import { ModuleBE_AssetsDB } from '../modules/ModuleBE_AssetsDB.js';
|
|
21
|
+
import { ModuleBE_BucketListener } from '../modules/ModuleBE_BucketListener.js';
|
|
22
|
+
import { ModulePackBE_PushPubSub } from '@nu-art/push-pub-sub-backend';
|
|
23
|
+
import { ModuleBE_AssetUploader } from '../modules/ModuleBE_AssetUploader.js';
|
|
24
|
+
import { ModuleBE_AssetsAPI } from '../modules/ModuleBE_AssetsAPI.js';
|
|
25
|
+
import { createApisForDBModuleV3 } from '@nu-art/thunderstorm-backend';
|
|
26
|
+
import { ModuleBE_AssetsStorage } from '../modules/ModuleBE_AssetsStorage.js';
|
|
27
|
+
import { ModuleBE_AssetsDeleted } from '../modules/ModuleBE_AssetsDeleted.js';
|
|
28
|
+
export const ModulePackBE_FileUploader = [
|
|
29
|
+
...ModulePackBE_PushPubSub,
|
|
30
|
+
ModuleBE_AssetUploader,
|
|
31
|
+
ModuleBE_AssetsTemp, createApisForDBModuleV3(ModuleBE_AssetsTemp),
|
|
32
|
+
ModuleBE_AssetsDeleted,
|
|
33
|
+
ModuleBE_AssetsStorage,
|
|
34
|
+
ModuleBE_AssetsDB, ModuleBE_AssetsAPI,
|
|
35
|
+
ModuleBE_BucketListener
|
|
36
|
+
];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DefaultDef_Group } from '@nu-art/permissions-shared';
|
|
2
|
+
import { DefaultDef_Domain, DefaultDef_Package } from '@nu-art/permissions-backend/types';
|
|
3
|
+
export declare const PermissionsDomain_AssetsManager: Readonly<DefaultDef_Domain>;
|
|
4
|
+
export declare const PermissionsGroup_AssetsManager: Readonly<DefaultDef_Group>;
|
|
5
|
+
export declare const PermissionsGroup_AssetsViewer: Readonly<DefaultDef_Group>;
|
|
6
|
+
export declare const PermissionsPackage_AssetsManager: DefaultDef_Package;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { DefaultAccessLevel_Admin, DefaultAccessLevel_Delete, DefaultAccessLevel_Read, DefaultAccessLevel_Write } from '@nu-art/permissions-shared';
|
|
2
|
+
import { ApiDef_Assets, ApiDef_AssetUploader } from '@nu-art/file-upload-shared';
|
|
3
|
+
import { Domain_Developer } from '@nu-art/permissions-backend/permissions';
|
|
4
|
+
import { ModuleBE_AssetsAPI } from '../modules/ModuleBE_AssetsAPI.js';
|
|
5
|
+
const Domain_AssetsManager_ID = '993c496c6aaad9c67723034137d26c42';
|
|
6
|
+
const _PermissionsDomain_AssetsManager = {
|
|
7
|
+
_id: Domain_AssetsManager_ID,
|
|
8
|
+
namespace: 'Assets',
|
|
9
|
+
dbNames: [],
|
|
10
|
+
customApis: [
|
|
11
|
+
{ path: ModuleBE_AssetsAPI.apiDef.v1.deleteAll.path, accessLevel: DefaultAccessLevel_Admin.name },
|
|
12
|
+
{ path: ModuleBE_AssetsAPI.apiDef.v1.patch.path, accessLevel: DefaultAccessLevel_Admin.name },
|
|
13
|
+
{ path: ModuleBE_AssetsAPI.apiDef.v1.upsertAll.path, accessLevel: DefaultAccessLevel_Admin.name },
|
|
14
|
+
{ path: ModuleBE_AssetsAPI.apiDef.v1.upsert.path, accessLevel: DefaultAccessLevel_Admin.name },
|
|
15
|
+
{ path: ModuleBE_AssetsAPI.apiDef.v1.delete.path, accessLevel: DefaultAccessLevel_Delete.name },
|
|
16
|
+
{ path: ModuleBE_AssetsAPI.apiDef.v1.queryUnique.path, accessLevel: DefaultAccessLevel_Read.name },
|
|
17
|
+
{ path: ModuleBE_AssetsAPI.apiDef.v1.query.path, accessLevel: DefaultAccessLevel_Read.name },
|
|
18
|
+
{ path: ApiDef_Assets.vv1.getReadSignedUrl.path, accessLevel: DefaultAccessLevel_Read.name },
|
|
19
|
+
{ path: ApiDef_AssetUploader.vv1.getUploadUrl.path, accessLevel: DefaultAccessLevel_Write.name },
|
|
20
|
+
{
|
|
21
|
+
path: ApiDef_AssetUploader.vv1.processAssetManually.path,
|
|
22
|
+
domainId: Domain_Developer._id,
|
|
23
|
+
accessLevel: DefaultAccessLevel_Write.name
|
|
24
|
+
},
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
export const PermissionsDomain_AssetsManager = Object.freeze(_PermissionsDomain_AssetsManager);
|
|
28
|
+
const PermissionsGroupId_AssetsViewer = '0773dcf3b9fbe5e595ef6e2a596b8939';
|
|
29
|
+
const PermissionsGroupId_AssetsManager = '3f5037358fba0ae1199047f2fa8add94';
|
|
30
|
+
const _PermissionsGroup_AssetsViewer = {
|
|
31
|
+
_id: PermissionsGroupId_AssetsViewer,
|
|
32
|
+
name: 'Assets Viewer',
|
|
33
|
+
uiLabel: 'Assets Viewer',
|
|
34
|
+
accessLevels: {
|
|
35
|
+
[PermissionsDomain_AssetsManager.namespace]: DefaultAccessLevel_Read.name,
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const _PermissionsGroup_AssetsManager = {
|
|
39
|
+
_id: PermissionsGroupId_AssetsManager,
|
|
40
|
+
name: 'Assets Manager',
|
|
41
|
+
uiLabel: 'Assets Manager',
|
|
42
|
+
accessLevels: {
|
|
43
|
+
[PermissionsDomain_AssetsManager.namespace]: DefaultAccessLevel_Delete.name,
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export const PermissionsGroup_AssetsManager = Object.freeze(_PermissionsGroup_AssetsManager);
|
|
47
|
+
export const PermissionsGroup_AssetsViewer = Object.freeze(_PermissionsGroup_AssetsViewer);
|
|
48
|
+
export const PermissionsPackage_AssetsManager = {
|
|
49
|
+
name: PermissionsDomain_AssetsManager.namespace,
|
|
50
|
+
domains: [PermissionsDomain_AssetsManager],
|
|
51
|
+
groups: [PermissionsGroup_AssetsViewer, PermissionsGroup_AssetsManager]
|
|
52
|
+
};
|
package/index.d.ts
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Permissions management system, define access level for each of
|
|
3
|
+
* your server apis, and restrict users by giving them access levels
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
export * from './core/module-pack.js';
|
|
20
|
+
export * from './modules/ModuleBE_AssetsDB.js';
|
|
21
|
+
export * from './modules/ModuleBE_AssetsTemp.js';
|
|
22
|
+
export * from './modules/ModuleBE_BucketListener.js';
|
|
23
|
+
export * from './modules/ModuleBE_AssetUploader.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ModuleBase_AssetUploader, UploaderConfig } from '@nu-art/file-upload-shared/modules/ModuleBase_AssetUploader';
|
|
2
|
+
import { Axios_RequestConfig } from '@nu-art/thunderstorm-backend';
|
|
3
|
+
import { TempSignedUrl, UI_Asset } from '@nu-art/file-upload-shared';
|
|
4
|
+
import { ApiDef, BaseHttpRequest, TypedApi } from '@nu-art/thunderstorm-shared';
|
|
5
|
+
export type ServerFilesToUpload = UI_Asset & {
|
|
6
|
+
file: Buffer;
|
|
7
|
+
};
|
|
8
|
+
type Config = UploaderConfig & {
|
|
9
|
+
requestConfig: Axios_RequestConfig;
|
|
10
|
+
};
|
|
11
|
+
export declare class ModuleBE_AssetUploader_Class extends ModuleBase_AssetUploader<Config> {
|
|
12
|
+
constructor();
|
|
13
|
+
init(): void;
|
|
14
|
+
createRequest<API extends TypedApi<any, any, any, any>>(uploadFile: ApiDef<API>): BaseHttpRequest<API>;
|
|
15
|
+
upload(files: ServerFilesToUpload[]): UI_Asset[];
|
|
16
|
+
protected subscribeToPush(toSubscribe: TempSignedUrl[]): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare const ModuleBE_AssetUploader: ModuleBE_AssetUploader_Class;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Permissions management system, define access level for each of
|
|
3
|
+
* your server apis, and restrict users by giving them access levels
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { ModuleBase_AssetUploader, } from '@nu-art/file-upload-shared/modules/ModuleBase_AssetUploader';
|
|
20
|
+
import { apiWithBodyAxios, apiWithQueryAxios, AxiosHttpModule } from '@nu-art/thunderstorm-backend';
|
|
21
|
+
import { ApiDef_AssetUploader } from '@nu-art/file-upload-shared';
|
|
22
|
+
export class ModuleBE_AssetUploader_Class extends ModuleBase_AssetUploader {
|
|
23
|
+
constructor() {
|
|
24
|
+
super();
|
|
25
|
+
this.vv1 = {
|
|
26
|
+
getUploadUrl: apiWithBodyAxios(ApiDef_AssetUploader.vv1.getUploadUrl),
|
|
27
|
+
processAssetManually: apiWithQueryAxios(ApiDef_AssetUploader.vv1.processAssetManually),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
init() {
|
|
31
|
+
super.init();
|
|
32
|
+
AxiosHttpModule.setRequestOption(this.config.requestConfig);
|
|
33
|
+
}
|
|
34
|
+
createRequest(uploadFile) {
|
|
35
|
+
return AxiosHttpModule.createRequest(uploadFile);
|
|
36
|
+
}
|
|
37
|
+
upload(files) {
|
|
38
|
+
return this.uploadImpl(files);
|
|
39
|
+
}
|
|
40
|
+
async subscribeToPush(toSubscribe) {
|
|
41
|
+
// Not sure now
|
|
42
|
+
// We said timeout
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export const ModuleBE_AssetUploader = new ModuleBE_AssetUploader_Class();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ModuleBE_BaseApi_Class } from '@nu-art/thunderstorm-backend';
|
|
2
|
+
import { DBProto_Assets } from '@nu-art/file-upload-shared';
|
|
3
|
+
export declare class ModuleBE_AssetsAPI_Class extends ModuleBE_BaseApi_Class<DBProto_Assets> {
|
|
4
|
+
constructor();
|
|
5
|
+
init(): void;
|
|
6
|
+
private getReadSignedUrl;
|
|
7
|
+
}
|
|
8
|
+
export declare const ModuleBE_AssetsAPI: ModuleBE_AssetsAPI_Class;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { addRoutes, createBodyServerApi, ModuleBE_BaseApi_Class } from '@nu-art/thunderstorm-backend';
|
|
2
|
+
import { ModuleBE_AssetsDB } from './ModuleBE_AssetsDB.js';
|
|
3
|
+
import { ApiDef_Assets } from '@nu-art/file-upload-shared';
|
|
4
|
+
import { ModuleBE_AssetsStorage } from './ModuleBE_AssetsStorage.js';
|
|
5
|
+
export class ModuleBE_AssetsAPI_Class extends ModuleBE_BaseApi_Class {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(ModuleBE_AssetsDB);
|
|
8
|
+
}
|
|
9
|
+
init() {
|
|
10
|
+
super.init();
|
|
11
|
+
addRoutes([
|
|
12
|
+
createBodyServerApi(ApiDef_Assets.vv1.getReadSignedUrl, this.getReadSignedUrl)
|
|
13
|
+
]);
|
|
14
|
+
}
|
|
15
|
+
getReadSignedUrl = async (body) => {
|
|
16
|
+
const dbAsset = await ModuleBE_AssetsDB.query.uniqueAssert(body._id);
|
|
17
|
+
return {
|
|
18
|
+
signedUrl: (await (await ModuleBE_AssetsStorage.getFile(dbAsset)).getReadSignedUrl()).signedUrl
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export const ModuleBE_AssetsAPI = new ModuleBE_AssetsAPI_Class();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { TypedMap } from '@nu-art/ts-common';
|
|
2
|
+
import { CleanupDetails, DBApiConfigV3, ModuleBE_BaseDB, OnCleanupSchedulerAct } from '@nu-art/thunderstorm-backend';
|
|
3
|
+
import { Clause_Where } from '@nu-art/firebase-shared';
|
|
4
|
+
import { OnAssetUploaded } from './ModuleBE_BucketListener.js';
|
|
5
|
+
import { DB_Asset, DBProto_Assets, TempSignedUrl, UI_Asset } from '@nu-art/file-upload-shared';
|
|
6
|
+
import { CollectionActionType, PostWriteProcessingData } from '@nu-art/firebase-backend/firestore-v3/FirestoreCollectionV3';
|
|
7
|
+
import { firestore } from 'firebase-admin';
|
|
8
|
+
import { FileMetadata } from '@google-cloud/storage';
|
|
9
|
+
import { FileWrapper, FirestoreTransaction } from '@nu-art/firebase-backend';
|
|
10
|
+
import Transaction = firestore.Transaction;
|
|
11
|
+
type MyConfig = DBApiConfigV3<DBProto_Assets> & {
|
|
12
|
+
authKey: string;
|
|
13
|
+
bucketName?: string;
|
|
14
|
+
storagePath: string;
|
|
15
|
+
pathRegexp: string;
|
|
16
|
+
};
|
|
17
|
+
export type AssetContent = {
|
|
18
|
+
asset: DB_Asset;
|
|
19
|
+
content: Buffer;
|
|
20
|
+
};
|
|
21
|
+
export type FileTypeResult = {
|
|
22
|
+
ext: string;
|
|
23
|
+
mime: string;
|
|
24
|
+
};
|
|
25
|
+
export type FileTypeValidation = {
|
|
26
|
+
fileType?: string[];
|
|
27
|
+
minSize?: number;
|
|
28
|
+
maxSize?: number;
|
|
29
|
+
validator?: FileValidator;
|
|
30
|
+
};
|
|
31
|
+
export declare const DefaultMimetypeValidator: (file: FileWrapper, doc: DB_Asset) => Promise<import("file-type").FileTypeResult>;
|
|
32
|
+
export type FileValidator = (file: FileWrapper, doc: DB_Asset) => Promise<FileTypeResult | undefined>;
|
|
33
|
+
export declare const fileSizeValidator: (file: FileWrapper, metadata: FileMetadata, minSizeInBytes?: number, maxSizeInBytes?: number) => Promise<boolean>;
|
|
34
|
+
export declare class ModuleBE_AssetsDB_Class extends ModuleBE_BaseDB<DBProto_Assets, MyConfig> implements OnCleanupSchedulerAct, OnAssetUploaded {
|
|
35
|
+
constructor();
|
|
36
|
+
mimeTypeValidator: TypedMap<FileValidator>;
|
|
37
|
+
fileValidator: TypedMap<FileTypeValidation>;
|
|
38
|
+
protected postWriteProcessing(data: PostWriteProcessingData<DBProto_Assets>, actionType: CollectionActionType, transaction?: Transaction): Promise<void>;
|
|
39
|
+
init(): void;
|
|
40
|
+
getAssetsContent(assetIds: string[]): Promise<AssetContent[]>;
|
|
41
|
+
registerTypeValidator(mimeType: string, validator: (file: FileWrapper, doc: DB_Asset) => Promise<void>): void;
|
|
42
|
+
queryUnique(where: Clause_Where<DB_Asset>, transaction?: FirestoreTransaction): Promise<DB_Asset>;
|
|
43
|
+
register: (key: string, validationConfig: FileTypeValidation) => void;
|
|
44
|
+
__onCleanupSchedulerAct(): CleanupDetails;
|
|
45
|
+
private cleanup;
|
|
46
|
+
getUrl: (files: UI_Asset[]) => Promise<TempSignedUrl[]>;
|
|
47
|
+
processAssetManually: (feId?: string) => Promise<void[]>;
|
|
48
|
+
__processAsset: (filePath?: string) => Promise<void>;
|
|
49
|
+
private notifyFrontend;
|
|
50
|
+
}
|
|
51
|
+
export declare const ModuleBE_AssetsDB: ModuleBE_AssetsDB_Class;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Permissions management system, define access level for each of
|
|
3
|
+
* your server apis, and restrict users by giving them access levels
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { ApiException, asArray, BadImplementationException, currentTimeMillis, Day, exists, filterInstances, generateHex, Hour, ImplementationMissingException, MB, Minute, MUSTNeverHappenException, ThisShouldNotHappenException } from '@nu-art/ts-common';
|
|
20
|
+
import { ModuleBE_AssetsTemp } from './ModuleBE_AssetsTemp.js';
|
|
21
|
+
import { addRoutes, createBodyServerApi, ModuleBE_BaseDB } from '@nu-art/thunderstorm-backend';
|
|
22
|
+
import { ModuleBE_AssetsStorage } from './ModuleBE_AssetsStorage.js';
|
|
23
|
+
import { ApiDef_AssetUploader, DBDef_Assets, FileStatus } from '@nu-art/file-upload-shared';
|
|
24
|
+
import { PushMessageBE_FileUploadStatus } from '../core/messages.js';
|
|
25
|
+
import { ModuleBE_AssetsDeleted } from './ModuleBE_AssetsDeleted.js';
|
|
26
|
+
import { fileTypeFromBuffer } from 'file-type';
|
|
27
|
+
export const DefaultMimetypeValidator = async (file, doc) => {
|
|
28
|
+
const buffer = await file.read();
|
|
29
|
+
const fileType = await fileTypeFromBuffer(buffer);
|
|
30
|
+
if (!fileType)
|
|
31
|
+
throw new ImplementationMissingException(`No validator defined for asset of mimetype: ${doc.mimeType}`);
|
|
32
|
+
if (fileType.mime !== doc.mimeType)
|
|
33
|
+
throw new BadImplementationException(`Original mimetype (${doc.mimeType}) does not match the resolved mimetype: (${fileType.mime})`);
|
|
34
|
+
return fileType;
|
|
35
|
+
};
|
|
36
|
+
export const fileSizeValidator = async (file, metadata, minSizeInBytes = 0, maxSizeInBytes = MB) => {
|
|
37
|
+
const fileSize = +(metadata.size ?? 0);
|
|
38
|
+
if (!fileSize)
|
|
39
|
+
throw new ThisShouldNotHappenException(`could not resolve metadata.size for file: ${file.path}`);
|
|
40
|
+
return fileSize >= minSizeInBytes && fileSize <= maxSizeInBytes;
|
|
41
|
+
};
|
|
42
|
+
export class ModuleBE_AssetsDB_Class extends ModuleBE_BaseDB {
|
|
43
|
+
constructor() {
|
|
44
|
+
super(DBDef_Assets);
|
|
45
|
+
this.setDefaultConfig({
|
|
46
|
+
...this.config,
|
|
47
|
+
storagePath: 'assets',
|
|
48
|
+
pathRegexp: '^assets/.*',
|
|
49
|
+
authKey: 'file-uploader'
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
mimeTypeValidator = {};
|
|
53
|
+
fileValidator = {};
|
|
54
|
+
async postWriteProcessing(data, actionType, transaction) {
|
|
55
|
+
const deletedItems = data.deleted;
|
|
56
|
+
if (exists(deletedItems))
|
|
57
|
+
await ModuleBE_AssetsDeleted.create.all(asArray(deletedItems), transaction);
|
|
58
|
+
}
|
|
59
|
+
init() {
|
|
60
|
+
super.init();
|
|
61
|
+
addRoutes([
|
|
62
|
+
createBodyServerApi(ApiDef_AssetUploader.vv1.getUploadUrl, this.getUrl)
|
|
63
|
+
]);
|
|
64
|
+
this.registerVersionUpgradeProcessor('1.0.1', async (assets) => {
|
|
65
|
+
assets.forEach(asset => {
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
delete asset._audit;
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
const originalQuery = this.query;
|
|
71
|
+
this.query = {
|
|
72
|
+
...originalQuery,
|
|
73
|
+
unique: async (_id, transaction) => {
|
|
74
|
+
const dbAsset = await originalQuery.uniqueAssert(_id, transaction);
|
|
75
|
+
const signedUrl = (dbAsset.signedUrl?.validUntil || 0) > currentTimeMillis() ? dbAsset.signedUrl : undefined;
|
|
76
|
+
if (!signedUrl) {
|
|
77
|
+
const url = await ModuleBE_AssetsStorage.getReadSignedUrl(dbAsset);
|
|
78
|
+
dbAsset.signedUrl = {
|
|
79
|
+
url,
|
|
80
|
+
validUntil: currentTimeMillis() + Day - Minute
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return dbAsset;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async getAssetsContent(assetIds) {
|
|
88
|
+
const assetsToSync = filterInstances(await ModuleBE_AssetsDB.query.all(assetIds));
|
|
89
|
+
const assetFiles = await Promise.all(assetsToSync.map(asset => ModuleBE_AssetsStorage.getFile(asset)));
|
|
90
|
+
const assetContent = await Promise.all(assetFiles.map(asset => asset.read()));
|
|
91
|
+
return assetIds.map((id, index) => ({ asset: assetsToSync[index], content: assetContent[index] }));
|
|
92
|
+
}
|
|
93
|
+
registerTypeValidator(mimeType, validator) {
|
|
94
|
+
}
|
|
95
|
+
async queryUnique(where, transaction) {
|
|
96
|
+
const dbAsset = await this.query.uniqueCustom({ where });
|
|
97
|
+
const signedUrl = (dbAsset.signedUrl?.validUntil || 0) > currentTimeMillis() ? dbAsset.signedUrl : undefined;
|
|
98
|
+
if (!signedUrl) {
|
|
99
|
+
const url = await ModuleBE_AssetsStorage.getReadSignedUrl(dbAsset);
|
|
100
|
+
dbAsset.signedUrl = {
|
|
101
|
+
url,
|
|
102
|
+
validUntil: currentTimeMillis() + Day - Minute
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return dbAsset;
|
|
106
|
+
}
|
|
107
|
+
register = (key, validationConfig) => {
|
|
108
|
+
if (this.fileValidator[key] && this.fileValidator[key] !== validationConfig)
|
|
109
|
+
throw new BadImplementationException(`File Validator already exists for key: ${key}`);
|
|
110
|
+
this.fileValidator[key] = validationConfig;
|
|
111
|
+
};
|
|
112
|
+
__onCleanupSchedulerAct() {
|
|
113
|
+
return {
|
|
114
|
+
moduleKey: this.getName(),
|
|
115
|
+
interval: Day,
|
|
116
|
+
cleanup: () => this.cleanup(),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
cleanup = async (interval = Hour, module = ModuleBE_AssetsTemp) => {
|
|
120
|
+
const entries = await module.query.custom({ where: { timestamp: { $lt: currentTimeMillis() - interval } } });
|
|
121
|
+
await Promise.all(entries.map(async (dbAsset) => {
|
|
122
|
+
const file = await ModuleBE_AssetsStorage.getFile(dbAsset);
|
|
123
|
+
if (!(await file.exists()))
|
|
124
|
+
return;
|
|
125
|
+
await file.delete();
|
|
126
|
+
}));
|
|
127
|
+
await module.delete.query({ where: { timestamp: { $lt: currentTimeMillis() - interval } } });
|
|
128
|
+
};
|
|
129
|
+
getUrl = async (files) => {
|
|
130
|
+
const bucketName = this.config?.bucketName;
|
|
131
|
+
const bucket = await ModuleBE_AssetsStorage.storage.getOrCreateBucket(bucketName);
|
|
132
|
+
return Promise.all(files.map(async (_file) => {
|
|
133
|
+
const key = _file.key || _file.mimeType;
|
|
134
|
+
// this will fail the entire request... should it?
|
|
135
|
+
if (!this.fileValidator[key])
|
|
136
|
+
throw new ImplementationMissingException(`Missing validator for type ${key}`);
|
|
137
|
+
const _id = generateHex(32);
|
|
138
|
+
const path = `${this.config.storagePath}/${_id}`;
|
|
139
|
+
const dbAsset = {
|
|
140
|
+
timestamp: currentTimeMillis(),
|
|
141
|
+
_id,
|
|
142
|
+
feId: _file.feId,
|
|
143
|
+
name: _file.name,
|
|
144
|
+
ext: _file.name.substring(_file.name.toLowerCase().lastIndexOf('.') + 1),
|
|
145
|
+
mimeType: _file.mimeType,
|
|
146
|
+
key,
|
|
147
|
+
path,
|
|
148
|
+
bucketName: bucket.bucketName
|
|
149
|
+
};
|
|
150
|
+
if (_file.public)
|
|
151
|
+
dbAsset.public = _file.public;
|
|
152
|
+
const dbTempMeta = await ModuleBE_AssetsTemp.set.item(dbAsset);
|
|
153
|
+
const fileWrapper = await bucket.getFile(dbTempMeta.path);
|
|
154
|
+
const url = await fileWrapper.getWriteSignedUrl(_file.mimeType, Hour);
|
|
155
|
+
return {
|
|
156
|
+
signedUrl: url.signedUrl,
|
|
157
|
+
asset: dbTempMeta
|
|
158
|
+
};
|
|
159
|
+
}));
|
|
160
|
+
};
|
|
161
|
+
processAssetManually = async (feId) => {
|
|
162
|
+
let query = { limit: 1 };
|
|
163
|
+
if (feId)
|
|
164
|
+
query = { where: { feId } };
|
|
165
|
+
const unprocessedFiles = await ModuleBE_AssetsTemp.query.custom(query);
|
|
166
|
+
return Promise.all(unprocessedFiles.map(asset => this.__processAsset(asset.path)));
|
|
167
|
+
};
|
|
168
|
+
__processAsset = async (filePath) => {
|
|
169
|
+
if (!filePath)
|
|
170
|
+
throw new MUSTNeverHappenException('Missing file path');
|
|
171
|
+
if (!filePath.match(this.config.pathRegexp))
|
|
172
|
+
return this.logVerbose(`File was added to storage in path: ${filePath}, NOT via file uploader`);
|
|
173
|
+
this.logDebug(`Looking for file with path: ${filePath}`);
|
|
174
|
+
let dbTempAsset;
|
|
175
|
+
try {
|
|
176
|
+
dbTempAsset = await ModuleBE_AssetsTemp.query.uniqueWhere({ path: filePath });
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (!dbTempAsset)
|
|
182
|
+
throw new ThisShouldNotHappenException(`Could not find meta for file with path: ${filePath}`);
|
|
183
|
+
await this.notifyFrontend(FileStatus.Processing, dbTempAsset);
|
|
184
|
+
this.logDebug(`Found temp meta with _id: ${dbTempAsset._id}`, dbTempAsset);
|
|
185
|
+
const validationConfig = this.fileValidator[dbTempAsset.key];
|
|
186
|
+
if (!validationConfig)
|
|
187
|
+
return this.notifyFrontend(FileStatus.ErrorNoConfig, dbTempAsset);
|
|
188
|
+
let mimetypeValidator = DefaultMimetypeValidator;
|
|
189
|
+
if (validationConfig.validator)
|
|
190
|
+
mimetypeValidator = validationConfig.validator;
|
|
191
|
+
if (!mimetypeValidator && validationConfig.fileType && validationConfig.fileType.includes(dbTempAsset.mimeType))
|
|
192
|
+
mimetypeValidator = this.mimeTypeValidator[dbTempAsset.mimeType];
|
|
193
|
+
if (!mimetypeValidator)
|
|
194
|
+
return this.notifyFrontend(FileStatus.ErrorNoValidator, dbTempAsset);
|
|
195
|
+
const file = await ModuleBE_AssetsStorage.getFile(dbTempAsset);
|
|
196
|
+
try {
|
|
197
|
+
const metadata = (await file.getMetadata());
|
|
198
|
+
if (!metadata)
|
|
199
|
+
return this.notifyFrontend(FileStatus.ErrorRetrievingMetadata, dbTempAsset);
|
|
200
|
+
await fileSizeValidator(file, metadata, validationConfig.minSize, validationConfig.maxSize);
|
|
201
|
+
const fileType = await mimetypeValidator(file, dbTempAsset);
|
|
202
|
+
dbTempAsset.md5Hash = metadata.md5Hash;
|
|
203
|
+
if (fileType && dbTempAsset.ext !== fileType.ext) {
|
|
204
|
+
this.logWarning(`renaming the file extension name: ${dbTempAsset.ext} => ${fileType.ext}`);
|
|
205
|
+
dbTempAsset.ext = fileType.ext;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch (e) {
|
|
209
|
+
//TODO delete the file and the temp doc
|
|
210
|
+
this.logError(`Error while processing asset: ${dbTempAsset.name}`, e);
|
|
211
|
+
return this.notifyFrontend(FileStatus.ErrorWhileProcessing, dbTempAsset);
|
|
212
|
+
}
|
|
213
|
+
if (dbTempAsset.public) {
|
|
214
|
+
try {
|
|
215
|
+
// need to handle the response status!
|
|
216
|
+
await file.makePublic();
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
return this.notifyFrontend(FileStatus.ErrorMakingPublic, dbTempAsset);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const finalDbAsset = await this.runTransaction(async (transaction) => {
|
|
223
|
+
const duplicatedAssets = await this.query.custom({ where: { md5Hash: dbTempAsset.md5Hash } }, transaction);
|
|
224
|
+
if (duplicatedAssets.length && duplicatedAssets[0]) {
|
|
225
|
+
this.logWarning(`${dbTempAsset.feId} is a duplicated entry for ${duplicatedAssets[0]._id}`);
|
|
226
|
+
return { ...duplicatedAssets[0], feId: dbTempAsset.feId };
|
|
227
|
+
}
|
|
228
|
+
const doc = this.collection.doc.item(dbTempAsset);
|
|
229
|
+
await ModuleBE_AssetsTemp.delete.unique(dbTempAsset._id, transaction);
|
|
230
|
+
return await doc.set(dbTempAsset, transaction);
|
|
231
|
+
});
|
|
232
|
+
return this.notifyFrontend(FileStatus.Completed, finalDbAsset);
|
|
233
|
+
};
|
|
234
|
+
notifyFrontend = async (status, asset, feId) => {
|
|
235
|
+
if (status !== FileStatus.Completed && status !== FileStatus.Processing) {
|
|
236
|
+
const message = `Error while processing asset: ${status}\n Failed on \n Asset: ${asset.feId}\n Key: ${asset.key}\n Type: ${asset.mimeType}\n File: ${asset.name}`;
|
|
237
|
+
throw new ApiException(500, message);
|
|
238
|
+
}
|
|
239
|
+
this.logDebug(`notify FE about asset ${feId}: ${status}`);
|
|
240
|
+
return PushMessageBE_FileUploadStatus.push({ status, asset }, { feId: feId || asset.feId });
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
export const ModuleBE_AssetsDB = new ModuleBE_AssetsDB_Class();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DBProto_AssetsDeleted } from '@nu-art/file-upload-shared';
|
|
2
|
+
import { ModuleBE_BaseDB } from '@nu-art/thunderstorm-backend';
|
|
3
|
+
export declare class ModuleBE_AssetsDeleted_Class extends ModuleBE_BaseDB<DBProto_AssetsDeleted> {
|
|
4
|
+
constructor();
|
|
5
|
+
}
|
|
6
|
+
export declare const ModuleBE_AssetsDeleted: ModuleBE_AssetsDeleted_Class;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Permissions management system, define access level for each of
|
|
3
|
+
* your server apis, and restrict users by giving them access levels
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { DBDef_TempDeleted } from '@nu-art/file-upload-shared';
|
|
20
|
+
import { ModuleBE_BaseDB } from '@nu-art/thunderstorm-backend';
|
|
21
|
+
export class ModuleBE_AssetsDeleted_Class extends ModuleBE_BaseDB {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(DBDef_TempDeleted);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export const ModuleBE_AssetsDeleted = new ModuleBE_AssetsDeleted_Class();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OnSyncEnvCompleted } from '@nu-art/thunderstorm-backend';
|
|
2
|
+
import { Module, TypedMap } from '@nu-art/ts-common';
|
|
3
|
+
import { StorageWrapperBE } from '@nu-art/firebase-backend';
|
|
4
|
+
import { DB_Asset } from '@nu-art/file-upload-shared';
|
|
5
|
+
type Config = {
|
|
6
|
+
batchItemCount: number;
|
|
7
|
+
};
|
|
8
|
+
export declare class ModuleBE_AssetsStorage_Class extends Module<Config> implements OnSyncEnvCompleted {
|
|
9
|
+
readonly storage: StorageWrapperBE;
|
|
10
|
+
constructor();
|
|
11
|
+
init(): void;
|
|
12
|
+
__onSyncEnvCompleted(env: string, baseUrl: string, requiredHeaders: TypedMap<string>): Promise<void>;
|
|
13
|
+
getReadSignedUrl: (dbAsset: DB_Asset) => Promise<string>;
|
|
14
|
+
getFile: (dbAsset: DB_Asset) => Promise<import("@nu-art/firebase-backend").FileWrapper>;
|
|
15
|
+
}
|
|
16
|
+
export declare const ModuleBE_AssetsStorage: ModuleBE_AssetsStorage_Class;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Permissions management system, define access level for each of
|
|
3
|
+
* your server apis, and restrict users by giving them access levels
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { AxiosHttpModule } from '@nu-art/thunderstorm-backend';
|
|
20
|
+
import { filterInstances, Module, NotImplementedYetException } from '@nu-art/ts-common';
|
|
21
|
+
import { ModuleBE_Firebase } from '@nu-art/firebase-backend';
|
|
22
|
+
import { ApiDef_Assets } from '@nu-art/file-upload-shared';
|
|
23
|
+
import { HttpMethod } from '@nu-art/thunderstorm-shared';
|
|
24
|
+
import { ModuleBE_AssetsDB } from './ModuleBE_AssetsDB.js';
|
|
25
|
+
export class ModuleBE_AssetsStorage_Class extends Module {
|
|
26
|
+
storage;
|
|
27
|
+
constructor() {
|
|
28
|
+
super();
|
|
29
|
+
this.setDefaultConfig({ batchItemCount: 10 });
|
|
30
|
+
}
|
|
31
|
+
init() {
|
|
32
|
+
super.init();
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
this.storage = ModuleBE_Firebase.createAdminSession().getStorage();
|
|
35
|
+
}
|
|
36
|
+
async __onSyncEnvCompleted(env, baseUrl, requiredHeaders) {
|
|
37
|
+
this.logWarning('Not Implemented Yet', new NotImplementedYetException('Sync assets not implemented'));
|
|
38
|
+
let assetsToSync = [];
|
|
39
|
+
let page = 0;
|
|
40
|
+
const itemsCount = this.config.batchItemCount;
|
|
41
|
+
let dbAssets;
|
|
42
|
+
do {
|
|
43
|
+
dbAssets = await ModuleBE_AssetsDB.query.custom({ limit: { page: page++, itemsCount } });
|
|
44
|
+
if (dbAssets.length === 0)
|
|
45
|
+
break;
|
|
46
|
+
assetsToSync = filterInstances(await Promise.all(dbAssets.map(async (dbAsset) => {
|
|
47
|
+
const fileWrapper = await this.getFile(dbAsset);
|
|
48
|
+
if (await fileWrapper.exists())
|
|
49
|
+
return;
|
|
50
|
+
return dbAsset;
|
|
51
|
+
})));
|
|
52
|
+
if (assetsToSync.length > 0)
|
|
53
|
+
continue;
|
|
54
|
+
assetsToSync.map(async (dbAsset) => {
|
|
55
|
+
let _signedUrl;
|
|
56
|
+
try {
|
|
57
|
+
const { signedUrl } = await AxiosHttpModule
|
|
58
|
+
.createRequest({ ...ApiDef_Assets.vv1.getReadSignedUrl, baseUrl, })
|
|
59
|
+
.setHeaders(requiredHeaders)
|
|
60
|
+
.setBodyAsJson({ assetId: dbAsset._id })
|
|
61
|
+
.executeSync();
|
|
62
|
+
_signedUrl = signedUrl;
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
console.log(e);
|
|
66
|
+
}
|
|
67
|
+
const fileContent = await AxiosHttpModule.createRequest({ method: HttpMethod.GET, fullUrl: _signedUrl, path: '' })
|
|
68
|
+
.setResponseType('text')
|
|
69
|
+
.executeSync();
|
|
70
|
+
await (await this.getFile(dbAsset)).write(fileContent);
|
|
71
|
+
});
|
|
72
|
+
} while (dbAssets.length > 0);
|
|
73
|
+
}
|
|
74
|
+
getReadSignedUrl = async (dbAsset) => (await (await this.getFile(dbAsset)).getReadSignedUrl()).signedUrl;
|
|
75
|
+
getFile = async (dbAsset) => this.storage.getFile(dbAsset.path, dbAsset.bucketName);
|
|
76
|
+
}
|
|
77
|
+
export const ModuleBE_AssetsStorage = new ModuleBE_AssetsStorage_Class();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DBProto_AssetsTemp } from '@nu-art/file-upload-shared';
|
|
2
|
+
import { ModuleBE_BaseDB } from '@nu-art/thunderstorm-backend';
|
|
3
|
+
export declare class ModuleBE_AssetsTemp_Class extends ModuleBE_BaseDB<DBProto_AssetsTemp> {
|
|
4
|
+
constructor();
|
|
5
|
+
}
|
|
6
|
+
export declare const ModuleBE_AssetsTemp: ModuleBE_AssetsTemp_Class;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Permissions management system, define access level for each of
|
|
3
|
+
* your server apis, and restrict users by giving them access levels
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { DBDef_TempAssets } from '@nu-art/file-upload-shared';
|
|
20
|
+
import { ModuleBE_BaseDB } from '@nu-art/thunderstorm-backend';
|
|
21
|
+
export class ModuleBE_AssetsTemp_Class extends ModuleBE_BaseDB {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(DBDef_TempAssets);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export const ModuleBE_AssetsTemp = new ModuleBE_AssetsTemp_Class();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ModuleBE_StorageListener } from '@nu-art/firebase-backend';
|
|
2
|
+
import { DefaultDef_ServiceAccount, RequiresServiceAccount, ServiceAccountCredentials } from '@nu-art/thunderstorm-backend/modules/_tdb/service-accounts';
|
|
3
|
+
import { StorageEvent } from 'firebase-functions/storage';
|
|
4
|
+
export interface OnAssetUploaded {
|
|
5
|
+
__processAsset(filePath?: string): void;
|
|
6
|
+
}
|
|
7
|
+
type Config = ServiceAccountCredentials & {};
|
|
8
|
+
export declare class ModuleBE_BucketListener_Class extends ModuleBE_StorageListener<Config> implements RequiresServiceAccount {
|
|
9
|
+
constructor();
|
|
10
|
+
onFinalize(event: StorageEvent): Promise<any>;
|
|
11
|
+
__requiresServiceAccount(): DefaultDef_ServiceAccount;
|
|
12
|
+
}
|
|
13
|
+
export declare const ModuleBE_BucketListener: ModuleBE_BucketListener_Class;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A backend boilerplate with example apis
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
import { BadImplementationException, Dispatcher } from '@nu-art/ts-common';
|
|
19
|
+
import { MemStorage } from '@nu-art/ts-common/mem-storage/MemStorage';
|
|
20
|
+
import { ModuleBE_StorageListener } from '@nu-art/firebase-backend';
|
|
21
|
+
import { PermissionsGroup_PushMessanger } from '@nu-art/push-pub-sub-backend/core/permissions';
|
|
22
|
+
import { MemKey_AccountId } from '@nu-art/user-account-backend';
|
|
23
|
+
const dispatcher_onAssetUploaded = new Dispatcher('__processAsset');
|
|
24
|
+
export class ModuleBE_BucketListener_Class extends ModuleBE_StorageListener {
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
27
|
+
}
|
|
28
|
+
async onFinalize(event) {
|
|
29
|
+
// need to create a dispatch that collects a list of services that requires service account and
|
|
30
|
+
// service account details, the permissions create project will create these account for the rest of the system ;
|
|
31
|
+
return new MemStorage().init(async () => {
|
|
32
|
+
const accountId = this.config.serviceAccount.accountId;
|
|
33
|
+
if (!accountId)
|
|
34
|
+
throw new BadImplementationException('Need to perform project setup to setup this feature');
|
|
35
|
+
MemKey_AccountId.set(accountId);
|
|
36
|
+
let filePath = event.data.name || '';
|
|
37
|
+
if (filePath.endsWith('}'))
|
|
38
|
+
filePath = filePath.substring(0, filePath.length - 1);
|
|
39
|
+
this.logInfo(`File was added to bucket: ${filePath}`);
|
|
40
|
+
await dispatcher_onAssetUploaded.dispatchModuleAsync(filePath);
|
|
41
|
+
this.logDebug('Object is ', event.data);
|
|
42
|
+
this.logDebug('event is ', event);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
__requiresServiceAccount() {
|
|
46
|
+
const serviceAccount = {
|
|
47
|
+
moduleName: this.getName(),
|
|
48
|
+
email: 'bucket-manager@nu-art-software.com',
|
|
49
|
+
groupIds: [PermissionsGroup_PushMessanger._id]
|
|
50
|
+
};
|
|
51
|
+
return serviceAccount;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export const ModuleBE_BucketListener = new ModuleBE_BucketListener_Class();
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nu-art/file-upload-backend",
|
|
3
|
+
"version": "0.400.7",
|
|
4
|
+
"description": "File Uploader - Express & Typescript based backend framework Backend",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"TacB0sS",
|
|
7
|
+
"infra",
|
|
8
|
+
"nu-art",
|
|
9
|
+
"storm",
|
|
10
|
+
"thunderstorm",
|
|
11
|
+
"typescript"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/nu-art-js/file-upload",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/nu-art-js/file-upload/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+ssh://git@github.com:nu-art-js/file-upload.git"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"directory": "dist",
|
|
23
|
+
"linkDirectory": true
|
|
24
|
+
},
|
|
25
|
+
"license": "Apache-2.0",
|
|
26
|
+
"author": "TacB0sS",
|
|
27
|
+
"files": [
|
|
28
|
+
"**/*"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@nu-art/file-upload-shared": "0.400.7",
|
|
35
|
+
"@google-cloud/common": "^5.0.2",
|
|
36
|
+
"@google-cloud/firestore": "^7.11.0",
|
|
37
|
+
"@google-cloud/storage": "^7.15.0",
|
|
38
|
+
"@nu-art/firebase-backend": "0.400.7",
|
|
39
|
+
"@nu-art/firebase-shared": "0.400.7",
|
|
40
|
+
"@nu-art/permissions-backend": "0.400.7",
|
|
41
|
+
"@nu-art/permissions-shared": "0.400.7",
|
|
42
|
+
"@nu-art/push-pub-sub-backend": "0.400.7",
|
|
43
|
+
"@nu-art/push-pub-sub-shared": "0.400.7",
|
|
44
|
+
"@nu-art/thunderstorm-backend": "0.400.7",
|
|
45
|
+
"@nu-art/thunderstorm-shared": "0.400.7",
|
|
46
|
+
"@nu-art/ts-common": "0.400.7",
|
|
47
|
+
"@nu-art/user-account-backend": "0.400.7",
|
|
48
|
+
"@nu-art/user-account-shared": "0.400.7",
|
|
49
|
+
"express": "^4.18.2",
|
|
50
|
+
"file-type": "^21.0.0",
|
|
51
|
+
"firebase": "^11.9.0",
|
|
52
|
+
"firebase-admin": "13.4.0",
|
|
53
|
+
"firebase-functions": "6.3.2",
|
|
54
|
+
"google-auth-library": "^10.0.0",
|
|
55
|
+
"jszip": "^3.2.2",
|
|
56
|
+
"react": "^18.0.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/react": "^18.0.0",
|
|
60
|
+
"@types/compression": "^1.0.1",
|
|
61
|
+
"@types/express": "^4.17.17"
|
|
62
|
+
},
|
|
63
|
+
"unitConfig": {
|
|
64
|
+
"type": "typescript-lib"
|
|
65
|
+
},
|
|
66
|
+
"type": "module",
|
|
67
|
+
"exports": {
|
|
68
|
+
".": {
|
|
69
|
+
"types": "./index.d.ts",
|
|
70
|
+
"import": "./index.js"
|
|
71
|
+
},
|
|
72
|
+
"./*": {
|
|
73
|
+
"types": "./*.d.ts",
|
|
74
|
+
"import": "./*.js"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|