From b0bfe891cd68872f3556708c07e6af5fd069252d Mon Sep 17 00:00:00 2001 From: Trym Lund Flogard Date: Wed, 2 Jun 2021 15:48:35 +0200 Subject: [PATCH] add auth, sharing --- action.yml | 6 +++++ package-lock.json | 14 ++++++++++ package.json | 2 ++ src/Inputs.ts | 8 ++++++ src/nextcloud/NextcloudClient.ts | 44 ++++++++++++++++++++++++++------ 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/action.yml b/action.yml index ba7c54f..639ec0c 100644 --- a/action.yml +++ b/action.yml @@ -11,6 +11,12 @@ inputs: nextcloud-url: description: 'The URL for the nextcloud server' required: true + nextcloud-username: + description: 'The username for the nextcloud user' + required: true + nextcloud-password: + description: 'The password for the nextcloud user' + required: true if-no-files-found: description: > The desired behavior if no files are found using the provided path. diff --git a/package-lock.json b/package-lock.json index d4a22dc..0dcbcd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,15 @@ "@types/glob": "*" } }, + "@types/btoa": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/btoa/-/btoa-1.2.3.tgz", + "integrity": "sha512-ANNCZICS/ofxhzUl8V1DniBJs+sFQ+Yg5am1ZwVEf/sxoKY/J2+h5Fuw3xUErlZ7eJLdgzukBjZwnsV6+/2Rmg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", @@ -146,6 +155,11 @@ "concat-map": "0.0.1" } }, + "btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==" + }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", diff --git a/package.json b/package.json index 85d6f21..fd0b0ff 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,12 @@ "@actions/core": "^1.3.0", "@actions/glob": "^0.1.2", "archiver": "^5.3.0", + "btoa": "^1.2.1", "node-fetch": "^2.6.1" }, "devDependencies": { "@types/archiver": "^5.1.0", + "@types/btoa": "^1.2.3", "@types/node": "^15.6.2", "@types/node-fetch": "^2.5.10", "typescript": "^4.3.2" diff --git a/src/Inputs.ts b/src/Inputs.ts index a66b16b..08f0ac1 100644 --- a/src/Inputs.ts +++ b/src/Inputs.ts @@ -18,6 +18,14 @@ export class Inputs { return core.getInput("nextcloud-url"); } + static get Username(): string { + return core.getInput("nextcloud-username"); + } + + static get Password(): string { + return core.getInput("nextcloud-password"); + } + static get NoFileBehvaior(): NoFileOption { const notFoundAction = core.getInput("if-no-files-found"); const noFileBehavior: NoFileOption = NoFileOption[notFoundAction as keyof typeof NoFileOption]; diff --git a/src/nextcloud/NextcloudClient.ts b/src/nextcloud/NextcloudClient.ts index 4516789..843f9ed 100644 --- a/src/nextcloud/NextcloudClient.ts +++ b/src/nextcloud/NextcloudClient.ts @@ -6,7 +6,9 @@ import * as os from 'os'; import { randomUUID } from 'crypto'; import * as archiver from 'archiver'; import { URL } from 'url'; -import fetch from 'node-fetch'; +import fetch, { HeadersInit } from 'node-fetch'; +import { Inputs } from '../Inputs'; +import btoa from 'btoa'; interface FileSpec { absolutePath: string, @@ -14,15 +16,22 @@ interface FileSpec { } export class NextcloudClient { + private guid: string; + private headers: HeadersInit; + public constructor( private endpoint: string, private artifact: string, - private rootDirectory: string) { } + private rootDirectory: string) { + this.guid = randomUUID(); + this.headers = {'Authorization': 'Basic ' + btoa(`${Inputs.Username}:${Inputs.Password}`)}; + } public async uploadFiles(files: string[]) { const spec = this.uploadSpec(files); var zip = await this.zipFiles(spec); - await this.upload(zip); + const path = await this.upload(zip); + await this.shareFile(path); } private uploadSpec(files: string[]): FileSpec[] { @@ -93,7 +102,7 @@ export class NextcloudClient { private async zipFiles(specs: FileSpec[]): Promise { - const tempArtifactDir = path.join(os.tmpdir(), randomUUID()); + const tempArtifactDir = path.join(os.tmpdir(), this.guid); const artifactPath = path.join(tempArtifactDir, `artifact-${this.artifact}`); await fs.mkdir(artifactPath, { recursive: true }); for (let spec of specs) { @@ -118,15 +127,34 @@ export class NextcloudClient { } private async upload(file: string) { - const url = new URL(this.endpoint, '/remote.php/dav/files/user/path/to/file'); + const filePath = `/artifacts/${this.guid}/${this.artifact}`; + const url = this.endpoint + `/remote.php/dav/files/${Inputs.Username}` + filePath; const stream = fsSync.createReadStream(file); - await fetch(url.href, { + const res = await fetch(url, { method: 'PUT', - body: stream + body: stream, + headers: this.headers }); + core.debug(await res.json()) + + return filePath; } - private shareFile() { + private async shareFile(nextcloudPath: string) { + const url = this.endpoint + `/ocs/v2.php/apps/files_sharing/api/v1/shares`; + const body = { + path: nextcloudPath, + shareType: 3, + publicUpload: "false", + permissions: 1, + }; + const res = await fetch(url, { + method: 'PUT', + headers: this.headers, + body: JSON.stringify(body), + }); + + core.debug(await res.json()) } } \ No newline at end of file