Browse Source

Added domain default recipient option

Will Browning 5 years ago
parent
commit
4bdeb4ca8c

+ 14 - 19
README.md

@@ -19,17 +19,14 @@ I made the code open-source to show everyone what was going on behind the scenes
 
 I use this service myself for the vast majority of sites I'm signed up to.
 
-
 #### **Do you store emails?**
 
 No I definitely do not store/save any emails that pass through the server.
 
-
 #### **Can I use my own domain?**
 
 Yes you can use your own domain name so you can also have *@example.com as your aliases. To do so you simply need to add an MX record to your domain so that our server can handle incoming emails.
 
-
 #### **Why should I use this instead of a similar service?**
 
 Here are a few reasons I can think of:
@@ -46,7 +43,6 @@ Here are a few reasons I can think of:
 * Ability to add additional usernames to compartmentalise aliases
 * New features added regularly
 
-
 #### **How do I add my own GPG/OpenPGP key for encryption?**
 
 On the recipients page you simply need to click "Add public key" and paste in your **public** key data. Now all emails forwarded to you will be encrypted with your key. You should also replace the subject line of forwarded messages in your account settings as this cannot be encrypted.
@@ -63,7 +59,6 @@ You can add this key to your own keyring so that you can verify emails have come
 
 The fingerprint of the mailer@anonaddy.me key is "26A987650243B28802524E2F809FD0D502E2F695" you can find the key on [https://keys.openpgp.org](https://keys.openpgp.org/search?q=26A987650243B28802524E2F809FD0D502E2F695).
 
-
 #### **What if I don't want anyone to link ownership of my aliases together?**
 
 If you're concerned that your aliases are all linked by your username e.g. @johndoe.anonaddy.com, then you have a couple of options:
@@ -71,22 +66,18 @@ If you're concerned that your aliases are all linked by your username e.g. @john
 1. You can generate UUID aliases instead, these are all under the root domain and cannot be linked to a user.
 2. You can add additional usernames and separate your aliases under your these. e.g. you could have one username for personal stuff, another for work, another for hobbies etc.
 
-
 #### **Where is the server located?**
 
 The server is located in Amsterdam, Netherlands with [Greenhost.net](https://greenhost.net/). Greenhost focuses greatly on privacy and security and their servers run entirely on Dutch wind energy.
 
-
 #### **What if I don't trust you?**
 
 It's good to keep your guard up when online so you should never trust anyone 100%. I'll try my best to be as honest and transparent as I can but if you still aren't convinced you can always just fire up your own server and self-host this application. You'll need to know about server administration and PHP. I'll be adding more details on how to do this soon.
 
-
 #### **What is the maximum number of recipients I can add to an alias?**
 
 The limit is currently set to 10 which should suffice in the vast majority of situations.
 
-
 #### **What happens when I delete my account?**
 
 When you delete your account the following happens:
@@ -100,7 +91,6 @@ When you delete your account the following happens:
 
 The reason aliases with a custom domain are soft deleted (a deleted_at column is filled in the database) is to ensure that nobody else can register your same domain in the future and then sign up to our site and receive emails for aliases you have previously used.
 
-
 #### **Does this work with any email provider?**
 
 Yes this will work with any provider, althought I can't guarantee it won't land in spam initially.
@@ -110,16 +100,28 @@ Yes this will work with any provider, althought I can't guarantee it won't land
 
 No, your real email will not be shown, the email will look as if it has come from us instead. Just make sure not to include anything that might identify you when composing the reply, i.e. your full name.
 
-
 #### **Can emails have attachments?**
 
 Yes you can add attachments to emails forwarded and replies. Attachments count towards your bandwidth.
 
-
 #### **What is the max email size limit?**
 
 The max email size is currently set to 10MB (including attachments).
 
+#### **What happens if I have a subscription but then cancel it?**
+
+If you cancel your subscription it will remain active until the end of your current billing cycle, you will still be able to use Pro features until the billing cycle ends.
+
+A few days before your billing cycle ends you will receive an email letting you know the steps you need to take to prevent the loss of any emails. Shortly after ending the following will happen:
+
+* Any custom domains will be **deactivated**
+* Any additional usernames will be **deactivated**
+* If you have any more than **2 recipients** they will be **deleted**
+* Pro account settings will be reverted to default values
+* Any aliases using Pro only domains will be **deactivated**
+* If you have any more than 20 UUID aliases they will be **deactivated**
+
+You will not be able to activate any of the above again until you resubscribe.
 
 #### **How do you prevent spammers?**
 
@@ -137,7 +139,6 @@ The following is in place to help prevent spam:
 
 The server is running a local DNS caching server to improve the speed of queries. DNS.WATCH resolvers are used as a fallback.
 
-
 #### **Is there a limit to how many emails I can forward?**
 
 Not unless you are really going to town. Each user is throttled to 200 emails per hour through the server.
@@ -154,27 +155,22 @@ I don't use rolling 30 day total as the only way to do this would be to log the
 
 Blocked emails do not count towards your bandwidth (e.g. an alias is inactive or deleted).
 
-
 #### **What happens if I go over my bandwidth limit in a given month?**
 
 If you get close to your limit you'll be sent an email letting you know. If you continue and go over your limit the server will start discarding emails until your bandwidth resets the next month.
 
-
 #### **I'm not receiving any emails, what's wrong?**
 
 Please make sure to add mailer@anonaddy.me to your address book and check your spam folder. Make sure to mark emails from us as safe if they turn up in spam. If you still aren't receiving emails contact me.
 
-
 #### **How do I know this site won't disappear next month?**
 
 I am very passionite about this project. I use it myself everyday and will be keeping it running indefinitely.
 
-
 #### **Is the application tested?**
 
 Yes it has over 100 automated PHPUnit tests written.
 
-
 #### **How do I host this myself?**
 
 You will need to set up your own server with Postfix so that you can pipe the received mail to the application. You can find more information here [https://github.com/anonaddy/anonaddy#self-hosting](https://github.com/anonaddy/anonaddy#self-hosting).
@@ -183,7 +179,6 @@ You will need to set up your own server with Postfix so that you can pipe the re
 
 My name is Will Browning, I'm a web developer from the UK and an advocate for online privacy and open-source software. You can find me on [Twitter](https://twitter.com/willbrowningme) although I don't tweet that much!
 
-
 #### **I couldn't find an answer to my question, how can I contact you?**
 
 For any other questions just send an email to - [contact@anonaddy.com](mailto:contact@anonaddy.com)

+ 8 - 3
app/Alias.php

@@ -66,9 +66,9 @@ class Alias extends Model
     /**
      * Get the custom domain for the email alias.
      */
-    public function domain()
+    public function customDomain()
     {
-        return $this->belongsTo(Domain::class);
+        return $this->belongsTo(Domain::class, 'domain_id');
     }
 
     /**
@@ -76,7 +76,7 @@ class Alias extends Model
      */
     public function recipients()
     {
-        return $this->BelongsToMany(Recipient::class, 'alias_recipients')->withPivot('id')->using(AliasRecipient::class);
+        return $this->belongsToMany(Recipient::class, 'alias_recipients')->withPivot('id')->using(AliasRecipient::class);
     }
 
     /**
@@ -93,6 +93,11 @@ class Alias extends Model
     public function verifiedRecipientsOrDefault()
     {
         if ($this->verifiedRecipients()->count() === 0) {
+            // If the alias is for a custom domain that has a default recipient set.
+            if (isset($this->customDomain->defaultRecipient)) {
+                return $this->customDomain->defaultRecipient();
+            }
+
             return $this->user->defaultRecipient();
         }
 

+ 19 - 1
app/Domain.php

@@ -33,7 +33,8 @@ class Domain extends Model
     protected $casts = [
         'id' => 'string',
         'user_id' => 'string',
-        'active' => 'boolean'
+        'active' => 'boolean',
+        'default_recipient_id' => 'string',
     ];
 
     /**
@@ -60,6 +61,23 @@ class Domain extends Model
         return $this->hasMany(Alias::class);
     }
 
+    /**
+     * Get the domains's default recipient.
+     */
+    public function defaultRecipient()
+    {
+        return $this->hasOne(Recipient::class, 'id', 'default_recipient_id');
+    }
+
+    /**
+     * Set the domains's default recipient.
+     */
+    public function setDefaultRecipientAttribute($recipient)
+    {
+        $this->attributes['default_recipient_id'] = $recipient->id;
+        $this->setRelation('defaultRecipient', $recipient);
+    }
+
     /**
      * Deactivate the domain.
      */

+ 1 - 1
app/Http/Controllers/DomainController.php

@@ -11,7 +11,7 @@ class DomainController extends Controller
     public function index()
     {
         return view('domains.index', [
-            'domains' => user()->domains()->with('aliases')->latest()->get()
+            'domains' => user()->domains()->with(['aliases', 'defaultRecipient'])->latest()->get()
         ]);
     }
 

+ 24 - 0
app/Http/Controllers/DomainDefaultRecipientController.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\UpdateDomainDefaultRecipientRequest;
+use App\Http\Resources\DomainResource;
+
+class DomainDefaultRecipientController extends Controller
+{
+    public function update(UpdateDomainDefaultRecipientRequest $request, $id)
+    {
+        $domain = user()->domains()->findOrFail($id);
+        if (empty($request->default_recipient)) {
+            $domain->default_recipient_id = null;
+        } else {
+            $recipient = user()->verifiedRecipients()->findOrFail($request->default_recipient);
+            $domain->default_recipient = $recipient;
+        }
+
+        $domain->save();
+
+        return new DomainResource($domain);
+    }
+}

+ 30 - 0
app/Http/Requests/UpdateDomainDefaultRecipientRequest.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class UpdateDomainDefaultRecipientRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'default_recipient' => 'nullable|string'
+        ];
+    }
+}

+ 8 - 0
app/User.php

@@ -165,6 +165,14 @@ class User extends Authenticatable implements MustVerifyEmail
         return $this->recipients()->whereNotNull('email_verified_at');
     }
 
+    /**
+     * Get all of the user's verified domains.
+     */
+    public function verifiedDomains()
+    {
+        return $this->domains()->whereNotNull('domain_verified_at');
+    }
+
     /**
      * Get all of the alias recipient pivot rows for the user.
      */

+ 32 - 0
database/migrations/2019_09_24_153605_add_default_recipient_id_column_to_domains_table.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddDefaultRecipientIdColumnToDomainsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('domains', function (Blueprint $table) {
+            $table->uuid('default_recipient_id')->nullable()->after('user_id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('domains', function (Blueprint $table) {
+            $table->dropColumn('default_recipient_id');
+        });
+    }
+}

BIN
public/android-chrome-192x192.png


BIN
public/android-chrome-256x256.png


BIN
public/apple-touch-icon.png


+ 1 - 1
public/browserconfig.xml

@@ -3,7 +3,7 @@
     <msapplication>
         <tile>
             <square150x150logo src="/mstile-150x150.png"/>
-            <TileColor>#da532c</TileColor>
+            <TileColor>#19216c</TileColor>
         </tile>
     </msapplication>
 </browserconfig>

BIN
public/favicon-16x16.png


BIN
public/favicon-32x32.png


BIN
public/favicon.ico


BIN
public/mstile-150x150.png


+ 17 - 14
public/safari-pinned-tab.svg

@@ -10,19 +10,22 @@ Created by potrace 1.11, written by Peter Selinger 2001-2013
 <g transform="translate(0.000000,260.000000) scale(0.100000,-0.100000)"
 fill="#000000" stroke="none">
 <path d="M0 1300 l0 -1300 1300 0 1300 0 0 1300 0 1300 -1300 0 -1300 0 0
--1300z m1194 559 l26 -20 0 -599 0 -599 -26 -20 c-21 -16 -41 -21 -90 -21 -35
-0 -74 5 -87 11 -25 11 -47 47 -47 74 0 26 -32 16 -75 -24 -53 -49 -137 -80
--234 -88 -219 -16 -394 110 -466 337 -26 81 -33 435 -11 540 44 211 200 370
-406 414 46 10 141 15 321 15 245 1 257 0 283 -20z m1153 -3 l28 -24 0 -592 0
--592 -28 -24 c-24 -21 -38 -24 -103 -24 -66 0 -78 3 -99 25 -14 13 -25 36 -25
-50 0 34 -24 32 -62 -5 -59 -60 -171 -100 -278 -100 -221 0 -395 151 -445 386
--10 46 -15 130 -15 255 0 278 33 384 159 510 72 72 177 131 266 147 28 6 168
-10 312 11 l262 1 28 -24z"/>
-<path d="M619 1625 c-59 -19 -127 -79 -159 -141 -24 -47 -25 -58 -28 -259 -2
--115 -1 -224 3 -241 9 -48 60 -117 106 -143 57 -32 158 -40 227 -17 67 23 134
-84 169 154 l28 57 0 300 0 300 -150 2 c-107 1 -163 -2 -196 -12z"/>
-<path d="M1770 1625 c-60 -19 -119 -70 -155 -136 l-30 -54 -3 -211 c-2 -141 1
--226 8 -255 16 -57 90 -132 145 -148 160 -44 317 40 364 195 20 64 21 89 19
-344 l-3 275 -150 2 c-106 1 -163 -2 -195 -12z"/>
+-1300z m2200 655 c63 -32 60 -7 60 -596 l0 -536 -31 -61 c-17 -36 -46 -74 -69
+-92 -78 -62 -57 -60 -799 -60 -513 0 -680 3 -689 12 -16 16 -16 70 0 86 9 9
+170 12 662 12 417 0 664 4 688 10 46 13 92 50 107 87 8 20 11 162 9 497 l-3
+468 -305 -238 c-394 -307 -376 -294 -420 -294 -46 0 -71 17 -551 387 -102 78
+-191 154 -197 168 -26 57 -2 127 51 150 50 22 1445 22 1487 0z m-1496 -381
+c17 -16 21 -51 8 -70 -4 -7 -47 -44 -97 -83 -94 -74 -129 -86 -159 -55 -9 8
+-16 26 -16 40 0 26 15 41 125 128 74 58 111 69 139 40z m226 -144 c39 -39 18
+-84 -62 -135 -50 -31 -108 5 -94 59 7 27 91 96 118 96 10 0 27 -9 38 -20z
+m-536 -96 c50 -50 -31 -146 -90 -106 -18 12 -35 52 -28 65 31 54 86 74 118 41z
+m742 -67 c42 -36 28 -65 -64 -136 -42 -33 -115 -89 -162 -125 -90 -71 -124
+-81 -154 -47 -35 38 -18 60 144 189 140 111 181 139 202 141 4 1 19 -9 34 -22z
+m-408 -20 c12 -24 11 -31 -2 -52 -24 -37 -387 -315 -411 -315 -31 0 -57 33
+-53 66 2 23 38 55 198 181 164 129 200 153 225 151 21 -2 34 -11 43 -31z m-26
+-324 c34 -30 18 -82 -32 -108 -24 -13 -35 -13 -53 -4 -46 24 -50 68 -11 104
+31 29 70 32 96 8z"/>
+<path d="M811 1837 c9 -7 145 -113 303 -237 159 -124 292 -225 297 -225 8 0
+609 465 609 471 0 2 -276 4 -612 4 -484 -1 -610 -3 -597 -13z"/>
 </g>
 </svg>

+ 2 - 2
public/site.webmanifest

@@ -1,6 +1,6 @@
 {
-    "name": "",
-    "short_name": "",
+    "name": "AnonAddy",
+    "short_name": "AnonAddy",
     "icons": [
         {
             "src": "/android-chrome-192x192.png",

+ 19 - 0
public/svg/icon-logo.svg

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg width="73.517" height="50" version="1.1" viewBox="0 0 73.517 50" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata>
+<style type="text/css">
+	.st0{fill:#3AE7E1;}
+	.st1{fill:#F5F7FA;}
+</style>
+<g id="XMLID_29_" transform="matrix(.1641 0 0 .1641 -8.4819 -6.6295)">
+		<path id="XMLID_41_" class="st0" d="m107.8 179.5c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l37-28.9c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-37 28.9c-1.8 1.5-3.9 2.4-6.1 2.7z" style="fill:#3ae7e1"/>
+	</g><g id="XMLID_30_" transform="matrix(.1641 0 0 .1641 -8.4819 -6.6295)">
+		<path id="XMLID_40_" class="st1" d="m71.9 207.7c-4.6 0.7-9.5-1-12.6-4.9-4.5-5.8-3.5-14.1 2.3-18.7l3.5-2.7c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-3.5 2.7c-1.8 1.4-3.9 2.3-6.1 2.6z" style="fill:#f5f7fa"/>
+	</g><g id="XMLID_31_" transform="matrix(.1641 0 0 .1641 -8.4819 -6.6295)">
+		<path id="XMLID_39_" class="st0" d="m67.1 283.6c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l81.2-63.4c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.1-2.3 18.7l-81.2 63.5c-1.9 1.4-4 2.3-6.1 2.6z" style="fill:#3ae7e1"/>
+	</g><g id="XMLID_34_" transform="matrix(.1641 0 0 .1641 -8.4819 -6.6295)">
+		<path id="XMLID_38_" class="st1" d="m182.8 193.6c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l12.9-10.1c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-12.9 10.1c-1.9 1.4-4 2.3-6.1 2.7z" style="fill:#f5f7fa"/>
+	</g><g id="XMLID_32_" transform="matrix(.1641 0 0 .1641 -8.4819 -6.6295)">
+		<path id="XMLID_37_" class="st0" d="m175.7 271.1c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l66.6-52c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.1-2.3 18.7l-66.6 52c-1.8 1.5-3.9 2.4-6.1 2.7z" style="fill:#3ae7e1"/>
+	</g><path id="XMLID_36_" class="st1" d="m14.377 42.599c-0.75484 0.11487-1.5589-0.16409-2.0676-0.82048-0.73843-0.95176-0.57434-2.3302 0.37742-3.0686l0.77125-0.60716c0.95176-0.73843 2.3302-0.57434 3.0686 0.37742 0.73843 0.95176 0.57433 2.3302-0.37742 3.0686l-0.77126 0.60715c-0.31178 0.24615-0.65638 0.39383-1.001 0.44306z" style="fill:#f5f7fa;stroke-width:.1641"/><path id="XMLID_44_" class="st0" d="m69.464 0h-50.673c-1.8871 0-3.6429 1.1651-4.2009 2.9701-0.26255 0.83689-0.24614 1.6902 0 2.4614 0.24615 0.78766 0.73844 1.5097 1.4276 2.0512 0 0 19.413 15.08 24.171 18.362 1.7066 1.0994 3.364 0.72203 4.3486-0.0328l24.631-19.166v33.131c0 3.2327-2.6255 5.8582-5.8582 5.8582h-46.554c-1.1979 0-2.1661 0.96817-2.1661 2.1661 0 1.2143 0.98458 2.1989 2.1989 2.1989h46.505c5.6449 0 10.223-4.5783 10.223-10.223v-35.724c0.0164-2.2317-1.805-4.0532-4.0532-4.0532zm-35.051 18.067 0.0164-0.11487 0.0656 0.0985zm7.9258 3.9383-22.563-17.64h45.208z" style="fill:#3ae7e1;stroke-width:.1641"/>
+</svg>

+ 39 - 21
public/svg/logo-dark.svg

@@ -1,23 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg width="203.11" height="50" version="1.1" viewBox="0 0 53.739 13.229" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <metadata>
-  <rdf:RDF>
-   <cc:Work rdf:about="">
-    <dc:format>image/svg+xml</dc:format>
-    <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
-    <dc:title/>
-   </cc:Work>
-  </rdf:RDF>
- </metadata>
- <g aria-label="anonaddy">
-  <path d="m4.0263 4.6733q0-0.1438-0.1438-0.1438h-1.0785q-0.71898 0-1.1216 0.44577-0.38825 0.44577-0.38825 1.0641v1.4236q0 0.54642 0.31635 0.89153 0.33073 0.34511 0.90591 0.34511 0.38825 0 0.66146-0.12942 0.28759-0.1438 0.47452-0.37387 0.18693-0.23007 0.27321-0.50328 0.10066-0.28759 0.10066-0.58956zm0.43139 5.1047q-0.20131 0-0.31635-0.12942-0.11504-0.12942-0.11504-0.28759 0-0.086277-0.071898-0.10066-0.057518-0.028759-0.11504 0.043139-0.20131 0.27321-0.60394 0.44577-0.38825 0.17255-0.94905 0.17255-0.50328 0-0.92029-0.18693-0.41701-0.18693-0.71898-0.53204-0.30197-0.34511-0.47452-0.81963-0.17255-0.4889-0.17255-1.0641v-1.2798q0-0.5608 0.20131-1.0641t0.5608-0.86277q0.37387-0.37387 0.87715-0.58956 0.50328-0.21569 1.1072-0.21569h2.1425q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v5.608q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m11.311 9.7781q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.54642-0.34511-0.94905-0.33073-0.41701-1.0209-0.41701-0.69022 0-1.0353 0.41701-0.33073 0.40263-0.33073 0.94905v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504h-0.43139q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.51766 0.18693-0.99219 0.20131-0.47452 0.54642-0.81963 0.34511-0.35949 0.83401-0.5608 0.4889-0.21569 1.0928-0.21569t1.0928 0.21569q0.4889 0.20131 0.83401 0.5608 0.34511 0.34511 0.53204 0.81963 0.20131 0.47452 0.20131 0.99219v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m16.798 8.6996q0.44577 0 0.81963-0.17255 0.38825-0.17255 0.66146-0.46014 0.28759-0.28759 0.44576-0.67584 0.15818-0.40263 0.15818-0.84839t-0.15818-0.83401q-0.15818-0.40263-0.44576-0.69022-0.27321-0.28759-0.66146-0.46014-0.37387-0.17255-0.81963-0.17255-0.44576 0-0.83401 0.17255-0.37387 0.17255-0.66146 0.46014-0.27321 0.28759-0.43139 0.69022-0.15817 0.38825-0.15817 0.83401t0.15817 0.84839q0.15818 0.38825 0.43139 0.67584 0.28759 0.28759 0.66146 0.46014 0.38825 0.17255 0.83401 0.17255zm0 1.2223q-0.7046 0-1.3229-0.25883-0.60394-0.27321-1.0641-0.73336-0.46014-0.46014-0.73336-1.0641-0.25883-0.61832-0.25883-1.3229 0-0.7046 0.25883-1.3085 0.27321-0.61832 0.73336-1.0785 0.46014-0.46014 1.0641-0.71898 0.61832-0.27321 1.3229-0.27321t1.3085 0.27321q0.61832 0.25883 1.0785 0.71898 0.46014 0.46014 0.71898 1.0785 0.27321 0.60394 0.27321 1.3085 0 0.7046-0.27321 1.3229-0.25883 0.60394-0.71898 1.0641-0.46014 0.46014-1.0785 0.73336-0.60394 0.25883-1.3085 0.25883z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m25.888 9.7781q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.54642-0.34511-0.94905-0.33073-0.41701-1.0209-0.41701-0.69022 0-1.0353 0.41701-0.33073 0.40263-0.33073 0.94905v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504h-0.43139q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.51766 0.18693-0.99219 0.20131-0.47452 0.54642-0.81963 0.34511-0.35949 0.83401-0.5608 0.4889-0.21569 1.0928-0.21569 0.60394 0 1.0928 0.21569 0.4889 0.20131 0.83401 0.5608 0.34511 0.34511 0.53204 0.81963 0.20131 0.47452 0.20131 0.99219v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m32.31 4.6733q0-0.1438-0.1438-0.1438h-1.0785q-0.71898 0-1.1216 0.44577-0.38825 0.44577-0.38825 1.0641v1.4236q0 0.54642 0.31635 0.89153 0.33073 0.34511 0.90591 0.34511 0.38825 0 0.66146-0.12942 0.28759-0.1438 0.47452-0.37387 0.18693-0.23007 0.27321-0.50328 0.10066-0.28759 0.10066-0.58956zm0.43139 5.1047q-0.20131 0-0.31635-0.12942-0.11504-0.12942-0.11504-0.28759 0-0.086277-0.0719-0.10066-0.05752-0.028759-0.11504 0.043139-0.20131 0.27321-0.60394 0.44577-0.38825 0.17255-0.94905 0.17255-0.50328 0-0.92029-0.18693-0.417-0.18693-0.71897-0.53204t-0.47452-0.81963q-0.17256-0.4889-0.17256-1.0641v-1.2798q0-0.5608 0.20131-1.0641 0.20131-0.50328 0.5608-0.86277 0.37387-0.37387 0.87715-0.58956 0.50328-0.21569 1.1072-0.21569h2.1426q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v5.608q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#7b8794;stroke-width:.065362"/>
-  <path d="m37.51 9.7781q-0.5608 0-1.0353-0.18693-0.46014-0.18693-0.79087-0.50328-0.33073-0.33073-0.51766-0.77649-0.17256-0.46014-0.17256-0.97781v-1.5817q0-0.51766 0.18693-0.96343 0.18693-0.46014 0.50328-0.77649 0.33073-0.33073 0.77649-0.51766 0.46014-0.18693 0.99219-0.18693h1.4236q0.1438 0 0.1438-0.1438v-2.7321q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43139q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v8.9153q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504zm1.5098-5.1047q0-0.1438-0.1438-0.1438h-1.3661q-0.54642 0-0.89153 0.34511-0.33073 0.33073-0.33073 0.87715v1.5817q0 0.54642 0.35949 0.89153 0.35949 0.33073 0.86277 0.33073h1.3661q0.1438 0 0.1438-0.1438z" style="fill:#7b8794;stroke-width:.065362"/>
-  <path d="m44.222 9.7781q-0.5608 0-1.0353-0.18693-0.46014-0.18693-0.79087-0.50328-0.33073-0.33073-0.51766-0.77649-0.17255-0.46014-0.17255-0.97781v-1.5817q0-0.51766 0.18693-0.96343 0.18693-0.46014 0.50328-0.77649 0.33073-0.33073 0.7765-0.51766 0.46014-0.18693 0.99219-0.18693h1.4236q0.1438 0 0.1438-0.1438v-2.7321q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43139q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v8.9153q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504zm1.5099-5.1047q0-0.1438-0.1438-0.1438h-1.3661q-0.54642 0-0.89153 0.34511-0.33073 0.33073-0.33073 0.87715v1.5817q0 0.54642 0.35949 0.89153 0.35949 0.33073 0.86277 0.33073h1.3661q0.1438 0 0.1438-0.1438z" style="fill:#7b8794;stroke-width:.065362"/>
-  <path d="m52.445 9.9219q0-0.1438-0.1438-0.1438h-1.3373q-0.53204 0-0.97781-0.17255-0.44576-0.18693-0.76212-0.50328-0.31635-0.31635-0.4889-0.74774-0.17255-0.44577-0.17255-0.96343v-3.6524q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43138q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v3.6524q0 0.54642 0.30197 0.86277 0.31635 0.30197 0.86277 0.30197h1.2798q0.1438 0 0.1438-0.1438v-4.6733q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43139q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v6.8015q0 0.54642-0.18693 1.0353t-0.53204 0.84839q-0.34511 0.37387-0.83401 0.58956t-1.1072 0.21569q-0.73336 0-1.2223-0.15818-0.4889-0.1438-0.86277-0.38825-0.15818-0.10066-0.21569-0.25883-0.04314-0.15817 0.04314-0.31635l0.17256-0.33073q0.18693-0.35949 0.5608-0.17256 0.30197 0.17256 0.66146 0.28759 0.35949 0.11504 0.86277 0.11504 0.73336 0 1.0497-0.40263 0.31635-0.38825 0.31635-1.0641z" style="fill:#7b8794;stroke-width:.065362"/>
- </g>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg width="295.33" height="50" version="1.1" viewBox="0 0 295.33 50" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata>
+<style type="text/css">
+	.st0{fill:#3AE7E1;}
+	.st1{fill:#7B8794;}
+</style>
+<g id="XMLID_1_" transform="matrix(.15571 0 0 .15571 -8.0487 -6.2909)">
+	<g id="XMLID_29_">
+		<path id="XMLID_41_" class="st0" d="m107.8 179.5c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l37-28.9c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-37 28.9c-1.8 1.5-3.9 2.4-6.1 2.7z" style="fill:#3ae7e1"/>
+	</g>
+	<g id="XMLID_30_">
+		<path id="XMLID_40_" class="st1" d="m71.9 207.7c-4.6 0.7-9.5-1-12.6-4.9-4.5-5.8-3.5-14.1 2.3-18.7l3.5-2.7c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-3.5 2.7c-1.8 1.4-3.9 2.3-6.1 2.6z" style="fill:#7b8794"/>
+	</g>
+	<g id="XMLID_31_">
+		<path id="XMLID_39_" class="st0" d="m67.1 283.6c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l81.2-63.4c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.1-2.3 18.7l-81.2 63.5c-1.9 1.4-4 2.3-6.1 2.6z" style="fill:#3ae7e1"/>
+	</g>
+	<g id="XMLID_34_">
+		<path id="XMLID_38_" class="st1" d="m182.8 193.6c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l12.9-10.1c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-12.9 10.1c-1.9 1.4-4 2.3-6.1 2.7z" style="fill:#7b8794"/>
+	</g>
+	<g id="XMLID_32_">
+		<path id="XMLID_37_" class="st0" d="m175.7 271.1c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l66.6-52c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.1-2.3 18.7l-66.6 52c-1.8 1.5-3.9 2.4-6.1 2.7z" style="fill:#3ae7e1"/>
+	</g>
+	<path id="XMLID_36_" class="st1" d="m139.3 300c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.2 2.3-18.7l4.7-3.7c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.2-2.3 18.7l-4.7 3.7c-1.9 1.5-4 2.4-6.1 2.7z" style="fill:#7b8794"/>
+	<path id="XMLID_44_" class="st0" d="m475 40.4h-308.8c-11.5 0-22.2 7.1-25.6 18.1-1.6 5.1-1.5 10.3 0 15 1.5 4.8 4.5 9.2 8.7 12.5 0 0 118.3 91.9 147.3 111.9 10.4 6.7 20.5 4.4 26.5-0.2l150.1-116.8v201.9c0 19.7-16 35.7-35.7 35.7h-283.7c-7.3 0-13.2 5.9-13.2 13.2 0 7.4 6 13.4 13.4 13.4h283.4c34.4 0 62.3-27.9 62.3-62.3v-217.7c0.1-13.6-11-24.7-24.7-24.7zm-213.6 110.1 0.1-0.7 0.4 0.6zm48.3 24-137.5-107.5h275.5z" style="fill:#3ae7e1"/>
+	<g id="XMLID_81_">
+		<g id="XMLID_4_">
+			<path id="XMLID_25_" class="st0" d="m791.7 281.8c2.4 6.5 0 9.8-6.8 9.8h-15.5c-12.2 0-16.1-1.8-18.4-8.9l-13.7-38.4h-82.1l-14 38.4c-2.4 7.1-6.2 8.9-18.4 8.9h-13.7c-6.8 0-9.2-3.3-6.8-9.8l74.3-193.3c2.7-6.8 5.4-8.3 12.5-8.3h15.8c7.1 0 10.1 1.8 12.5 8zm-87.4-130.8c-3.6-10.7-5.9-24.4-6.8-31.2l-0.3-5.1h-2.1c0 11.3-2.1 23.2-6.5 36l-22.9 63h61.3z" style="fill:#3ae7e1"/>
+			<path id="XMLID_28_" class="st0" d="m881.8 133.2c41.6 0 61.8 21.4 61.8 59.8v89.5c0 6.8-2.4 9.2-9.2 9.2h-16.4c-6.8 0-8.9-2.4-8.9-9.2v-88.6c0-19.3-10.7-29.1-32.4-29.1-9.5 0-19 1.2-28.5 3.9-1.5 0.6-2.1 1.5-2.1 3v110.9c0 6.8-2.1 9.2-8.9 9.2h-16.4c-6.8 0-9.2-2.4-9.2-9.2v-122.4c0-9.5 2.1-13.1 11.6-16.9 17-6.9 36.3-10.1 58.6-10.1z" style="fill:#3ae7e1"/>
+			<path id="XMLID_65_" class="st0" d="m971.6 192.6c0-37.2 24.7-59.5 68.4-59.5 44 0 68.7 22.3 68.7 59.5v44c0 37.2-24.7 59.5-68.7 59.5-43.7 0-68.4-22.3-68.4-59.5zm102.6 0c0-18.1-12.5-28.2-34.2-28.2s-33.9 10.1-33.9 28.2v44c0 17.8 12.2 28.2 33.9 28.2s34.2-10.4 34.2-28.2z" style="fill:#3ae7e1"/>
+			<path id="XMLID_68_" class="st0" d="m1207.7 133.2c41.6 0 61.8 21.4 61.8 59.8v89.5c0 6.8-2.4 9.2-9.2 9.2h-16.4c-6.8 0-8.9-2.4-8.9-9.2v-88.6c0-19.3-10.7-29.1-32.4-29.1-9.5 0-19 1.2-28.5 3.9-1.5 0.6-2.1 1.5-2.1 3v110.9c0 6.8-2.1 9.2-8.9 9.2h-16.4c-6.8 0-9.2-2.4-9.2-9.2v-122.4c0-9.5 2.1-13.1 11.6-16.9 16.9-6.9 36.3-10.1 58.6-10.1z" style="fill:#3ae7e1"/>
+		</g>
+		<g id="XMLID_24_">
+			<path id="XMLID_70_" class="st1" d="m1477.7 281.8c2.4 6.5 0 9.8-6.8 9.8h-15.5c-12.2 0-16.1-1.8-18.4-8.9l-13.7-38.4h-82.1l-14 38.4c-2.4 7.1-6.2 8.9-18.4 8.9h-13.7c-6.8 0-9.2-3.3-6.8-9.8l74.3-193.3c2.7-6.8 5.4-8.3 12.5-8.3h15.8c7.1 0 10.1 1.8 12.5 8zm-87.5-130.8c-3.6-10.7-5.9-24.4-6.8-31.2l-0.3-5.1h-2.1c0 11.3-2.1 23.2-6.5 36l-22.9 63h61.3z" style="fill:#7b8794"/>
+			<path id="XMLID_73_" class="st1" d="m1490.7 195.3c0-40.4 20.8-62.1 62.1-62.1 9.2 0 20.8 1.2 35.4 3.9v-56.3c0-6.8 2.1-9.2 8.9-9.2h16.4c6.8 0 9.2 2.4 9.2 9.2v189.4c0 9.5-2.4 12.5-11.9 16.4-16.9 6.2-35.4 9.5-55.6 9.5-43.1 0-64.5-19.9-64.5-60.1zm97.6-26.7c-11.9-2.7-21.4-3.9-28.8-3.9-22.9 0-34.2 10.4-34.2 31.5v38.7c0 19.9 11 29.7 33.3 29.7 10.4 0 19.6-1.2 27.4-3.3 1.5-0.6 2.4-1.8 2.4-3.3v-89.4z" style="fill:#7b8794"/>
+			<path id="XMLID_76_" class="st1" d="m1651.9 195.3c0-40.4 20.8-62.1 62.1-62.1 9.2 0 20.8 1.2 35.4 3.9v-56.3c0-6.8 2.1-9.2 8.9-9.2h16.4c6.8 0 9.2 2.4 9.2 9.2v189.4c0 9.5-2.4 12.5-11.9 16.4-16.9 6.2-35.4 9.5-55.6 9.5-43.1 0-64.5-19.9-64.5-60.1zm97.5-26.7c-11.9-2.7-21.4-3.9-28.8-3.9-22.9 0-34.2 10.4-34.2 31.5v38.7c0 19.9 11 29.7 33.3 29.7 10.4 0 19.6-1.2 27.4-3.3 1.5-0.6 2.4-1.8 2.4-3.3v-89.4z" style="fill:#7b8794"/>
+			<path id="XMLID_79_" class="st1" d="m1939.1 137.6c6.8 0 9.2 2.1 9.2 8.9v150.2c0 40.7-20.5 64.8-65.4 64.8-29.4 0-50.3-9.5-61.8-28.5-4.2-6.5-3-11.6 3.9-14.9l11.3-6.2c7.1-3.6 10.4-2.7 14.9 3.6 6.2 10.1 16.6 15.2 31.2 15.2 21.1 0 31.5-10.7 31.5-32.1v-14c-12.2 2.7-24.1 4.2-35.4 4.2-41.6 0-62.1-21.4-62.1-59.8v-82.4c0-6.8 2.4-8.9 9.2-8.9h16.4c6.8 0 8.9 2.1 8.9 8.9v81.2c0 19.6 10.7 29.4 32.4 29.4 9.8 0 19.9-1.5 30.6-4.2v-106.5c0-6.8 2.4-8.9 9.2-8.9z" style="fill:#7b8794"/>
+		</g>
+	</g>
+</g>
 </svg>

+ 39 - 21
public/svg/logo.svg

@@ -1,23 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg width="203.11" height="50" version="1.1" viewBox="0 0 53.739 13.229" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <metadata>
-  <rdf:RDF>
-   <cc:Work rdf:about="">
-    <dc:format>image/svg+xml</dc:format>
-    <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
-    <dc:title/>
-   </cc:Work>
-  </rdf:RDF>
- </metadata>
- <g aria-label="anonaddy">
-  <path d="m4.0263 4.6733q0-0.1438-0.1438-0.1438h-1.0785q-0.71898 0-1.1216 0.44577-0.38825 0.44577-0.38825 1.0641v1.4236q0 0.54642 0.31635 0.89153 0.33073 0.34511 0.90591 0.34511 0.38825 0 0.66146-0.12942 0.28759-0.1438 0.47452-0.37387 0.18693-0.23007 0.27321-0.50328 0.10066-0.28759 0.10066-0.58956zm0.43139 5.1047q-0.20131 0-0.31635-0.12942-0.11504-0.12942-0.11504-0.28759 0-0.086277-0.071898-0.10066-0.057518-0.028759-0.11504 0.043139-0.20131 0.27321-0.60394 0.44577-0.38825 0.17255-0.94905 0.17255-0.50328 0-0.92029-0.18693-0.41701-0.18693-0.71898-0.53204-0.30197-0.34511-0.47452-0.81963-0.17255-0.4889-0.17255-1.0641v-1.2798q0-0.5608 0.20131-1.0641t0.5608-0.86277q0.37387-0.37387 0.87715-0.58956 0.50328-0.21569 1.1072-0.21569h2.1425q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v5.608q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m11.311 9.7781q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.54642-0.34511-0.94905-0.33073-0.41701-1.0209-0.41701-0.69022 0-1.0353 0.41701-0.33073 0.40263-0.33073 0.94905v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504h-0.43139q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.51766 0.18693-0.99219 0.20131-0.47452 0.54642-0.81963 0.34511-0.35949 0.83401-0.5608 0.4889-0.21569 1.0928-0.21569t1.0928 0.21569q0.4889 0.20131 0.83401 0.5608 0.34511 0.34511 0.53204 0.81963 0.20131 0.47452 0.20131 0.99219v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m16.798 8.6996q0.44577 0 0.81963-0.17255 0.38825-0.17255 0.66146-0.46014 0.28759-0.28759 0.44576-0.67584 0.15818-0.40263 0.15818-0.84839t-0.15818-0.83401q-0.15818-0.40263-0.44576-0.69022-0.27321-0.28759-0.66146-0.46014-0.37387-0.17255-0.81963-0.17255-0.44576 0-0.83401 0.17255-0.37387 0.17255-0.66146 0.46014-0.27321 0.28759-0.43139 0.69022-0.15817 0.38825-0.15817 0.83401t0.15817 0.84839q0.15818 0.38825 0.43139 0.67584 0.28759 0.28759 0.66146 0.46014 0.38825 0.17255 0.83401 0.17255zm0 1.2223q-0.7046 0-1.3229-0.25883-0.60394-0.27321-1.0641-0.73336-0.46014-0.46014-0.73336-1.0641-0.25883-0.61832-0.25883-1.3229 0-0.7046 0.25883-1.3085 0.27321-0.61832 0.73336-1.0785 0.46014-0.46014 1.0641-0.71898 0.61832-0.27321 1.3229-0.27321t1.3085 0.27321q0.61832 0.25883 1.0785 0.71898 0.46014 0.46014 0.71898 1.0785 0.27321 0.60394 0.27321 1.3085 0 0.7046-0.27321 1.3229-0.25883 0.60394-0.71898 1.0641-0.46014 0.46014-1.0785 0.73336-0.60394 0.25883-1.3085 0.25883z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m25.888 9.7781q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.54642-0.34511-0.94905-0.33073-0.41701-1.0209-0.41701-0.69022 0-1.0353 0.41701-0.33073 0.40263-0.33073 0.94905v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504h-0.43139q-0.20131 0-0.31635-0.11504-0.11504-0.11504-0.11504-0.31635v-3.5949q0-0.51766 0.18693-0.99219 0.20131-0.47452 0.54642-0.81963 0.34511-0.35949 0.83401-0.5608 0.4889-0.21569 1.0928-0.21569 0.60394 0 1.0928 0.21569 0.4889 0.20131 0.83401 0.5608 0.34511 0.34511 0.53204 0.81963 0.20131 0.47452 0.20131 0.99219v3.5949q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#3ae7e1;stroke-width:.065362"/>
-  <path d="m32.31 4.6733q0-0.1438-0.1438-0.1438h-1.0785q-0.71898 0-1.1216 0.44577-0.38825 0.44577-0.38825 1.0641v1.4236q0 0.54642 0.31635 0.89153 0.33073 0.34511 0.90591 0.34511 0.38825 0 0.66146-0.12942 0.28759-0.1438 0.47452-0.37387 0.18693-0.23007 0.27321-0.50328 0.10066-0.28759 0.10066-0.58956zm0.43139 5.1047q-0.20131 0-0.31635-0.12942-0.11504-0.12942-0.11504-0.28759 0-0.086277-0.0719-0.10066-0.05752-0.028759-0.11504 0.043139-0.20131 0.27321-0.60394 0.44577-0.38825 0.17255-0.94905 0.17255-0.50328 0-0.92029-0.18693-0.417-0.18693-0.71897-0.53204t-0.47452-0.81963q-0.17256-0.4889-0.17256-1.0641v-1.2798q0-0.5608 0.20131-1.0641 0.20131-0.50328 0.5608-0.86277 0.37387-0.37387 0.87715-0.58956 0.50328-0.21569 1.1072-0.21569h2.1426q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v5.608q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504z" style="fill:#f5f7fa;stroke-width:.065362"/>
-  <path d="m37.51 9.7781q-0.5608 0-1.0353-0.18693-0.46014-0.18693-0.79087-0.50328-0.33073-0.33073-0.51766-0.77649-0.17256-0.46014-0.17256-0.97781v-1.5817q0-0.51766 0.18693-0.96343 0.18693-0.46014 0.50328-0.77649 0.33073-0.33073 0.77649-0.51766 0.46014-0.18693 0.99219-0.18693h1.4236q0.1438 0 0.1438-0.1438v-2.7321q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43139q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v8.9153q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504zm1.5098-5.1047q0-0.1438-0.1438-0.1438h-1.3661q-0.54642 0-0.89153 0.34511-0.33073 0.33073-0.33073 0.87715v1.5817q0 0.54642 0.35949 0.89153 0.35949 0.33073 0.86277 0.33073h1.3661q0.1438 0 0.1438-0.1438z" style="fill:#f5f7fa;stroke-width:.065362"/>
-  <path d="m44.222 9.7781q-0.5608 0-1.0353-0.18693-0.46014-0.18693-0.79087-0.50328-0.33073-0.33073-0.51766-0.77649-0.17255-0.46014-0.17255-0.97781v-1.5817q0-0.51766 0.18693-0.96343 0.18693-0.46014 0.50328-0.77649 0.33073-0.33073 0.7765-0.51766 0.46014-0.18693 0.99219-0.18693h1.4236q0.1438 0 0.1438-0.1438v-2.7321q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43139q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v8.9153q0 0.20131-0.11504 0.31635-0.11504 0.11504-0.31635 0.11504zm1.5099-5.1047q0-0.1438-0.1438-0.1438h-1.3661q-0.54642 0-0.89153 0.34511-0.33073 0.33073-0.33073 0.87715v1.5817q0 0.54642 0.35949 0.89153 0.35949 0.33073 0.86277 0.33073h1.3661q0.1438 0 0.1438-0.1438z" style="fill:#f5f7fa;stroke-width:.065362"/>
-  <path d="m52.445 9.9219q0-0.1438-0.1438-0.1438h-1.3373q-0.53204 0-0.97781-0.17255-0.44576-0.18693-0.76212-0.50328-0.31635-0.31635-0.4889-0.74774-0.17255-0.44577-0.17255-0.96343v-3.6524q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43138q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v3.6524q0 0.54642 0.30197 0.86277 0.31635 0.30197 0.86277 0.30197h1.2798q0.1438 0 0.1438-0.1438v-4.6733q0-0.20131 0.11504-0.31635 0.11504-0.11504 0.31635-0.11504h0.43139q0.20131 0 0.31635 0.11504 0.11504 0.11504 0.11504 0.31635v6.8015q0 0.54642-0.18693 1.0353t-0.53204 0.84839q-0.34511 0.37387-0.83401 0.58956t-1.1072 0.21569q-0.73336 0-1.2223-0.15818-0.4889-0.1438-0.86277-0.38825-0.15818-0.10066-0.21569-0.25883-0.04314-0.15817 0.04314-0.31635l0.17256-0.33073q0.18693-0.35949 0.5608-0.17256 0.30197 0.17256 0.66146 0.28759 0.35949 0.11504 0.86277 0.11504 0.73336 0 1.0497-0.40263 0.31635-0.38825 0.31635-1.0641z" style="fill:#f5f7fa;stroke-width:.065362"/>
- </g>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg width="295.33" height="50" version="1.1" viewBox="0 0 295.33 50" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata>
+<style type="text/css">
+	.st0{fill:#3AE7E1;}
+	.st1{fill:#F5F7FA;}
+</style>
+<g id="XMLID_1_" transform="matrix(.15571 0 0 .15571 -8.0487 -6.2909)">
+	<g id="XMLID_29_">
+		<path id="XMLID_41_" class="st0" d="m107.8 179.5c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l37-28.9c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-37 28.9c-1.8 1.5-3.9 2.4-6.1 2.7z" style="fill:#3ae7e1"/>
+	</g>
+	<g id="XMLID_30_">
+		<path id="XMLID_40_" class="st1" d="m71.9 207.7c-4.6 0.7-9.5-1-12.6-4.9-4.5-5.8-3.5-14.1 2.3-18.7l3.5-2.7c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-3.5 2.7c-1.8 1.4-3.9 2.3-6.1 2.6z" style="fill:#f5f7fa"/>
+	</g>
+	<g id="XMLID_31_">
+		<path id="XMLID_39_" class="st0" d="m67.1 283.6c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l81.2-63.4c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.1-2.3 18.7l-81.2 63.5c-1.9 1.4-4 2.3-6.1 2.6z" style="fill:#3ae7e1"/>
+	</g>
+	<g id="XMLID_34_">
+		<path id="XMLID_38_" class="st1" d="m182.8 193.6c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l12.9-10.1c5.8-4.5 14.1-3.5 18.7 2.3 4.5 5.8 3.5 14.1-2.3 18.7l-12.9 10.1c-1.9 1.4-4 2.3-6.1 2.7z" style="fill:#f5f7fa"/>
+	</g>
+	<g id="XMLID_32_">
+		<path id="XMLID_37_" class="st0" d="m175.7 271.1c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.1 2.3-18.7l66.6-52c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.1-2.3 18.7l-66.6 52c-1.8 1.5-3.9 2.4-6.1 2.7z" style="fill:#3ae7e1"/>
+	</g>
+	<path id="XMLID_36_" class="st1" d="m139.3 300c-4.6 0.7-9.5-1-12.6-5-4.5-5.8-3.5-14.2 2.3-18.7l4.7-3.7c5.8-4.5 14.2-3.5 18.7 2.3s3.5 14.2-2.3 18.7l-4.7 3.7c-1.9 1.5-4 2.4-6.1 2.7z" style="fill:#f5f7fa"/>
+	<path id="XMLID_44_" class="st0" d="m475 40.4h-308.8c-11.5 0-22.2 7.1-25.6 18.1-1.6 5.1-1.5 10.3 0 15 1.5 4.8 4.5 9.2 8.7 12.5 0 0 118.3 91.9 147.3 111.9 10.4 6.7 20.5 4.4 26.5-0.2l150.1-116.8v201.9c0 19.7-16 35.7-35.7 35.7h-283.7c-7.3 0-13.2 5.9-13.2 13.2 0 7.4 6 13.4 13.4 13.4h283.4c34.4 0 62.3-27.9 62.3-62.3v-217.7c0.1-13.6-11-24.7-24.7-24.7zm-213.6 110.1 0.1-0.7 0.4 0.6zm48.3 24-137.5-107.5h275.5z" style="fill:#3ae7e1"/>
+	<g id="XMLID_81_">
+		<g id="XMLID_4_">
+			<path id="XMLID_25_" class="st0" d="m791.7 281.8c2.4 6.5 0 9.8-6.8 9.8h-15.5c-12.2 0-16.1-1.8-18.4-8.9l-13.7-38.4h-82.1l-14 38.4c-2.4 7.1-6.2 8.9-18.4 8.9h-13.7c-6.8 0-9.2-3.3-6.8-9.8l74.3-193.3c2.7-6.8 5.4-8.3 12.5-8.3h15.8c7.1 0 10.1 1.8 12.5 8zm-87.4-130.8c-3.6-10.7-5.9-24.4-6.8-31.2l-0.3-5.1h-2.1c0 11.3-2.1 23.2-6.5 36l-22.9 63h61.3z" style="fill:#3ae7e1"/>
+			<path id="XMLID_28_" class="st0" d="m881.8 133.2c41.6 0 61.8 21.4 61.8 59.8v89.5c0 6.8-2.4 9.2-9.2 9.2h-16.4c-6.8 0-8.9-2.4-8.9-9.2v-88.6c0-19.3-10.7-29.1-32.4-29.1-9.5 0-19 1.2-28.5 3.9-1.5 0.6-2.1 1.5-2.1 3v110.9c0 6.8-2.1 9.2-8.9 9.2h-16.4c-6.8 0-9.2-2.4-9.2-9.2v-122.4c0-9.5 2.1-13.1 11.6-16.9 17-6.9 36.3-10.1 58.6-10.1z" style="fill:#3ae7e1"/>
+			<path id="XMLID_65_" class="st0" d="m971.6 192.6c0-37.2 24.7-59.5 68.4-59.5 44 0 68.7 22.3 68.7 59.5v44c0 37.2-24.7 59.5-68.7 59.5-43.7 0-68.4-22.3-68.4-59.5zm102.6 0c0-18.1-12.5-28.2-34.2-28.2s-33.9 10.1-33.9 28.2v44c0 17.8 12.2 28.2 33.9 28.2s34.2-10.4 34.2-28.2z" style="fill:#3ae7e1"/>
+			<path id="XMLID_68_" class="st0" d="m1207.7 133.2c41.6 0 61.8 21.4 61.8 59.8v89.5c0 6.8-2.4 9.2-9.2 9.2h-16.4c-6.8 0-8.9-2.4-8.9-9.2v-88.6c0-19.3-10.7-29.1-32.4-29.1-9.5 0-19 1.2-28.5 3.9-1.5 0.6-2.1 1.5-2.1 3v110.9c0 6.8-2.1 9.2-8.9 9.2h-16.4c-6.8 0-9.2-2.4-9.2-9.2v-122.4c0-9.5 2.1-13.1 11.6-16.9 16.9-6.9 36.3-10.1 58.6-10.1z" style="fill:#3ae7e1"/>
+		</g>
+		<g id="XMLID_24_">
+			<path id="XMLID_70_" class="st1" d="m1477.7 281.8c2.4 6.5 0 9.8-6.8 9.8h-15.5c-12.2 0-16.1-1.8-18.4-8.9l-13.7-38.4h-82.1l-14 38.4c-2.4 7.1-6.2 8.9-18.4 8.9h-13.7c-6.8 0-9.2-3.3-6.8-9.8l74.3-193.3c2.7-6.8 5.4-8.3 12.5-8.3h15.8c7.1 0 10.1 1.8 12.5 8zm-87.5-130.8c-3.6-10.7-5.9-24.4-6.8-31.2l-0.3-5.1h-2.1c0 11.3-2.1 23.2-6.5 36l-22.9 63h61.3z" style="fill:#f5f7fa"/>
+			<path id="XMLID_73_" class="st1" d="m1490.7 195.3c0-40.4 20.8-62.1 62.1-62.1 9.2 0 20.8 1.2 35.4 3.9v-56.3c0-6.8 2.1-9.2 8.9-9.2h16.4c6.8 0 9.2 2.4 9.2 9.2v189.4c0 9.5-2.4 12.5-11.9 16.4-16.9 6.2-35.4 9.5-55.6 9.5-43.1 0-64.5-19.9-64.5-60.1zm97.6-26.7c-11.9-2.7-21.4-3.9-28.8-3.9-22.9 0-34.2 10.4-34.2 31.5v38.7c0 19.9 11 29.7 33.3 29.7 10.4 0 19.6-1.2 27.4-3.3 1.5-0.6 2.4-1.8 2.4-3.3v-89.4z" style="fill:#f5f7fa"/>
+			<path id="XMLID_76_" class="st1" d="m1651.9 195.3c0-40.4 20.8-62.1 62.1-62.1 9.2 0 20.8 1.2 35.4 3.9v-56.3c0-6.8 2.1-9.2 8.9-9.2h16.4c6.8 0 9.2 2.4 9.2 9.2v189.4c0 9.5-2.4 12.5-11.9 16.4-16.9 6.2-35.4 9.5-55.6 9.5-43.1 0-64.5-19.9-64.5-60.1zm97.5-26.7c-11.9-2.7-21.4-3.9-28.8-3.9-22.9 0-34.2 10.4-34.2 31.5v38.7c0 19.9 11 29.7 33.3 29.7 10.4 0 19.6-1.2 27.4-3.3 1.5-0.6 2.4-1.8 2.4-3.3v-89.4z" style="fill:#f5f7fa"/>
+			<path id="XMLID_79_" class="st1" d="m1939.1 137.6c6.8 0 9.2 2.1 9.2 8.9v150.2c0 40.7-20.5 64.8-65.4 64.8-29.4 0-50.3-9.5-61.8-28.5-4.2-6.5-3-11.6 3.9-14.9l11.3-6.2c7.1-3.6 10.4-2.7 14.9 3.6 6.2 10.1 16.6 15.2 31.2 15.2 21.1 0 31.5-10.7 31.5-32.1v-14c-12.2 2.7-24.1 4.2-35.4 4.2-41.6 0-62.1-21.4-62.1-59.8v-82.4c0-6.8 2.4-8.9 9.2-8.9h16.4c6.8 0 8.9 2.1 8.9 8.9v81.2c0 19.6 10.7 29.4 32.4 29.4 9.8 0 19.9-1.5 30.6-4.2v-106.5c0-6.8 2.4-8.9 9.2-8.9z" style="fill:#f5f7fa"/>
+		</g>
+	</g>
+</g>
 </svg>

+ 1 - 0
resources/js/pages/Aliases.vue

@@ -131,6 +131,7 @@
     <vue-good-table
       v-if="initialAliases.length"
       @on-search="debounceToolips"
+      @on-page-change="debounceToolips"
       :columns="columns"
       :rows="rows"
       :search-options="{

+ 120 - 0
resources/js/pages/Domains.vue

@@ -114,6 +114,23 @@
             />
           </div>
         </span>
+        <span v-else-if="props.column.field === 'default_recipient'">
+          <div v-if="props.row.default_recipient">
+            {{ props.row.default_recipient.email | truncate(30) }}
+            <icon
+              name="edit"
+              class="ml-2 inline-block w-6 h-6 text-grey-200 fill-current cursor-pointer"
+              @click.native="openDomainDefaultRecipientModal(props.row)"
+            />
+          </div>
+          <div class="flex justify-center" v-else>
+            <icon
+              name="plus"
+              class="block w-6 h-6 text-grey-200 fill-current cursor-pointer"
+              @click.native="openDomainDefaultRecipientModal(props.row)"
+            />
+          </div>
+        </span>
         <span v-else-if="props.column.field === 'aliases_count'">
           {{ props.row.aliases.length }}
         </span>
@@ -225,6 +242,54 @@
       </div>
     </Modal>
 
+    <Modal :open="domainDefaultRecipientModalOpen" @close="closeDomainDefaultRecipientModal">
+      <div class="max-w-lg w-full bg-white rounded-lg shadow-2xl px-6 py-6">
+        <h2
+          class="font-semibold text-grey-900 text-2xl leading-tight border-b-2 border-grey-100 pb-4"
+        >
+          Update Default Recipient
+        </h2>
+        <p class="my-4 text-grey-700">
+          Select the default recipient for this domain. This overrides the default recipient in your
+          account settings. Leave it empty if you would like to use the default recipient in your
+          account settings.
+        </p>
+        <multiselect
+          v-model="defaultRecipient"
+          :options="recipientOptions"
+          :multiple="false"
+          :close-on-select="true"
+          :clear-on-select="false"
+          :searchable="false"
+          :allow-empty="true"
+          placeholder="Select recipient"
+          label="email"
+          track-by="email"
+          :preselect-first="false"
+          :show-labels="false"
+        >
+        </multiselect>
+        <div class="mt-6">
+          <button
+            type="button"
+            @click="editDefaultRecipient()"
+            class="px-4 py-3 text-cyan-900 font-semibold bg-cyan-400 hover:bg-cyan-300 border border-transparent rounded focus:outline-none"
+            :class="editDefaultRecipientLoading ? 'cursor-not-allowed' : ''"
+            :disabled="editDefaultRecipientLoading"
+          >
+            Update Default Recipient
+            <loader v-if="editDefaultRecipientLoading" />
+          </button>
+          <button
+            @click="closeDomainDefaultRecipientModal()"
+            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="deleteDomainModalOpen" @close="closeDeleteModal">
       <div class="max-w-lg w-full bg-white rounded-lg shadow-2xl p-6">
         <h2
@@ -263,6 +328,7 @@
 import Modal from './../components/Modal.vue'
 import Toggle from './../components/Toggle.vue'
 import tippy from 'tippy.js'
+import Multiselect from 'vue-multiselect'
 
 export default {
   props: {
@@ -274,10 +340,15 @@ export default {
       type: String,
       required: true,
     },
+    recipientOptions: {
+      type: Array,
+      required: true,
+    },
   },
   components: {
     Modal,
     Toggle,
+    Multiselect,
   },
   mounted() {
     this.addTooltips()
@@ -294,6 +365,10 @@ export default {
       deleteDomainLoading: false,
       deleteDomainModalOpen: false,
       recheckRecordsLoading: false,
+      domainDefaultRecipientModalOpen: false,
+      defaultRecipientDomainToEdit: {},
+      defaultRecipient: {},
+      editDefaultRecipientLoading: false,
       errors: {},
       columns: [
         {
@@ -310,6 +385,12 @@ export default {
           field: 'description',
           width: '500px',
         },
+        {
+          label: 'Default Recipient',
+          field: 'default_recipient',
+          sortable: false,
+          globalSearchDisabled: true,
+        },
         {
           label: 'Alias Count',
           field: 'aliases_count',
@@ -428,6 +509,16 @@ export default {
       this.deleteDomainModalOpen = false
       this.domainIdToDelete = null
     },
+    openDomainDefaultRecipientModal(domain) {
+      this.domainDefaultRecipientModalOpen = true
+      this.defaultRecipientDomainToEdit = domain
+      this.defaultRecipient = domain.default_recipient
+    },
+    closeDomainDefaultRecipientModal() {
+      this.domainDefaultRecipientModalOpen = false
+      this.defaultRecipientDomainToEdit = {}
+      this.defaultRecipient = {}
+    },
     editDomain(domain) {
       if (this.domainDescriptionToEdit.length > 100) {
         return this.error('Description cannot be more than 100 characters')
@@ -455,6 +546,35 @@ export default {
           this.error()
         })
     },
+    editDefaultRecipient() {
+      this.editDefaultRecipientLoading = true
+
+      axios
+        .patch(
+          `/domains/${this.defaultRecipientDomainToEdit.id}/default-recipient`,
+          JSON.stringify({
+            default_recipient: this.defaultRecipient ? this.defaultRecipient.id : '',
+          }),
+          {
+            headers: { 'Content-Type': 'application/json' },
+          }
+        )
+        .then(response => {
+          let domain = _.find(this.rows, ['id', this.defaultRecipientDomainToEdit.id])
+          domain.default_recipient = this.defaultRecipient
+
+          this.domainDefaultRecipientModalOpen = false
+          this.editDefaultRecipientLoading = false
+          this.defaultRecipient = {}
+          this.success("Domain's default recipient updated")
+        })
+        .catch(error => {
+          this.domainDefaultRecipientModalOpen = false
+          this.editDefaultRecipientLoading = false
+          this.defaultRecipient = {}
+          this.error()
+        })
+    },
     activateDomain(id) {
       axios
         .post(

+ 1 - 1
resources/views/domains/index.blade.php

@@ -4,6 +4,6 @@
     <div class="container py-8">
         @include('shared.status')
 
-        <domains :initial-domains="{{json_encode($domains)}}" hostname="{{config('anonaddy.hostname')}}" />
+        <domains :initial-domains="{{json_encode($domains)}}" hostname="{{config('anonaddy.hostname')}}" :recipient-options="{{ json_encode(Auth::user()->verifiedRecipients) }}" />
     </div>
 @endsection

+ 3 - 1
resources/views/nav/nav.blade.php

@@ -3,7 +3,9 @@
     <nav class="bg-indigo-900 py-4 shadow">
         <div class="container flex items-center justify-between flex-wrap">
             <div class="flex items-center flex-shrink-0 text-white mr-6">
-                <img class="w-32" alt="AnonAddy Logo" src="/svg/logo.svg">
+                <a href="{{ route('aliases.index') }}">
+                    <img class="h-6" alt="AnonAddy Logo" src="/svg/icon-logo.svg">
+                </a>
             </div>
             <div class="block md:hidden">
                 <button @click="mobileNavActive = !mobileNavActive" class="flex items-center px-3 py-2 border rounded text-indigo-200 border-indigo-400 hover:text-white hover:border-white focus:outline-none">

+ 1 - 0
routes/web.php

@@ -46,6 +46,7 @@ Route::middleware(['auth', 'verified', '2fa'])->group(function () {
     Route::post('/domains', 'DomainController@store')->name('domains.store');
     Route::patch('/domains/{id}', 'DomainController@update')->name('domains.update');
     Route::delete('/domains/{id}', 'DomainController@destroy')->name('domains.destroy');
+    Route::patch('/domains/{id}/default-recipient', 'DomainDefaultRecipientController@update')->name('domains.default_recipient');
 
     Route::get('/domains/{id}/recheck', 'DomainVerificationController@recheck')->name('domain_verification.recheck');
 

+ 76 - 0
tests/Feature/DomainsTest.php

@@ -3,6 +3,7 @@
 namespace Tests\Feature;
 
 use App\Domain;
+use App\Recipient;
 use App\User;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Illuminate\Support\Carbon;
@@ -213,4 +214,79 @@ class DomainsTest extends TestCase
         $response->assertStatus(204);
         $this->assertEmpty($this->user->domains);
     }
+
+    /** @test */
+    public function user_can_update_domain_default_recipient()
+    {
+        $domain = factory(Domain::class)->create([
+            'user_id' => $this->user->id,
+            'domain_verified_at' => now()
+        ]);
+
+        $newDefaultRecipient = factory(Recipient::class)->create([
+            'user_id' => $this->user->id
+        ]);
+
+        $response = $this->json('PATCH', '/domains/'.$domain->id.'/default-recipient', [
+            'default_recipient' => $newDefaultRecipient->id
+        ]);
+
+        $response->assertStatus(200);
+        $this->assertDatabaseHas('domains', [
+            'id' => $domain->id,
+            'default_recipient_id' => $newDefaultRecipient->id
+        ]);
+
+        $this->assertEquals($newDefaultRecipient->email, $domain->refresh()->defaultRecipient->email);
+    }
+
+    /** @test */
+    public function user_cannot_update_domain_default_recipient_with_unverified_recipient()
+    {
+        $domain = factory(Domain::class)->create([
+            'user_id' => $this->user->id,
+            'domain_verified_at' => now()
+        ]);
+
+        $newDefaultRecipient = factory(Recipient::class)->create([
+            'user_id' => $this->user->id,
+            'email_verified_at' => null
+        ]);
+
+        $response = $this->json('PATCH', '/domains/'.$domain->id.'/default-recipient', [
+            'default_recipient' => $newDefaultRecipient->id
+        ]);
+
+        $response->assertStatus(404);
+        $this->assertDatabaseMissing('domains', [
+            'id' => $domain->id,
+            'default_recipient_id' => $newDefaultRecipient->id
+        ]);
+    }
+
+    /** @test */
+    public function user_can_remove_domain_default_recipient()
+    {
+        $defaultRecipient = factory(Recipient::class)->create([
+            'user_id' => $this->user->id
+        ]);
+
+        $domain = factory(Domain::class)->create([
+            'user_id' => $this->user->id,
+            'default_recipient_id' => $defaultRecipient->id,
+            'domain_verified_at' => now(),
+        ]);
+
+        $response = $this->json('PATCH', '/domains/'.$domain->id.'/default-recipient', [
+            'default_recipient' => ''
+        ]);
+
+        $response->assertStatus(200);
+        $this->assertDatabaseHas('domains', [
+            'id' => $domain->id,
+            'default_recipient_id' => null
+        ]);
+
+        $this->assertNull($domain->refresh()->defaultRecipient);
+    }
 }

+ 51 - 0
tests/Feature/ReceiveEmailTest.php

@@ -934,4 +934,55 @@ class ReceiveEmailTest extends TestCase
             return $mail->hasTo($this->user->email);
         });
     }
+
+    /** @test */
+    public function it_can_forward_email_for_custom_domain_with_default_recipient()
+    {
+        Mail::fake();
+
+        Mail::assertNothingSent();
+
+        $recipient = factory(Recipient::class)->create([
+            'user_id' => $this->user->id
+        ]);
+
+        $domain = factory(Domain::class)->create([
+            'user_id' => $this->user->id,
+            'default_recipient_id' => $recipient->id,
+            'domain' => 'example.com',
+            'domain_verified_at' => now()
+        ]);
+
+        $this->artisan(
+            'anonaddy:receive-email',
+            [
+                'file' => base_path('tests/emails/email_custom_domain.eml'),
+                '--sender' => 'will@anonaddy.com',
+                '--recipient' => ['ebay@example.com'],
+                '--local_part' => ['ebay'],
+                '--extension' => [''],
+                '--domain' => ['example.com'],
+                '--size' => '871'
+            ]
+        )->assertExitCode(0);
+
+        $this->assertDatabaseHas('aliases', [
+            'domain_id' => $domain->id,
+            'email' => 'ebay@example.com',
+            'local_part' => 'ebay',
+            'domain' => 'example.com',
+            'emails_forwarded' => 1,
+            'emails_blocked' => 0
+        ]);
+        $this->assertDatabaseHas('users', [
+            'id' => $this->user->id,
+            'username' => 'johndoe',
+            'bandwidth' => '871'
+        ]);
+        $this->assertEquals(1, $this->user->aliases()->count());
+
+        Mail::assertQueued(ForwardEmail::class, function ($mail) use ($recipient) {
+            return $mail->hasTo($recipient->email);
+        });
+    }
 }