Skip to content

Commit

Permalink
feat: documents (monicahq/chandler#159)
Browse files Browse the repository at this point in the history
  • Loading branch information
djaiss authored and asbiin committed Mar 31, 2023
1 parent 46f83e0 commit cbd923e
Show file tree
Hide file tree
Showing 70 changed files with 2,552 additions and 41 deletions.
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,15 @@ MEILISEARCH_KEY=
TELEGRAM_BOT_TOKEN=
TELEGRAM_BOT_URL=
TELEGRAM_BOT_WEBHOOK_URL=

# Default storage limit for accounts on this instance, in Mb
# 0 = unlimited
DEFAULT_STORAGE_LIMIT=50

# API key for uploading files
# We use Uploadcare (https://uploadcare.com) to upload and store all user
# generated files.
# Uploadcare is GDPR and all privacy laws compliant.
# It also provides a generous free plan.
UPLOADCARE_PUBLIC_KEY=
UPLOADCARE_PRIVATE_KEY=
9 changes: 9 additions & 0 deletions app/Exceptions/EnvVariablesNotSetException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace App\Exceptions;

use Exception;

class EnvVariablesNotSetException extends Exception
{
}
25 changes: 25 additions & 0 deletions app/Helpers/FileHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Helpers;

class FileHelper
{
/**
* Formats the file size to a human readable size.
*
* @param int $bytes
* @return string|null
*/
public static function formatFileSize(int $bytes): ?string
{
$units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
$step = 1024;
$i = 0;
while (($bytes / $step) > 0.9) {
$bytes = $bytes / $step;
$i++;
}

return round($bytes, 2) . $units[$i];
}
}
31 changes: 31 additions & 0 deletions app/Helpers/StorageHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace App\Helpers;

use App\Models\Account;
use App\Models\Contact;
use App\Models\File;

class StorageHelper
{
/**
* Indicate if the account can accept another file, depending on the account's
* limits.
*
* @param Account $account
* @return bool
*/
public static function canUploadFile(Account $account): bool
{
// get the file size of all the files in the account
// the size will be in bytes
$vaultIds = $account->vaults()->select('id')->get()->pluck('id')->toArray();
$contactIds = Contact::whereIn('vault_id', $vaultIds)->select('id')->get()->pluck('id')->toArray();

$totalSizeInBytes = File::whereIn('contact_id', $contactIds)->sum('size');

$accountLimit = $account->storage_limit_in_mb * 1024 * 1024;

return $totalSizeInBytes < $accountLimit;
}
}
17 changes: 16 additions & 1 deletion app/Jobs/SetupAccount.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use App\Models\Currency;
use App\Models\Emotion;
use App\Models\Information;
use App\Models\LifeEventCategory;
use App\Models\LifeEventType;
use App\Models\Module;
Expand Down Expand Up @@ -427,6 +426,22 @@ private function addTemplatePageInformation(): void
'can_be_deleted' => true,
]);

// Documents
$module = (new CreateModule())->execute([
'account_id' => $this->user->account_id,
'author_id' => $this->user->id,
'name' => trans('app.module_documents'),
'type' => Module::TYPE_DOCUMENTS,
'can_be_deleted' => false,
]);
(new AssociateModuleToTemplatePage())->execute([
'account_id' => $this->user->account_id,
'author_id' => $this->user->id,
'template_id' => $this->template->id,
'template_page_id' => $templatePageInformation->id,
'module_id' => $module->id,
]);

// Notes
$module = (new CreateModule())->execute([
'account_id' => $this->user->account_id,
Expand Down
19 changes: 19 additions & 0 deletions app/Models/Account.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ class Account extends Model
{
use HasFactory;

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'storage_limit_in_mb',
];

/**
* Get the users associated with the account.
*
Expand Down Expand Up @@ -182,4 +191,14 @@ public function giftStates(): HasMany
{
return $this->hasMany(GiftState::class);
}

/**
* Get the vaults associated with the account.
*
* @return HasMany
*/
public function vaults(): HasMany
{
return $this->hasMany(Vault::class);
}
}
10 changes: 10 additions & 0 deletions app/Models/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,16 @@ public function goals(): HasMany
return $this->hasMany(Goal::class);
}

/**
* Get the files associated with the contact.
*
* @return HasMany
*/
public function files(): HasMany
{
return $this->hasMany(File::class);
}

/**
* Get the groups associated with the contact.
*
Expand Down
57 changes: 57 additions & 0 deletions app/Models/File.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace App\Models;

use App\Contact\ManageDocuments\Events\FileDeleted;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class File extends Model
{
use HasFactory;

protected $table = 'files';

/**
* Possible type.
*/
public const TYPE_DOCUMENT = 'document';
public const TYPE_AVATAR = 'avatar';
public const TYPE_PHOTO = 'photo';

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'contact_id',
'uuid',
'original_url',
'cdn_url',
'name',
'mime_type',
'type',
'size',
];

/**
* The event map for the model.
*
* @var array
*/
protected $dispatchesEvents = [
'deleted' => FileDeleted::class,
];

/**
* Get the contact associated with the file.
*
* @return BelongsTo
*/
public function contact(): BelongsTo
{
return $this->belongsTo(Contact::class);
}
}
1 change: 1 addition & 0 deletions app/Models/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Module extends Model
public const TYPE_ADDRESSES = 'addresses';
public const TYPE_GROUPS = 'groups';
public const TYPE_CONTACT_INFORMATION = 'contact_information';
public const TYPE_DOCUMENTS = 'documents';

/**
* The attributes that are mass assignable.
Expand Down
5 changes: 5 additions & 0 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Providers;

use App\Contact\ManageDocuments\Events\FileDeleted;
use App\Contact\ManageDocuments\Listeners\DeleteFileInStorage;
use App\Listeners\LocaleUpdatedListener;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
Expand All @@ -23,6 +25,9 @@ class EventServiceProvider extends ServiceProvider
LocaleUpdated::class => [
LocaleUpdatedListener::class,
],
FileDeleted::class => [
DeleteFileInStorage::class,
],
];

/**
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"laravel/tinker": "^2.5",
"meilisearch/meilisearch-php": "^0.23.2",
"tightenco/ziggy": "^1.0",
"uploadcare/uploadcare-php": "^3.0",
"vluzrmos/language-detector": "^2.3"
},
"require-dev": {
Expand Down
Loading

0 comments on commit cbd923e

Please sign in to comment.