Browse Source

Added settings to config

Will Browning 5 years ago
parent
commit
c6bf93f44c

+ 13 - 13
.env.example

@@ -1,8 +1,8 @@
-APP_NAME=Laravel
+APP_NAME=Example
 APP_ENV=local
 APP_ENV=local
 APP_KEY=
 APP_KEY=
 APP_DEBUG=true
 APP_DEBUG=true
-APP_URL=http://localhost
+APP_URL=https://example.com
 
 
 LOG_CHANNEL=stack
 LOG_CHANNEL=stack
 
 
@@ -30,8 +30,8 @@ MAIL_USERNAME=null
 MAIL_PASSWORD=null
 MAIL_PASSWORD=null
 MAIL_ENCRYPTION=null
 MAIL_ENCRYPTION=null
 
 
-MAIL_FROM_NAME=AnonAddy
-MAIL_FROM_ADDRESS=mailer@anonaddy.me
+MAIL_FROM_NAME=Example
+MAIL_FROM_ADDRESS=mailer@example.com
 
 
 PUSHER_APP_ID=
 PUSHER_APP_ID=
 PUSHER_APP_KEY=
 PUSHER_APP_KEY=
@@ -41,16 +41,16 @@ PUSHER_APP_CLUSTER=mt1
 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
 MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
 MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
 
 
-ENVOY_USER_AND_SERVER=username@server
-ENVOY_BASE_DIR=/path/to/app/directory
-ENVOY_RUN_TESTS="ssh -tt -p22 vagrant@192.168.10.10 '/path/to/homestead/app/vendor/bin/phpunit --configuration /path/to/homestead/app/phpunit.xml'"
-
-ANONADDY_RETURN_PATH=bounces@anonaddy.me
+ANONADDY_RETURN_PATH=bounces@example.com
 ANONADDY_ADMIN_USERNAME=johndoe
 ANONADDY_ADMIN_USERNAME=johndoe
-ANONADDY_DOMAIN=anonaddy.me
-ANONADDY_ALL_DOMAINS=anonaddy.me,anonaddy.com
+ANONADDY_ENABLE_REGISTRATION=true
+ANONADDY_DOMAIN=example.com
+ANONADDY_HOSTNAME=mail.example.com
+ANONADDY_DNS_RESOLVER=127.0.0.1
+ANONADDY_ALL_DOMAINS=example.com,example2.com
 ANONADDY_SECRET=long-random-string
 ANONADDY_SECRET=long-random-string
 ANONADDY_LIMIT=200
 ANONADDY_LIMIT=200
-ANONADDY_NEWSLETTER_URL=https://newsletter.yourdomain.com/subscribe
-ANONADDY_NEWSLETTER_LIST=your-list-id
+ANONADDY_BANDWIDTH_LIMIT=104857600
+ANONADDY_NEW_ALIAS_LIMIT=10
+ANONADDY_ADDITIONAL_USERNAME_LIMIT=3
 ANONADDY_SIGNING_KEY_FINGERPRINT=your-signing-key-fingerprint
 ANONADDY_SIGNING_KEY_FINGERPRINT=your-signing-key-fingerprint

+ 0 - 175
Envoy.blade.php

@@ -1,175 +0,0 @@
-@setup
-require __DIR__."/vendor/autoload.php";
-$dotenv = Dotenv\Dotenv::create(__DIR__, ".env");
-$dotenv->load();
-
-$userAndServer = getenv("ENVOY_USER_AND_SERVER");
-$repository = "anonaddy/anonaddy";
-$baseDir = getenv("ENVOY_BASE_DIR");
-$releasesDir = "{$baseDir}/releases";
-$persistentDir = "{$baseDir}/persistent";
-$currentDir = "{$baseDir}/current";
-$newReleaseName = date("Ymd-His");
-$newReleaseDir = "{$releasesDir}/{$newReleaseName}";
-
-function logMessage($message) {
-  return "echo '\033[32m" .$message. "\033[0m';\n";
-}
-@endsetup
-
-@servers(["local" => "127.0.0.1", "remote" => $userAndServer])
-
-@story("deploy")
-startDeployment
-runTests
-cloneRepository
-runComposer
-runNpm
-generateAssets
-updateSymlinks
-optimizeInstallation
-migrateDatabase
-blessNewRelease
-cleanOldReleases
-finishDeploy
-@endstory
-
-@story("deploy-code")
-runTests
-deployOnlyCode
-@endstory
-
-@story("deploy-rollback")
-deploymentRollback
-@endstory
-
-@task("startDeployment", ["on" => "local"])
-{{ logMessage("🏃  Starting deployment...") }}
-@endtask
-
-@task("runTests", ["on" => "local"])
-{{ logMessage("💻  Running Unit Tests...") }}
-env -i bash -c "{{ getenv('ENVOY_RUN_TESTS') }}" || exit 1
-@endtask
-
-@task("cloneRepository", ["on" => "remote"])
-{{ logMessage("🌀  Cloning repository...") }}
-[ -d {{ $releasesDir }} ] || mkdir {{ $releasesDir }}
-[ -d {{ $persistentDir }} ] || mkdir {{ $persistentDir }}
-[ -d {{ $persistentDir }}/storage ] || mkdir {{ $persistentDir }}/storage
-cd {{ $releasesDir }}
-
-# Create the release dir
-mkdir {{ $newReleaseDir }}
-
-# Clone the repo
-git clone --depth 1 git@github.com:{{ $repository }} {{ $newReleaseName }}
-
-# Configure sparse checkout
-cd {{ $newReleaseDir }}
-git config core.sparsecheckout true
-echo "*" > .git/info/sparse-checkout
-echo "!storage" >> .git/info/sparse-checkout
-echo "!public/build" >> .git/info/sparse-checkout
-git read-tree -mu HEAD
-
-# Mark release
-cd {{ $newReleaseDir }}
-echo "{{ $newReleaseName }}" > public/release-name.txt
-@endtask
-
-@task("runComposer", ["on" => "remote"])
-{{ logMessage("🚚  Running Composer...") }}
-cd {{ $newReleaseDir }}
-composer install --prefer-dist --no-scripts --no-dev -q -o
-@endtask
-
-@task("runNpm", ["on" => "remote"])
-{{ logMessage("📦  Running Npm...") }}
-cd {{ $newReleaseDir }}
-npm install --no-progress &> /dev/null
-@endtask
-
-@task("generateAssets", ["on" => "remote"])
-{{ logMessage("🌅  Generating assets...") }}
-cd {{ $newReleaseDir }}
-npm run production --no-progress &> /dev/null
-@endtask
-
-@task("updateSymlinks", ["on" => "remote"])
-{{ logMessage("🔗  Updating symlinks to persistent data...") }}
-# Remove the storage directory and replace with persistent data
-rm -rf {{ $newReleaseDir }}/storage
-cd {{ $newReleaseDir }}
-ln -nfs {{ $baseDir }}/persistent/storage storage
-
-# Import the environment config
-cd {{ $newReleaseDir }}
-ln -nfs {{ $baseDir }}/.env .env
-@endtask
-
-@task("optimizeInstallation", ["on" => "remote"])
-{{ logMessage("✨  Optimizing installation...") }}
-cd {{ $newReleaseDir }}
-php artisan clear-compiled
-@endtask
-
-@task("migrateDatabase", ["on" => "remote"])
-{{ logMessage("🙈  Migrating database...") }}
-cd {{ $newReleaseDir }}
-php artisan migrate --force
-@endtask
-
-@task("blessNewRelease", ["on" => "remote"])
-{{ logMessage("🙏  Blessing new release...") }}
-ln -nfs {{ $newReleaseDir }} {{ $currentDir }}
-cd {{ $newReleaseDir }}
-
-php artisan storage:link
-
-php artisan config:clear
-php artisan view:clear
-php artisan cache:clear
-
-php artisan config:cache
-php artisan view:cache
-php artisan route:cache
-
-php artisan queue:restart
-@endtask
-
-@task("cleanOldReleases", ["on" => "remote"])
-{{ logMessage("🚾  Cleaning up old releases...") }}
-# Delete all but the 5 most recent.
-cd {{ $releasesDir }}
-ls -dt {{ $releasesDir }}/* | tail -n +6 | xargs -d "\n" chown -R deployer .
-ls -dt {{ $releasesDir }}/* | tail -n +6 | xargs -d "\n" rm -rf
-@endtask
-
-@task("finishDeploy", ["on" => "local"])
-{{ logMessage("🚀  Application deployed!") }}
-@endtask
-
-@task("deployOnlyCode",["on" => "remote"])
-{{ logMessage("💻  Deploying code changes...") }}
-cd {{ $currentDir }}
-git pull origin master
-
-php artisan storage:link
-
-php artisan config:clear
-php artisan view:clear
-php artisan cache:clear
-
-php artisan config:cache
-php artisan view:cache
-php artisan route:cache
-
-php artisan queue:restart
-@endtask
-
-@task("deploymentRollback", ["on" => "remote"])
-cd {{ $releasesDir }}
-ln -nfs {{ $releasesDir }}/$(find . -maxdepth 1 -name "20*" | sort  | tail -n 2 | head -n1) {{ $baseDir }}/current
-echo "Rolled back to $(find . -maxdepth 1 -name "20*" | sort  | tail -n 2 | head -n1)"
-@endtask

+ 1 - 1
README.md

@@ -1,6 +1,6 @@
 # Anonymous Email Forwarding
 # Anonymous Email Forwarding
 
 
-This is the source code for [app.anonaddy.com](https://app.anonaddy.com).
+This is the source code for self-hosting AnonAddy.
 
 
 ## FAQ
 ## FAQ
 
 

+ 9 - 0
app/AdditionalUsername.php

@@ -33,6 +33,15 @@ class AdditionalUsername extends Model
         'active' => 'boolean'
         'active' => 'boolean'
     ];
     ];
 
 
+    public static function boot()
+    {
+        parent::boot();
+
+        AdditionalUsername::deleting(function ($username) {
+            DeletedUsername::create(['username' => $username->username]);
+        });
+    }
+
     /**
     /**
      * Set the username.
      * Set the username.
      */
      */

+ 9 - 31
app/Alias.php

@@ -88,52 +88,30 @@ class Alias extends Model
     }
     }
 
 
     /**
     /**
-     * Get the verified emails of recipients not using PGP for the email alias.
+     * Get the verified recipients for the email alias or the default recipient if none are set.
      */
      */
-    public function nonPgpRecipientEmails()
+    public function verifiedRecipientsOrDefault()
     {
     {
-        if ($this->verifiedRecipients()->count() === 0 && !$this->user->defaultRecipient->should_encrypt) {
-            return [$this->user->email];
-        }
-
-        return $this
-                ->verifiedRecipients()
-                ->where('should_encrypt', false)
-                ->get()
-                ->map(function ($recipient) {
-                    return $recipient->email;
-                })->toArray();
-    }
-
-    /**
-     * Check if the email alias has any recipients not using PGP.
-     */
-    public function hasNonPgpRecipients()
-    {
-        return count($this->nonPgpRecipientEmails()) > 0;
-    }
-
-    /**
-     * Get the verified recipients using PGP for the email alias.
-     */
-    public function recipientsUsingPgp()
-    {
-        if ($this->verifiedRecipients()->count() === 0 && $this->user->defaultRecipient->should_encrypt) {
+        if ($this->verifiedRecipients()->count() === 0) {
             return $this->user->defaultRecipient();
             return $this->user->defaultRecipient();
         }
         }
 
 
         return $this
         return $this
                 ->verifiedRecipients()
                 ->verifiedRecipients()
-                ->where('should_encrypt', true)
-                ->whereNotNull('fingerprint')
                 ->get();
                 ->get();
     }
     }
 
 
+    /**
+     * Deactivate the alias.
+     */
     public function deactivate()
     public function deactivate()
     {
     {
         $this->update(['active' => false]);
         $this->update(['active' => false]);
     }
     }
 
 
+    /**
+     * Activate the alias.
+     */
     public function activate()
     public function activate()
     {
     {
         $this->update(['active' => true]);
         $this->update(['active' => true]);

+ 11 - 18
app/Console/Commands/ReceiveEmail.php

@@ -68,7 +68,7 @@ class ReceiveEmail extends Command
 
 
             $recipients = $this->getRecipients();
             $recipients = $this->getRecipients();
 
 
-            // Divide the size of the email by the number of recipients (excluding any unsubscribe recipients) to prevent it being added multiple times
+            // Divide the size of the email by the number of recipients (excluding any unsubscribe recipients) to prevent it being added multiple times.
             $recipientCount = $recipients->where('domain', '!=', 'unsubscribe.'.config('anonaddy.domain'))->count();
             $recipientCount = $recipients->where('domain', '!=', 'unsubscribe.'.config('anonaddy.domain'))->count();
 
 
             $this->size = $this->option('size') / ($recipientCount ? $recipientCount : 1);
             $this->size = $this->option('size') / ($recipientCount ? $recipientCount : 1);
@@ -82,7 +82,7 @@ class ReceiveEmail extends Command
                     })
                     })
                     ->first();
                     ->first();
 
 
-                $subdomain = substr($recipient['domain'], 0, strrpos($recipient['domain'], '.'.$parentDomain)); // e.g. johndoe
+                $subdomain = substr($recipient['domain'], 0, strrpos($recipient['domain'], '.'.$parentDomain));
 
 
                 if ($subdomain === 'unsubscribe') {
                 if ($subdomain === 'unsubscribe') {
                     $this->handleUnsubscribe($recipient);
                     $this->handleUnsubscribe($recipient);
@@ -91,19 +91,18 @@ class ReceiveEmail extends Command
 
 
                 $user = User::where('username', $subdomain)->first();
                 $user = User::where('username', $subdomain)->first();
 
 
-                // If no user is found for the subdomain check if it is a custom or root domain instead
                 if (is_null($user)) {
                 if (is_null($user)) {
-                    // check if this is a custom domain
+                    // Check if this is a custom domain.
                     if ($customDomain = Domain::where('domain', $recipient['domain'])->first()) {
                     if ($customDomain = Domain::where('domain', $recipient['domain'])->first()) {
                         $user = $customDomain->user;
                         $user = $customDomain->user;
                     }
                     }
 
 
-                    // check if this is an additional username
+                    // Check if this is an additional username.
                     if ($additionalUsername = AdditionalUsername::where('username', $subdomain)->first()) {
                     if ($additionalUsername = AdditionalUsername::where('username', $subdomain)->first()) {
                         $user = $additionalUsername->user;
                         $user = $additionalUsername->user;
                     }
                     }
 
 
-                    // check if this is a uuid generated alias
+                    // Check if this is a uuid generated alias.
                     if ($alias = Alias::find($recipient['local_part'])) {
                     if ($alias = Alias::find($recipient['local_part'])) {
                         $user = $alias->user;
                         $user = $alias->user;
                     } elseif ($recipient['domain'] === $parentDomain && !empty(config('anonaddy.admin_username'))) {
                     } elseif ($recipient['domain'] === $parentDomain && !empty(config('anonaddy.admin_username'))) {
@@ -111,14 +110,14 @@ class ReceiveEmail extends Command
                     }
                     }
                 }
                 }
 
 
-                // If there is still no user or the user has no verified default recipient then continue
+                // If there is still no user or the user has no verified default recipient then continue.
                 if (is_null($user) || !$user->hasVerifiedDefaultRecipient()) {
                 if (is_null($user) || !$user->hasVerifiedDefaultRecipient()) {
                     continue;
                     continue;
                 }
                 }
 
 
                 $this->checkRateLimit($user);
                 $this->checkRateLimit($user);
 
 
-                // check whether this email is a reply or a new email to be forwarded
+                // Check whether this email is a reply or a new email to be forwarded.
                 if ($recipient['extension'] === sha1(config('anonaddy.secret').$displayTo)) {
                 if ($recipient['extension'] === sha1(config('anonaddy.secret').$displayTo)) {
                     $this->handleReply($user, $recipient, $displayTo);
                     $this->handleReply($user, $recipient, $displayTo);
                 } else {
                 } else {
@@ -177,7 +176,7 @@ class ReceiveEmail extends Command
         ]);
         ]);
 
 
         if (!isset($alias->id)) {
         if (!isset($alias->id)) {
-            // this is a new alias
+            // This is a new alias.
             if ($user->hasExceededNewAliasLimit()) {
             if ($user->hasExceededNewAliasLimit()) {
                 $this->error('4.2.1 New aliases per hour limit exceeded for user ' . $user->username . '.');
                 $this->error('4.2.1 New aliases per hour limit exceeded for user ' . $user->username . '.');
 
 
@@ -211,18 +210,12 @@ class ReceiveEmail extends Command
 
 
         $emailData = new EmailData($this->parser);
         $emailData = new EmailData($this->parser);
 
 
-        $alias->recipientsUsingPgp()->each(function ($recipient) use ($alias, $emailData) {
-            $message = (new ForwardEmail($alias, $emailData, $recipient->fingerprint))->onQueue('default');
+        $alias->verifiedRecipientsOrDefault()->each(function ($recipient) use ($alias, $emailData) {
+            $message = (new ForwardEmail($alias, $emailData, $recipient->should_encrypt ? $recipient->fingerprint : null))->onQueue('default');
 
 
             Mail::to($recipient->email)->queue($message);
             Mail::to($recipient->email)->queue($message);
         });
         });
 
 
-        if ($alias->hasNonPgpRecipients()) {
-            $message = (new ForwardEmail($alias, $emailData))->onQueue('default');
-
-            Mail::to($alias->nonPgpRecipientEmails())->queue($message);
-        }
-
         if (!Mail::failures()) {
         if (!Mail::failures()) {
             $alias->increment('emails_forwarded');
             $alias->increment('emails_forwarded');
 
 
@@ -283,7 +276,7 @@ class ReceiveEmail extends Command
 
 
     protected function exitIfFromSelf()
     protected function exitIfFromSelf()
     {
     {
-        // To prevent recipient alias infinite nested looping
+        // To prevent recipient alias infinite nested looping.
         if (in_array($this->option('sender'), [config('mail.from.address'), config('anonaddy.return_path')])) {
         if (in_array($this->option('sender'), [config('mail.from.address'), config('anonaddy.return_path')])) {
             exit(0);
             exit(0);
         }
         }

+ 2 - 2
app/Domain.php

@@ -105,9 +105,9 @@ class Domain extends Model
      */
      */
     public function checkVerification()
     public function checkVerification()
     {
     {
-        $dns = new Dns($this->domain, '1.1.1.1');
+        $dns = new Dns($this->domain, config('anonaddy.dns_resolver'));
 
 
-        if (Str::contains($dns->getRecords('MX'), 'MX 10 mail.anonaddy.me.')) {
+        if (Str::contains($dns->getRecords('MX'), 'MX 10 ' . config('anonaddy.hostname') . '.')) {
             $this->markDomainAsVerified();
             $this->markDomainAsVerified();
         }
         }
     }
     }

+ 2 - 2
app/Http/Controllers/AliasController.php

@@ -32,9 +32,9 @@ class AliasController extends Controller
 
 
         $alias = user()->aliases()->create([
         $alias = user()->aliases()->create([
             'id' => $uuid,
             'id' => $uuid,
-            'email' => $uuid . '@anonaddy.me',
+            'email' => $uuid.'@'.config('anonaddy.domain'),
             'local_part' => $uuid,
             'local_part' => $uuid,
-            'domain' => 'anonaddy.me'
+            'domain' => config('anonaddy.domain')
         ]);
         ]);
 
 
         return new AliasResource($alias->fresh());
         return new AliasResource($alias->fresh());

+ 0 - 7
app/Http/Controllers/Auth/RegisterController.php

@@ -3,7 +3,6 @@
 namespace App\Http\Controllers\Auth;
 namespace App\Http\Controllers\Auth;
 
 
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
-use App\Jobs\SubscribeToNewsletter;
 use App\Recipient;
 use App\Recipient;
 use App\Rules\NotBlacklisted;
 use App\Rules\NotBlacklisted;
 use App\Rules\NotDeletedUsername;
 use App\Rules\NotDeletedUsername;
@@ -73,8 +72,6 @@ class RegisterController extends Controller
                 new RegisterUniqueRecipient
                 new RegisterUniqueRecipient
             ],
             ],
             'password' => ['required', 'min:8'],
             'password' => ['required', 'min:8'],
-            'newsletter' => ['nullable'],
-            'terms' => ['required', 'accepted'],
         ], [
         ], [
             'captcha.captcha' => 'The text entered was incorrect, please try again.',
             'captcha.captcha' => 'The text entered was incorrect, please try again.',
         ])
         ])
@@ -98,10 +95,6 @@ class RegisterController extends Controller
             'user_id' => $userId
             'user_id' => $userId
         ]);
         ]);
 
 
-        if (isset($data['newsletter'])) {
-            SubscribeToNewsletter::dispatch($data['email']);
-        }
-
         $twoFactor = app('pragmarx.google2fa');
         $twoFactor = app('pragmarx.google2fa');
 
 
         return User::create([
         return User::create([

+ 1 - 1
app/Http/Requests/UpdateBannerLocationRequest.php

@@ -13,7 +13,7 @@ class UpdateBannerLocationRequest extends FormRequest
      */
      */
     public function authorize()
     public function authorize()
     {
     {
-        return true; // Pro plan
+        return true;
     }
     }
 
 
     /**
     /**

+ 1 - 1
app/Http/Requests/UpdateFromNameRequest.php

@@ -13,7 +13,7 @@ class UpdateFromNameRequest extends FormRequest
      */
      */
     public function authorize()
     public function authorize()
     {
     {
-        return true; // Pro plan
+        return true;
     }
     }
 
 
     /**
     /**

+ 2 - 2
app/Jobs/DeleteAccount.php

@@ -38,9 +38,9 @@ class DeleteAccount implements ShouldQueue
         $this->user->aliasRecipients()->delete();
         $this->user->aliasRecipients()->delete();
         $this->user->aliases()->whereNull('domain_id')->forceDelete();
         $this->user->aliases()->whereNull('domain_id')->forceDelete();
         $this->user->aliases()->delete();
         $this->user->aliases()->delete();
-        $this->user->recipients()->get()->each->delete(); // in order to fire deleting model event
+        $this->user->recipients()->get()->each->delete(); // In order to fire deleting model event.
         $this->user->domains()->delete();
         $this->user->domains()->delete();
-        $this->user->additionalUsernames()->delete();
+        $this->user->additionalUsernames()->get()->each->delete(); // In order to fire deleting model event.
         $this->user->delete();
         $this->user->delete();
     }
     }
 }
 }

+ 0 - 48
app/Jobs/SubscribeToNewsletter.php

@@ -1,48 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-
-class SubscribeToNewsletter implements ShouldQueue
-{
-    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
-
-    protected $email;
-
-    /**
-     * Create a new job instance.
-     *
-     * @return void
-     */
-    public function __construct($email)
-    {
-        $this->email = $email;
-    }
-
-    /**
-     * Execute the job.
-     *
-     * @return void
-     */
-    public function handle()
-    {
-        $data = [
-            'email' => $this->email,
-            'list' => config('anonaddy.newsletter_list'),
-            'gdpr' => "true"
-        ];
-
-        $ch = curl_init(config('anonaddy.newsletter_url'));
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-        curl_setopt($ch, CURLOPT_POST, true);
-        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
-
-        curl_exec($ch);
-        curl_close($ch);
-    }
-}

+ 3 - 4
app/User.php

@@ -201,8 +201,7 @@ class User extends Authenticatable implements MustVerifyEmail
 
 
     public function getBandwidthLimit()
     public function getBandwidthLimit()
     {
     {
-        // TODO check user's limit and return
-        return 104857600;
+        return config('anonaddy.bandwidth_limit');
     }
     }
 
 
     public function getBandwidthLimitMb()
     public function getBandwidthLimitMb()
@@ -221,12 +220,12 @@ class User extends Authenticatable implements MustVerifyEmail
         return $this
         return $this
                 ->aliases()
                 ->aliases()
                 ->where('created_at', '>=', now()->subHour())
                 ->where('created_at', '>=', now()->subHour())
-                ->count() >= 10; // TODO update for different plans
+                ->count() >= config('anonaddy.new_alias_hourly_limit');
     }
     }
 
 
     public function hasReachedAdditionalUsernameLimit()
     public function hasReachedAdditionalUsernameLimit()
     {
     {
-        return $this->username_count >= 3;
+        return $this->username_count >= config('anonaddy.additional_username_limit');
     }
     }
 
 
     public function isVerifiedRecipient($email)
     public function isVerifiedRecipient($email)

+ 38 - 38
composer.lock

@@ -46,9 +46,9 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Ben Scholzen 'DASPRiD'",
                     "name": "Ben Scholzen 'DASPRiD'",
+                    "role": "Developer",
                     "email": "mail@dasprids.de",
                     "email": "mail@dasprids.de",
-                    "homepage": "http://www.dasprids.de",
-                    "role": "Developer"
+                    "homepage": "http://www.dasprids.de"
                 }
                 }
             ],
             ],
             "description": "BaconQrCode is a QR code generator for PHP.",
             "description": "BaconQrCode is a QR code generator for PHP.",
@@ -1583,15 +1583,15 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Paragon Initiative Enterprises",
                     "name": "Paragon Initiative Enterprises",
+                    "role": "Maintainer",
                     "email": "security@paragonie.com",
                     "email": "security@paragonie.com",
-                    "homepage": "https://paragonie.com",
-                    "role": "Maintainer"
+                    "homepage": "https://paragonie.com"
                 },
                 },
                 {
                 {
                     "name": "Steve 'Sc00bz' Thomas",
                     "name": "Steve 'Sc00bz' Thomas",
+                    "role": "Original Developer",
                     "email": "steve@tobtu.com",
                     "email": "steve@tobtu.com",
-                    "homepage": "https://www.tobtu.com",
-                    "role": "Original Developer"
+                    "homepage": "https://www.tobtu.com"
                 }
                 }
             ],
             ],
             "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
             "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
@@ -1831,8 +1831,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Antonio Carlos Ribeiro",
                     "name": "Antonio Carlos Ribeiro",
-                    "email": "acr@antoniocarlosribeiro.com",
-                    "role": "Creator & Designer"
+                    "role": "Creator & Designer",
+                    "email": "acr@antoniocarlosribeiro.com"
                 }
                 }
             ],
             ],
             "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
             "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
@@ -1902,8 +1902,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Antonio Carlos Ribeiro",
                     "name": "Antonio Carlos Ribeiro",
-                    "email": "acr@antoniocarlosribeiro.com",
-                    "role": "Creator & Designer"
+                    "role": "Creator & Designer",
+                    "email": "acr@antoniocarlosribeiro.com"
                 }
                 }
             ],
             ],
             "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
             "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
@@ -1958,8 +1958,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Antonio Carlos Ribeiro",
                     "name": "Antonio Carlos Ribeiro",
-                    "email": "acr@antoniocarlosribeiro.com",
-                    "role": "Creator & Designer"
+                    "role": "Creator & Designer",
+                    "email": "acr@antoniocarlosribeiro.com"
                 }
                 }
             ],
             ],
             "description": "QR Code package for Google2FA",
             "description": "QR Code package for Google2FA",
@@ -3985,8 +3985,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Tijs Verkoyen",
                     "name": "Tijs Verkoyen",
-                    "email": "css_to_inline_styles@verkoyen.eu",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "css_to_inline_styles@verkoyen.eu"
                 }
                 }
             ],
             ],
             "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.",
             "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.",
@@ -4800,18 +4800,18 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Arne Blankerts",
                     "name": "Arne Blankerts",
-                    "email": "arne@blankerts.de",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "arne@blankerts.de"
                 },
                 },
                 {
                 {
                     "name": "Sebastian Heuer",
                     "name": "Sebastian Heuer",
-                    "email": "sebastian@phpeople.de",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "sebastian@phpeople.de"
                 },
                 },
                 {
                 {
                     "name": "Sebastian Bergmann",
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "sebastian@phpunit.de"
                 }
                 }
             ],
             ],
             "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
             "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
@@ -4847,18 +4847,18 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Arne Blankerts",
                     "name": "Arne Blankerts",
-                    "email": "arne@blankerts.de",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "arne@blankerts.de"
                 },
                 },
                 {
                 {
                     "name": "Sebastian Heuer",
                     "name": "Sebastian Heuer",
-                    "email": "sebastian@phpeople.de",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "sebastian@phpeople.de"
                 },
                 },
                 {
                 {
                     "name": "Sebastian Bergmann",
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "sebastian@phpunit.de"
                 }
                 }
             ],
             ],
             "description": "Library for handling version information and constraints",
             "description": "Library for handling version information and constraints",
@@ -5231,8 +5231,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Sebastian Bergmann",
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
+                    "role": "lead",
+                    "email": "sebastian@phpunit.de"
                 }
                 }
             ],
             ],
             "description": "FilterIterator implementation that filters files based on a list of suffixes.",
             "description": "FilterIterator implementation that filters files based on a list of suffixes.",
@@ -5273,8 +5273,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Sebastian Bergmann",
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
+                    "role": "lead",
+                    "email": "sebastian@phpunit.de"
                 }
                 }
             ],
             ],
             "description": "Simple template engine.",
             "description": "Simple template engine.",
@@ -5322,8 +5322,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Sebastian Bergmann",
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
+                    "role": "lead",
+                    "email": "sebastian@phpunit.de"
                 }
                 }
             ],
             ],
             "description": "Utility class for timing",
             "description": "Utility class for timing",
@@ -6029,8 +6029,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Sebastian Bergmann",
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
+                    "role": "lead",
+                    "email": "sebastian@phpunit.de"
                 }
                 }
             ],
             ],
             "description": "Collection of value objects that represent the types of the PHP type system",
             "description": "Collection of value objects that represent the types of the PHP type system",
@@ -6072,8 +6072,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Sebastian Bergmann",
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
+                    "role": "lead",
+                    "email": "sebastian@phpunit.de"
                 }
                 }
             ],
             ],
             "description": "Library that helps with managing the version number of Git-hosted PHP projects",
             "description": "Library that helps with managing the version number of Git-hosted PHP projects",
@@ -6326,8 +6326,8 @@
             "authors": [
             "authors": [
                 {
                 {
                     "name": "Arne Blankerts",
                     "name": "Arne Blankerts",
-                    "email": "arne@blankerts.de",
-                    "role": "Developer"
+                    "role": "Developer",
+                    "email": "arne@blankerts.de"
                 }
                 }
             ],
             ],
             "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
             "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",

+ 62 - 12
config/anonaddy.php

@@ -19,31 +19,67 @@ return [
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     |
     |
     | If set this value will be used and allow you to receive forwarded emails
     | If set this value will be used and allow you to receive forwarded emails
-    | at the root domain, e.g. @anonaddy.me aswell as @username.anonaddy.me
+    | at the root domain, e.g. @example.com aswell as @username.example.com
     |
     |
     */
     */
 
 
     'admin_username' => env('ANONADDY_ADMIN_USERNAME'),
     'admin_username' => env('ANONADDY_ADMIN_USERNAME'),
 
 
+    /*
+    |--------------------------------------------------------------------------
+    | Enable Registration
+    |--------------------------------------------------------------------------
+    |
+    | If set to false this will prevent new users from registering on the site
+    | useful if you are self-hosting and do not want anyone else to be able to register
+    |
+    */
+
+    'enable_registration' => env('ANONADDY_ENABLE_REGISTRATION', true),
+
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     | Domain
     | Domain
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     |
     |
     | If set and you are self hosting AnonAddy then a check will be done so that you can
     | If set and you are self hosting AnonAddy then a check will be done so that you can
-    | receive email at the root domain, e.g. @yourdomain.com aswell as @username.yourdomain.com
+    | receive email at the root domain, e.g. @example.com aswell as @username.example.com
     |
     |
     */
     */
 
 
     'domain' => env('ANONADDY_DOMAIN'),
     'domain' => env('ANONADDY_DOMAIN'),
 
 
+    /*
+    |--------------------------------------------------------------------------
+    | Hostname
+    |--------------------------------------------------------------------------
+    |
+    | This value is your FQDN hostname for your server e.g. mail.example.com
+    | it is used to validate records on custom domains that are added by users
+    |
+    */
+
+    'hostname' => env('ANONADDY_HOSTNAME'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | DNS Resolver
+    |--------------------------------------------------------------------------
+    |
+    | This value is used when validating records on custom domains that are added
+    | by users, if you don't have a local caching name server you can use 1.1.1.1 etc.
+    |
+    */
+
+    'dns_resolver' => env('ANONADDY_DNS_RESOLVER', '127.0.0.1'),
+
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     | All Domains
     | All Domains
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     |
     |
-    | If you would like to have other domains to use e.g. @username.yourdomain2.com
-    | enter a comma separated list in your .env file like so, anonaddy.me,anonaddy.com
+    | If you would like to have other domains to use e.g. @username.example2.com
+    | enter a comma separated list in your .env file like so, example.com,example2.com
     |
     |
     */
     */
 
 
@@ -63,7 +99,7 @@ return [
 
 
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
-    | Limit
+    | Hourly Email Limit
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     |
     |
     | This value is an integer that determines the number of emails a user can forward
     | This value is an integer that determines the number of emails a user can forward
@@ -71,29 +107,43 @@ return [
     |
     |
     */
     */
 
 
-    'limit' => env('ANONADDY_LIMIT'),
+    'limit' => env('ANONADDY_LIMIT', 200),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Monthly Bandwidth Limit
+    |--------------------------------------------------------------------------
+    |
+    | This value is an integer that determines the monthly bandwidth
+    | limit for users in bytes the default value is 104857600 which is 100MB
+    |
+    */
+
+    'bandwidth_limit' => env('ANONADDY_BANDWIDTH_LIMIT', 104857600),
 
 
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
-    | Newsletter URL
+    | New Alias Hourly Limit
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     |
     |
-    | This value is the url to subscribe new registrations to the newsletter if they opt in
+    | This value is an integer that determines the number of new aliases
+    | a user can create each hour, the default value is 10 aliases per hour
     |
     |
     */
     */
 
 
-    'newsletter_url' => env('ANONADDY_NEWSLETTER_URL'),
+    'new_alias_hourly_limit' => env('ANONADDY_NEW_ALIAS_LIMIT', 10),
 
 
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
-    | Newsletter List
+    | Additional Username Limit
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     |
     |
-    | This value is the ID of the list to subscribe to
+    | This value is an integer that determines the number of additional
+    | usernames a user can add to their account, the default value is 3
     |
     |
     */
     */
 
 
-    'newsletter_list' => env('ANONADDY_NEWSLETTER_LIST'),
+    'additional_username_limit' => env('ANONADDY_ADDITIONAL_USERNAME_LIMIT', 3),
 
 
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------

+ 10 - 6
resources/js/pages/Aliases.vue

@@ -467,7 +467,7 @@
         </p>
         </p>
         <p class="mb-4">
         <p class="mb-4">
           Let's say you're signing up to <b>example.com</b> you could enter
           Let's say you're signing up to <b>example.com</b> you could enter
-          <b>example@{{ domain }}</b> (or .me) as your email address.
+          <b>example@{{ subdomain }}</b> as your email address.
         </p>
         </p>
         <p class="mb-4">
         <p class="mb-4">
           The alias will show up here automatically as soon as it has forwarded its first email.
           The alias will show up here automatically as soon as it has forwarded its first email.
@@ -477,7 +477,7 @@
           together!
           together!
         </p>
         </p>
         <p class="mb-4">
         <p class="mb-4">
-          Try it out now by sending an email to <b>first@{{ domain }}</b> and then refresh this
+          Try it out now by sending an email to <b>first@{{ subdomain }}</b> and then refresh this
           page.
           page.
         </p>
         </p>
         <h3 class="mb-4 text-xl text-indigo-800 font-semibold">
         <h3 class="mb-4 text-xl text-indigo-800 font-semibold">
@@ -488,7 +488,7 @@
           like this:
           like this:
         </p>
         </p>
         <p class="mb-4">
         <p class="mb-4">
-          <b>86064c92-da41-443e-a2bf-5a7b0247842f@anonaddy.me</b>
+          <b>86064c92-da41-443e-a2bf-5a7b0247842f@{{ domain }}</b>
         </p>
         </p>
       </div>
       </div>
     </div>
     </div>
@@ -502,11 +502,11 @@
         </h2>
         </h2>
         <p class="mt-4 text-grey-700">
         <p class="mt-4 text-grey-700">
           This will generate a new unique alias in the form of<br /><br />
           This will generate a new unique alias in the form of<br /><br />
-          86064c92-da41-443e-a2bf-5a7b0247842f@anonaddy.me<br /><br />
+          86064c92-da41-443e-a2bf-5a7b0247842f@{{ domain }}<br /><br />
           Useful if you do not wish to include your username in the email as a potential link
           Useful if you do not wish to include your username in the email as a potential link
           between aliases.<br /><br />
           between aliases.<br /><br />
-          Other aliases e.g. alias@{{ domain }} or .me are created automatically when they receive
-          their first email.
+          Other aliases e.g. alias@{{ subdomain }} are created automatically when they receive their
+          first email.
         </p>
         </p>
         <div class="mt-6">
         <div class="mt-6">
           <button
           <button
@@ -643,6 +643,10 @@ export default {
       type: String,
       type: String,
       required: true,
       required: true,
     },
     },
+    subdomain: {
+      type: String,
+      required: true,
+    },
     bandwidthMb: {
     bandwidthMb: {
       type: Number,
       type: Number,
       required: true,
       required: true,

+ 8 - 2
resources/js/pages/Domains.vue

@@ -286,7 +286,8 @@
         </p>
         </p>
         <p class="mb-4">
         <p class="mb-4">
           Host: <b>@</b><br />
           Host: <b>@</b><br />
-          Value: <b>mail.anonaddy.me</b><br />
+          Value: <b>{{ hostname }}</b
+          ><br />
           Priority: <b>10</b><br />
           Priority: <b>10</b><br />
           TTL: <b>3600</b>
           TTL: <b>3600</b>
         </p>
         </p>
@@ -306,7 +307,8 @@
         <p class="mt-4 text-grey-700">
         <p class="mt-4 text-grey-700">
           Make sure you add the following MX record to your domain.<br /><br />
           Make sure you add the following MX record to your domain.<br /><br />
           Host: <b>@</b><br />
           Host: <b>@</b><br />
-          Value: <b>mail.anonaddy.me</b><br />
+          Value: <b>{{ hostname }}</b
+          ><br />
           Priority: <b>10</b><br />
           Priority: <b>10</b><br />
           TTL: <b>3600</b><br /><br />
           TTL: <b>3600</b><br /><br />
           Just include the domain/subdomain e.g. example.com without any http protocol.
           Just include the domain/subdomain e.g. example.com without any http protocol.
@@ -385,6 +387,10 @@ export default {
       type: Array,
       type: Array,
       required: true,
       required: true,
     },
     },
+    hostname: {
+      type: String,
+      required: true,
+    },
   },
   },
   components: {
   components: {
     Modal,
     Modal,

+ 8 - 3
resources/js/pages/Usernames.vue

@@ -224,8 +224,8 @@
           and personal emails.
           and personal emails.
         </p>
         </p>
         <p>
         <p>
-          You can add a maximum of 3 additional usernames. Deleted usernames still count towards
-          your limit so please choose carefully.
+          You can add a maximum of {{ usernameCount }} additional usernames. Deleted usernames still
+          count towards your limit so please choose carefully.
         </p>
         </p>
       </div>
       </div>
     </div>
     </div>
@@ -238,7 +238,8 @@
           Add new username
           Add new username
         </h2>
         </h2>
         <p class="mt-4 text-grey-700">
         <p class="mt-4 text-grey-700">
-          Please choose additional usernames carefully as you can only add a maximum of three.
+          Please choose additional usernames carefully as you can only add a maximum of
+          {{ usernameCount }}.
         </p>
         </p>
         <div class="mt-6">
         <div class="mt-6">
           <p v-show="errors.newUsername" class="mb-3 text-red-500">
           <p v-show="errors.newUsername" class="mb-3 text-red-500">
@@ -315,6 +316,10 @@ export default {
       type: Array,
       type: Array,
       required: true,
       required: true,
     },
     },
+    usernameCount: {
+      type: Number,
+      required: true,
+    },
   },
   },
   components: {
   components: {
     Modal,
     Modal,

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

@@ -4,6 +4,6 @@
     <div class="container py-8">
     <div class="container py-8">
         @include('shared.status')
         @include('shared.status')
 
 
-        <aliases :default-recipient="{{json_encode($defaultRecipient)}}" :initial-aliases="{{json_encode($aliases)}}" :recipient-options="{{json_encode($recipients)}}" :total-forwarded="{{$totalForwarded}}" :total-blocked="{{$totalBlocked}}" :total-replies="{{$totalReplies}}" domain="{{$domain}}" :bandwidth-mb="{{$bandwidthMb}}" :month="{{ json_encode(now()->format('M')) }}" />
+        <aliases :default-recipient="{{json_encode($defaultRecipient)}}" :initial-aliases="{{json_encode($aliases)}}" :recipient-options="{{json_encode($recipients)}}" :total-forwarded="{{$totalForwarded}}" :total-blocked="{{$totalBlocked}}" :total-replies="{{$totalReplies}}" domain="{{config('anonaddy.domain')}}" subdomain="{{$domain}}" :bandwidth-mb="{{$bandwidthMb}}" :month="{{ json_encode(now()->format('M')) }}" />
     </div>
     </div>
 @endsection
 @endsection

+ 0 - 28
resources/views/auth/register.blade.php

@@ -92,34 +92,6 @@
                             @endif
                             @endif
                         </div>
                         </div>
 
 
-                        <div class="flex flex-wrap mb-3 items-center">
-                            <input type="checkbox" name="newsletter" class="mr-2" id="newsletter">
-
-                            <label class="text-sm text-grey-700" for="newsletter">
-                                Sign up to our newsletter
-                            </label>
-
-                            @if ($errors->has('newsletter'))
-                                <p class="text-red-500 text-xs italic mt-4">
-                                    {{ $errors->first('newsletter') }}
-                                </p>
-                            @endif
-                        </div>
-
-                        <div class="flex flex-wrap items-center">
-                            <input type="checkbox" name="terms" class="mr-2" id="terms">
-
-                            <label class="text-sm text-grey-700" for="terms">
-                                I accept the <a href="https://anonaddy.com/terms" class="text-indigo-800" target="_blank" rel="nofollow noreferrer noopener">terms</a> and <a href="https://anonaddy.com/privacy" class="text-indigo-800" target="_blank" rel="nofollow noreferrer noopener">privacy policy</a>
-                            </label>
-
-                            @if ($errors->has('terms'))
-                                <p class="text-red-500 text-xs italic mt-4">
-                                    {{ $errors->first('terms') }}
-                                </p>
-                            @endif
-                        </div>
-
                     </div>
                     </div>
 
 
                     <div class="px-6 md:px-10 py-4 bg-grey-50 border-t border-grey-100 flex flex-wrap items-center">
                     <div class="px-6 md:px-10 py-4 bg-grey-50 border-t border-grey-100 flex flex-wrap items-center">

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

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

+ 0 - 4
resources/views/settings/show.blade.php

@@ -4,10 +4,6 @@
     <div class="container py-8">
     <div class="container py-8">
         @include('shared.status')
         @include('shared.status')
 
 
-        <div class="text-sm border border-t-8 rounded text-yellow-800 border-yellow-600 bg-yellow-100 px-3 py-4 mb-4" role="alert">
-            We're currently in <b>beta</b>, you'll be able to use all features to test everything out and you'll also have a <b>100MB bandwidth limit</b> each calendar month!
-        </div>
-
         <div class="mb-4">
         <div class="mb-4">
             <h2 class="text-3xl font-bold">
             <h2 class="text-3xl font-bold">
                 Usage
                 Usage

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

@@ -4,6 +4,6 @@
     <div class="container py-8">
     <div class="container py-8">
         @include('shared.status')
         @include('shared.status')
 
 
-        <usernames :initial-usernames="{{json_encode($usernames)}}" />
+        <usernames :initial-usernames="{{json_encode($usernames)}}" :username-count="{{config('anonaddy.additional_username_limit')}}" />
     </div>
     </div>
 @endsection
 @endsection

+ 1 - 1
routes/web.php

@@ -11,7 +11,7 @@
 |
 |
 */
 */
 
 
-Auth::routes(['verify' => true]);
+Auth::routes(['verify' => true, 'register' => config('anonaddy.enable_registration')]);
 
 
 Route::post('/login/2fa', 'TwoFactorAuthController@authenticateTwoFactor')->name('login.2fa')->middleware(['2fa', 'throttle', 'auth']);
 Route::post('/login/2fa', 'TwoFactorAuthController@authenticateTwoFactor')->name('login.2fa')->middleware(['2fa', 'throttle', 'auth']);
 
 

+ 11 - 5
tests/Feature/ReceiveEmailTest.php

@@ -362,8 +362,11 @@ class ReceiveEmailTest extends TestCase
         ]);
         ]);
 
 
         Mail::assertQueued(ForwardEmail::class, function ($mail) {
         Mail::assertQueued(ForwardEmail::class, function ($mail) {
-            return $mail->hasTo('one@example.com') &&
-                   $mail->hasTo('two@example.com');
+            return $mail->hasTo('one@example.com');
+        });
+
+        Mail::assertQueued(ForwardEmail::class, function ($mail) {
+            return $mail->hasTo('two@example.com');
         });
         });
     }
     }
 
 
@@ -409,9 +412,12 @@ class ReceiveEmailTest extends TestCase
             'bandwidth' => '444'
             'bandwidth' => '444'
         ]);
         ]);
 
 
-        Mail::assertQueued(ForwardEmail::class, function ($mail) use ($recipient, $recipient2) {
-            return $mail->hasTo($recipient->email) &&
-                   $mail->hasTo($recipient2->email);
+        Mail::assertQueued(ForwardEmail::class, function ($mail) use ($recipient) {
+            return $mail->hasTo($recipient->email);
+        });
+
+        Mail::assertQueued(ForwardEmail::class, function ($mail) use ($recipient2) {
+            return $mail->hasTo($recipient2->email);
         });
         });
     }
     }
 
 

+ 11 - 0
tests/Feature/SettingsTest.php

@@ -2,6 +2,7 @@
 
 
 namespace Tests\Feature;
 namespace Tests\Feature;
 
 
+use App\AdditionalUsername;
 use App\Alias;
 use App\Alias;
 use App\AliasRecipient;
 use App\AliasRecipient;
 use App\DeletedUsername;
 use App\DeletedUsername;
@@ -178,6 +179,10 @@ class SettingsTest extends TestCase
             'domain_id' => $domain->id
             'domain_id' => $domain->id
         ]);
         ]);
 
 
+        $additionalUsername = factory(AdditionalUsername::class)->create([
+            'user_id' => $this->user->id
+        ]);
+
         $response = $this->post('/settings/account', [
         $response = $this->post('/settings/account', [
             'current_password_delete' => 'mypassword'
             'current_password_delete' => 'mypassword'
         ]);
         ]);
@@ -216,7 +221,13 @@ class SettingsTest extends TestCase
             'user_id' => $this->user->id,
             'user_id' => $this->user->id,
         ]);
         ]);
 
 
+        $this->assertDatabaseMissing('additional_usernames', [
+            'id' => $additionalUsername->id,
+            'user_id' => $this->user->id
+        ]);
+
         $this->assertEquals(DeletedUsername::first()->username, $this->user->username);
         $this->assertEquals(DeletedUsername::first()->username, $this->user->username);
+        $this->assertEquals(DeletedUsername::skip(1)->first()->username, $additionalUsername->username);
     }
     }
 
 
     /** @test */
     /** @test */

+ 21 - 55
tests/Unit/AliasTest.php

@@ -54,50 +54,6 @@ class AliasTest extends TestCase
         $this->assertEquals($verifiedRecipient->id, $alias->verifiedRecipients[0]->id);
         $this->assertEquals($verifiedRecipient->id, $alias->verifiedRecipients[0]->id);
     }
     }
 
 
-    /** @test */
-    public function alias_can_get_verified_recipient_emails()
-    {
-        $alias = factory(Alias::class)->create([
-            'user_id' => $this->user->id
-        ]);
-
-        $recipientOne = factory(Recipient::class)->create([
-            'user_id' => $this->user->id,
-            'email' => 'one@example.com'
-        ]);
-
-        $recipientTwo = factory(Recipient::class)->create([
-            'user_id' => $this->user->id,
-            'email' => 'two@example.com'
-        ]);
-
-        $recipientThree = factory(Recipient::class)->create([
-            'user_id' => $this->user->id,
-            'email' => 'three@example.com'
-        ]);
-
-        AliasRecipient::create([
-            'alias' => $alias,
-            'recipient' => $recipientOne
-        ]);
-
-        AliasRecipient::create([
-            'alias' => $alias,
-            'recipient' => $recipientTwo
-        ]);
-
-        AliasRecipient::create([
-            'alias' => $alias,
-            'recipient' => $recipientThree
-        ]);
-
-        $recipientEmails = $alias->nonPgpRecipientEmails();
-
-        $this->assertCount(3, $recipientEmails);
-        $this->assertIsArray($recipientEmails);
-        $this->assertEquals([$recipientOne->email, $recipientTwo->email, $recipientThree->email], $recipientEmails);
-    }
-
     /** @test */
     /** @test */
     public function alias_can_set_default_recipient_email()
     public function alias_can_set_default_recipient_email()
     {
     {
@@ -119,7 +75,7 @@ class AliasTest extends TestCase
     /** @test */
     /** @test */
     public function alias_can_get_default_recipient_email()
     public function alias_can_get_default_recipient_email()
     {
     {
-        factory(Alias::class)->create([
+        $alias = factory(Alias::class)->create([
             'user_id' => $this->user->id
             'user_id' => $this->user->id
         ]);
         ]);
 
 
@@ -129,12 +85,17 @@ class AliasTest extends TestCase
         ]);
         ]);
 
 
         $this->user->defaultRecipient = $recipient;
         $this->user->defaultRecipient = $recipient;
+        $this->user->save();
 
 
         $this->assertEquals($this->user->email, $recipient->email);
         $this->assertEquals($this->user->email, $recipient->email);
+        $this->assertCount(1, $alias->verifiedRecipientsOrDefault()->get());
+        $alias->verifiedRecipientsOrDefault()->each(function ($recipient) {
+            $this->assertEquals($this->user->email, $recipient->email);
+        });
     }
     }
 
 
     /** @test */
     /** @test */
-    public function alias_can_get_recipients_using_pgp_or_not()
+    public function alias_can_get_verified_recipients_or_default()
     {
     {
         $alias = factory(Alias::class)->create([
         $alias = factory(Alias::class)->create([
             'user_id' => $this->user->id
             'user_id' => $this->user->id
@@ -168,6 +129,14 @@ class AliasTest extends TestCase
             'fingerprint' => null
             'fingerprint' => null
         ]);
         ]);
 
 
+        $recipientFive = factory(Recipient::class)->create([
+            'user_id' => $this->user->id,
+            'email' => 'five@example.com',
+            'should_encrypt' => false,
+            'fingerprint' => null,
+            'email_verified_at' => null
+        ]);
+
         AliasRecipient::create([
         AliasRecipient::create([
             'alias' => $alias,
             'alias' => $alias,
             'recipient' => $recipientOne
             'recipient' => $recipientOne
@@ -188,15 +157,12 @@ class AliasTest extends TestCase
             'recipient' => $recipientFour
             'recipient' => $recipientFour
         ]);
         ]);
 
 
-        $pgpRecipients = $alias->recipientsUsingPgp();
-
-        $nonPgpRecipients = $alias->nonPgpRecipientEmails();
-
-        $this->assertCount(1, $nonPgpRecipients);
-        $this->assertIsArray($nonPgpRecipients);
-        $this->assertEquals([$recipientThree->email], $nonPgpRecipients);
+        AliasRecipient::create([
+            'alias' => $alias,
+            'recipient' => $recipientFive
+        ]);
 
 
-        $this->assertTrue($alias->hasNonPgpRecipients());
-        $this->assertCount(2, $pgpRecipients);
+        $this->assertCount(4, $alias->verifiedRecipientsOrDefault());
+        $this->assertCount(5, $alias->recipients);
     }
     }
 }
 }