13 changed files with 260 additions and 7 deletions
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
FROM node |
||||
|
||||
RUN npm install http-server -g |
||||
EXPOSE 80 |
||||
|
||||
COPY entrypoint.sh / |
||||
RUN chmod +x /entrypoint.sh |
||||
ENTRYPOINT ["/entrypoint.sh"] |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
$dir = Split-Path -Parent $MyInvocation.MyCommand.Path |
||||
|
||||
echo "`n# Building Attachments" |
||||
|
||||
echo "`nBuilding docker image" |
||||
docker --version |
||||
docker build -t bitwarden/attachments $dir\. |
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash |
||||
set -e |
||||
|
||||
DIR="$(dirname $(readlink -f $0))" |
||||
|
||||
echo -e "\n# Building Attachments" |
||||
|
||||
echo -e "\nBuilding docker image" |
||||
docker --version |
||||
docker build -t bitwarden/attachments $DIR/. |
||||
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh |
||||
|
||||
http-server /etc/bitwarden/core/attachments/. -p 80 -d false --utc |
||||
|
||||
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
using System.Threading.Tasks; |
||||
using System.IO; |
||||
using System; |
||||
using Bit.Core.Models.Table; |
||||
|
||||
namespace Bit.Core.Services |
||||
{ |
||||
public class LocalAttachmentStorageService : IAttachmentStorageService |
||||
{ |
||||
private readonly string _baseDirPath; |
||||
private readonly string _baseTempDirPath; |
||||
|
||||
public LocalAttachmentStorageService( |
||||
GlobalSettings globalSettings) |
||||
{ |
||||
_baseDirPath = globalSettings.Attachment.BaseDirectory; |
||||
_baseTempDirPath = $"{_baseDirPath}/temp"; |
||||
} |
||||
|
||||
public async Task UploadNewAttachmentAsync(Stream stream, Cipher cipher, string attachmentId) |
||||
{ |
||||
await InitAsync(); |
||||
var cipherDirPath = $"{_baseDirPath}/{cipher.Id}"; |
||||
CreateDirectoryIfNotExists(cipherDirPath); |
||||
|
||||
using(var fs = File.Create($"{cipherDirPath}/{attachmentId}")) |
||||
{ |
||||
stream.Seek(0, SeekOrigin.Begin); |
||||
stream.CopyTo(fs); |
||||
} |
||||
} |
||||
|
||||
public async Task UploadShareAttachmentAsync(Stream stream, Guid cipherId, Guid organizationId, string attachmentId) |
||||
{ |
||||
await InitAsync(); |
||||
var tempCipherOrgDirPath = $"{_baseTempDirPath}/{cipherId}/{organizationId}"; |
||||
CreateDirectoryIfNotExists(tempCipherOrgDirPath); |
||||
|
||||
using(var fs = File.Create($"{tempCipherOrgDirPath}/{attachmentId}")) |
||||
{ |
||||
stream.Seek(0, SeekOrigin.Begin); |
||||
stream.CopyTo(fs); |
||||
} |
||||
} |
||||
|
||||
public async Task StartShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) |
||||
{ |
||||
await InitAsync(); |
||||
var sourceFilePath = $"{_baseTempDirPath}/{cipherId}/{organizationId}/{attachmentId}"; |
||||
if(!File.Exists(sourceFilePath)) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
var destFilePath = $"{_baseDirPath}/{cipherId}/{attachmentId}"; |
||||
if(!File.Exists(destFilePath)) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
var originalFilePath = $"{_baseTempDirPath}/{cipherId}/{attachmentId}"; |
||||
DeleteFileIfExists(originalFilePath); |
||||
|
||||
File.Move(destFilePath, originalFilePath); |
||||
DeleteFileIfExists(destFilePath); |
||||
|
||||
File.Move(sourceFilePath, destFilePath); |
||||
} |
||||
|
||||
public async Task RollbackShareAttachmentAsync(Guid cipherId, Guid organizationId, string attachmentId) |
||||
{ |
||||
await InitAsync(); |
||||
DeleteFileIfExists($"{_baseTempDirPath}/{cipherId}/{organizationId}/{attachmentId}"); |
||||
|
||||
var originalFilePath = $"{_baseTempDirPath}/{cipherId}/{attachmentId}"; |
||||
if(!File.Exists(originalFilePath)) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
var destFilePath = $"{_baseDirPath}/{cipherId}/{attachmentId}"; |
||||
DeleteFileIfExists(destFilePath); |
||||
|
||||
File.Move(originalFilePath, destFilePath); |
||||
DeleteFileIfExists(originalFilePath); |
||||
} |
||||
|
||||
public async Task DeleteAttachmentAsync(Guid cipherId, string attachmentId) |
||||
{ |
||||
await InitAsync(); |
||||
DeleteFileIfExists($"{_baseDirPath}/{cipherId}/{attachmentId}"); |
||||
} |
||||
|
||||
public async Task CleanupAsync(Guid cipherId) |
||||
{ |
||||
await InitAsync(); |
||||
DeleteDirectoryIfExists($"{_baseTempDirPath}/{cipherId}"); |
||||
} |
||||
|
||||
public async Task DeleteAttachmentsForCipherAsync(Guid cipherId) |
||||
{ |
||||
await InitAsync(); |
||||
DeleteDirectoryIfExists($"{_baseDirPath}/{cipherId}"); |
||||
} |
||||
|
||||
public async Task DeleteAttachmentsForOrganizationAsync(Guid organizationId) |
||||
{ |
||||
await InitAsync(); |
||||
} |
||||
|
||||
public async Task DeleteAttachmentsForUserAsync(Guid userId) |
||||
{ |
||||
await InitAsync(); |
||||
} |
||||
|
||||
private void DeleteFileIfExists(string path) |
||||
{ |
||||
if(File.Exists(path)) |
||||
{ |
||||
File.Delete(path); |
||||
} |
||||
} |
||||
|
||||
private void DeleteDirectoryIfExists(string path) |
||||
{ |
||||
if(Directory.Exists(path)) |
||||
{ |
||||
Directory.Delete(path, true); |
||||
} |
||||
} |
||||
|
||||
private void CreateDirectoryIfNotExists(string path) |
||||
{ |
||||
if(!Directory.Exists(path)) |
||||
{ |
||||
Directory.CreateDirectory(path); |
||||
} |
||||
} |
||||
|
||||
private Task InitAsync() |
||||
{ |
||||
if(!Directory.Exists(_baseDirPath)) |
||||
{ |
||||
Directory.CreateDirectory(_baseDirPath); |
||||
} |
||||
|
||||
if(!Directory.Exists(_baseTempDirPath)) |
||||
{ |
||||
Directory.CreateDirectory(_baseTempDirPath); |
||||
} |
||||
|
||||
return Task.FromResult(0); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue