Skip to content

Commit

Permalink
Added uuid aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
willbrowningme committed Aug 1, 2019
1 parent c797993 commit 1433805
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 7 deletions.
1 change: 1 addition & 0 deletions app/Alias.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Alias extends Model
];

protected $fillable = [
'id',
'active',
'description',
'email',
Expand Down
8 changes: 4 additions & 4 deletions app/Console/Commands/ReceiveEmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ public function handle()
$user = $customDomain->user;
}

// TODO add check here for uuid pre-generated aliases e.g. [email protected]

// Check if this is the root domain e.g. anonaddy.me
if ($recipient['domain'] === $parentDomain && !empty(config('anonaddy.admin_username'))) {
// check if this is a uuid generated alias
if ($alias = Alias::find($recipient['local_part'])) {
$user = $alias->user;
} elseif ($recipient['domain'] === $parentDomain && !empty(config('anonaddy.admin_username'))) {
$user = User::where('username', config('anonaddy.admin_username'))->first();
}
}
Expand Down
19 changes: 19 additions & 0 deletions app/Http/Controllers/AliasController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Http\Requests\UpdateAliasRequest;
use App\Http\Resources\AliasResource;
use Ramsey\Uuid\Uuid;

class AliasController extends Controller
{
Expand All @@ -21,6 +22,24 @@ public function index()
]);
}

public function store()
{
if (user()->hasExceededNewAliasLimit()) {
return response('', 429);
}

$uuid = Uuid::uuid4();

$alias = user()->aliases()->create([
'id' => $uuid,
'email' => $uuid . '@anonaddy.me',
'local_part' => $uuid,
'domain' => 'anonaddy.me'
]);

return new AliasResource($alias->fresh());
}

public function update(UpdateAliasRequest $request, $id)
{
$alias = user()->aliases()->findOrFail($id);
Expand Down
3 changes: 3 additions & 0 deletions app/Http/Resources/AliasResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ public function toArray($request)
'id' => $this->id,
'user_id' => $this->user_id,
'domain_id' => $this->domain_id,
'local_part' => $this->local_part,
'extension' => $this->extension,
'domain' => $this->domain,
'email' => $this->email,
'active' => $this->active,
'description' => $this->description,
Expand Down
74 changes: 72 additions & 2 deletions resources/js/pages/Aliases.vue
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@
class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current pointer-events-none mr-2 flex items-center"
/>
</div>
<div class="mt-4 md:mt-0">
<button
@click="generateAliasModalOpen = true"
class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none ml-auto"
>
Generate New Alias
</button>
</div>
</div>
<div class="bg-white rounded shadow overflow-x-auto">
<table v-if="initialAliases.length" class="w-full whitespace-no-wrap">
Expand Down Expand Up @@ -299,10 +307,10 @@
v-clipboard:error="clipboardError"
>
<span class="font-semibold text-indigo-800">{{
alias.local_part | truncate(20)
alias.local_part | truncate(25)
}}</span>
<span class="block text-grey-400 text-sm">{{
getAliasEmail(alias) | truncate(35)
getAliasEmail(alias) | truncate(40)
}}</span>
</span>
</div>
Expand Down Expand Up @@ -469,6 +477,40 @@
</div>
</div>

<Modal :open="generateAliasModalOpen" @close="generateAliasModalOpen = false">
<div class="max-w-lg w-full bg-white rounded-lg shadow-2xl p-6">
<h2
class="font-semibold text-grey-900 text-2xl leading-tight border-b-2 border-grey-100 pb-4"
>
Generate new UUID alias
</h2>
<p class="mt-4 text-grey-700">
This will generate a new unique alias in the form of<br /><br />
[email protected]<br /><br />
Useful if you do not wish to include your username in the email as a potential link
between aliases.<br /><br />
Other aliases e.g. alias@{{ domain }} or .me are created automatically when they receive
their first email.
</p>
<div class="mt-6">
<button
@click="generateNewAlias"
class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
:class="generateAliasLoading ? 'cursor-not-allowed' : ''"
:disabled="generateAliasLoading"
>
Generate Alias
</button>
<button
@click="generateAliasModalOpen = false"
class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
>
Cancel
</button>
</div>
</div>
</Modal>

<Modal :open="editAliasRecipientsModalOpen" @close="closeAliasRecipientsModal">
<div class="max-w-lg w-full bg-white rounded-lg shadow-2xl px-6 py-6">
<h2
Expand Down Expand Up @@ -615,6 +657,8 @@ export default {
currentSortDir: 'desc',
editAliasRecipientsLoading: false,
editAliasRecipientsModalOpen: false,
generateAliasModalOpen: false,
generateAliasLoading: false,
recipientsAliasToEdit: {},
aliasRecipientsToEdit: [],
}
Expand Down Expand Up @@ -689,6 +733,9 @@ export default {
this.aliases = _.orderBy(this.aliases, [this.currentSort], [this.currentSortDir])
},
reSort() {
this.aliases = _.orderBy(this.aliases, [this.currentSort], [this.currentSortDir])
},
openAliasRecipientsModal(alias) {
this.editAliasRecipientsModalOpen = true
this.recipientsAliasToEdit = alias
Expand Down Expand Up @@ -731,6 +778,29 @@ export default {
this.error()
})
},
generateNewAlias() {
this.generateAliasLoading = true
axios
.post('/aliases', JSON.stringify({}), {
headers: { 'Content-Type': 'application/json' },
})
.then(({ data }) => {
this.generateAliasLoading = false
this.aliases.push(data.data)
this.reSort()
this.generateAliasModalOpen = false
this.success('New alias generated successfully')
})
.catch(error => {
this.generateAliasLoading = false
if (error.response.status === 429) {
this.error('You have reached your hourly limit for creating new aliases')
} else {
this.error()
}
})
},
editAlias(alias) {
if (this.aliasDescriptionToEdit.length > 100) {
return this.error('Description cannot be more than 100 characters')
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/Recipients.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
:data-tippy-content="
`Use this to attach recipients to new aliases as they are created e.g. alias+key@${
user.username
}.anonaddy.com. You can attach multiple recipients by doing alias+2.3@${
}.anonaddy.com. You can attach multiple recipients by doing alias+2.3.4@${
user.username
}.anonaddy.com`
"
Expand Down
1 change: 1 addition & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

Route::middleware(['auth', 'verified', '2fa'])->group(function () {
Route::get('/', 'AliasController@index')->name('aliases.index');
Route::post('/aliases', 'AliasController@store')->name('aliases.store');
Route::patch('/aliases/{id}', 'AliasController@update')->name('aliases.update');
Route::delete('/aliases/{id}', 'AliasController@destroy')->name('aliases.destroy');

Expand Down
10 changes: 10 additions & 0 deletions tests/Feature/AliasesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ public function aliases_are_listed_with_only_verified_recipient_options()
$this->assertEquals($aliasRecipient->recipient->email, $response->data('recipients')[0]['email']);
}

/** @test */
public function user_can_generate_new_alias()
{
$response = $this->json('POST', '/aliases', []);

$response->assertStatus(200);
$this->assertCount(1, $this->user->aliases);
$this->assertEquals($this->user->aliases[0]->email, $response->getData()->data->email);
}

/** @test */
public function user_can_activate_alias()
{
Expand Down
55 changes: 55 additions & 0 deletions tests/Feature/ReceiveEmailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,61 @@ public function it_can_forward_email_with_existing_alias()
});
}

/** @test */
public function it_can_forward_email_with_uuid_generated_alias()
{
Mail::fake();

Mail::assertNothingSent();

$uuid = '86064c92-da41-443e-a2bf-5a7b0247842f';

config([
'anonaddy.admin_username' => 'random'
]);

factory(Alias::class)->create([
'id' => $uuid,
'user_id' => $this->user->id,
'email' => $uuid.'@anonaddy.me',
'local_part' => $uuid,
'domain' => 'anonaddy.me',
]);

$defaultRecipient = $this->user->defaultRecipient;

$this->artisan(
'anonaddy:receive-email',
[
'file' => base_path('tests/emails/email_with_uuid.eml'),
'--sender' => '[email protected]',
'--recipient' => [$uuid.'@anonaddy.me'],
'--local_part' => [$uuid],
'--extension' => [''],
'--domain' => ['anonaddy.me'],
'--size' => '892'
]
)->assertExitCode(0);

$this->assertDatabaseHas('aliases', [
'local_part' => $uuid,
'domain' => 'anonaddy.me',
'email' => $uuid.'@anonaddy.me',
'emails_forwarded' => 1,
'emails_blocked' => 0
]);
$this->assertDatabaseHas('users', [
'id' => $this->user->id,
'username' => 'johndoe',
'bandwidth' => '892'
]);
$this->assertCount(1, $this->user->aliases);

Mail::assertQueued(ForwardEmail::class, function ($mail) use ($defaultRecipient) {
return $mail->hasTo($defaultRecipient->email);
});
}

/** @test */
public function it_can_forward_email_with_existing_alias_and_receipients()
{
Expand Down
28 changes: 28 additions & 0 deletions tests/emails/email_with_uuid.eml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Date: Wed, 20 Feb 2019 15:00:00 +0100 (CET)
From: Will <[email protected]>
To: <[email protected]>
Subject: Test Email
Content-Type: multipart/mixed; boundary="----=_Part_10031_1199410393.1550677940425"

------=_Part_10031_1199410393.1550677940425
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Hi,<br>
<br>
This is a test email.<br>
<br>
Will


------=_Part_10031_1199410393.1550677940425
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hi,
This is a test email.
Will
------=_Part_10031_1199410393.1550677940425--

0 comments on commit 1433805

Please sign in to comment.