Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ clover.xml
coverage/
node_modules/
package-lock.json
yarn.lock
vendor/
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
"statamic/cms": "^3.1"
},
"require-dev": {
"nunomaduro/larastan": "^0.7.6",
"orchestra/testbench": "^6.18.0",
"phpunit/phpunit": "^9.5"
"phpunit/phpunit": "^9.5",
"spatie/ray": "^1.26"
},
"config": {
"process-timeout": 0,
Expand Down
50 changes: 26 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"cross-env": "^5.1",
"laravel-mix": "^5.0.9",
"laravel-mix-purgecss": "^4.2.0",
"node-forge": ">=0.10.0",
"postcss-import": "^14.0.0",
"postcss-nested": "^5.0.5",
"postcss-preset-env": "^6.7.0",
"vue-template-compiler": "^2.6.12"
},
"dependencies": {
"axios": "^0.21.0",
"tailwindcss": "^2.0.3"
}
"private": true,
"scripts": {
"dev": "mix",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"production": "mix --production"
},
"devDependencies": {
"autoprefixer": "^10.2.6",
"axios": "^0.21.1",
"browser-sync": "^2.26.14",
"browser-sync-webpack-plugin": "^2.3.0",
"cross-env": "^7.0.3",
"laravel-mix": "^6.0.19",
"postcss": "^8.3.0",
"postcss-focus-visible": "^3.0.0",
"postcss-import": "^14.0.2",
"postcss-nested": "^5.0.5",
"resolve-url-loader": "^4.0.0",
"tailwindcss": "^2.1.2",
"vue-loader": "^15.9.5",
"vue-template-compiler": "^2.6.12"
},
"dependencies": {}
}
8 changes: 8 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
includes:
- ./vendor/nunomaduro/larastan/extension.neon

parameters:
level: 1
paths:
- src
- tests
1 change: 1 addition & 0 deletions public/css/statamic-magiclink.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

2 changes: 1 addition & 1 deletion public/js/statamic-magiclink.js

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions resources/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import SendMagicLinkComponent from './components/SendMagicLinkComponent';
import SettingsComponent from './components/SettingsComponent';
import LinksListingComponent from './components/Links/ListingComponent';

window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

Statamic.booting(() => {
Statamic.$components.register('magiclink-settings', SettingsComponent);
Statamic.$components.register('magiclink-send-link', SendMagicLinkComponent);
Expand Down
32 changes: 31 additions & 1 deletion resources/js/components/SettingsComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</div>

<publish-fields-container class="card p-0 mb-3 configure-section">
<div v-for="(address, index) in countAddresses">
<div v-for="(a, index) in countAddresses">
<form-group
class="border-b"
handle="allowedAddresses[]"
Expand All @@ -50,6 +50,28 @@
</div>
</publish-fields-container>

<div class="mb-1 content">
<h2 class="text-base">
{{ __('magiclink::cp.settings.ml_allowed_domains') }}
<button class="btn-sm" @click="addDomain">
+ Add new domain
</button>
</h2>
</div>

<publish-fields-container class="card p-0 mb-3 configure-section">
<div v-for="(d, index) in countDomains">
<form-group
class="border-b"
handle="allowedDomains[]"
:display="__('magiclink::cp.settings.ml_allowed_domains')"
:errors="errors.allowedDomains"
:instructions="__('magiclink::cp.settings.ml_allowed_domains_instructions')"
v-model="allowedDomains[index]"
/>
</div>
</publish-fields-container>

<div class="py-2 mt-3 border-t flex justify-between">
<a :href="indexUrl" class="btn" v-text="__('Cancel') "/>
<button type="submit" class="btn-primary" @click="save">{{ __('Save') }}</button>
Expand All @@ -63,6 +85,7 @@
props: {
action: String,
initialAllowedAddresses: Array,
initialAllowedDomains: Array,
initialExpireTime: {
type: Number,
required: true,
Expand All @@ -85,6 +108,8 @@
return {
allowedAddresses: this.initialAllowedAddresses,
countAddresses: this.initialAllowedAddresses.length + 1,
allowedDomains: this.initialAllowedDomains,
countDomains: this.initialAllowedDomains.length + 1,
error: null,
errors: {},
enabled: this.initialEnabled,
Expand All @@ -100,6 +125,7 @@
payload() {
return {
allowedAddresses: this.allowedAddresses,
allowedDomains: this.allowedDomains,
enabled: this.enabled,
expireTime: this.expireTime,
}
Expand All @@ -116,6 +142,10 @@
this.countAddresses += 1;
},

addDomain() {
this.countDomains += 1;
},

save() {
this.clearErrors();

Expand Down
2 changes: 1 addition & 1 deletion resources/lang/de/cp.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
'ml_enabled' => 'MagicLink aktivieren?',
'ml_enabled_instructions' => 'Aktiviere oder deaktiviere die Nutzung von MagicLinks',
'ml_expire_time' => 'Ablaufzeit',
'ml_expire_time_instructions' => 'Laufzeit des Links, nachdem er verfällt. Standart sind 30 Minuten.',
'ml_expire_time_instructions' => 'Laufzeit des Links, nachdem er verfällt. Standard sind 30 Minuten.',
'updated_successfully' => 'Einstellungen erfolgreich aktualisiert.',
],
'permissions' => [
Expand Down
2 changes: 2 additions & 0 deletions resources/lang/en/cp.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
'ml_expire_time_instructions' => 'Time the login link is valid. Default is 30 minutes.',
'ml_allowed_addresses' => 'Allowed addresses',
'ml_allowed_addresses_instructions' => 'Allowed addresses to request a magic link for viewing protected content. Enter one address in each field.',
'ml_allowed_domains' => 'Allowed domains',
'ml_allowed_domains_instructions' => 'Allowed domains to request a magic link for. _Example:_ example.com',
'settings' => 'Settings',
'updated_successfully' => 'Settings updated successfully.',
],
Expand Down
1 change: 1 addition & 0 deletions resources/views/cp/settings/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
:initial-enabled="{{ Statamic\Support\Str::bool($enabled) }}"
initial-expire-time="{{ $expireTime }}"
:initial-allowed-addresses="{{ json_encode($allowedAddresses) }}"
:initial-allowed-domains="{{ json_encode($allowedDomains) }}"
></magiclink-settings>


Expand Down
2 changes: 1 addition & 1 deletion resources/views/magiclink/send-link-form.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

@section('content')
<div class="logo pt-7">
@svg('statamic-wordmark')
@cp_svg('statamic-wordmark')
</div>

<div class="card auth-card mx-auto">
Expand Down
7 changes: 6 additions & 1 deletion src/Http/Controllers/Cp/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ public function update(Request $request)
'expireTime' => ['required', 'numeric'],
'allowedAddresses' => ['present', 'array'],
'allowedAddresses.*' => ['sometimes', 'email'],
'allowedDomains' => ['present', 'array'],
]);

$this->settingsRepository->put($request);
$payload = $request->all();
$payload['allowedDomains'] = array_filter($payload['allowedDomains']);
$payload['allowedAddresses'] = array_filter($payload['allowedAddresses']);

$this->settingsRepository->put(collect($payload));

session()->flash('success', __('magiclink::cp.settings.updated_successfully'));

Expand Down
2 changes: 1 addition & 1 deletion src/Http/Controllers/MagicLinkController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private function prepareUser(Request $request): ?\Statamic\Contracts\Auth\User
* Special check for protected content, when no CP user exists.
*/
if ($user === null) {
if ($this->settingsRepository->allowedAddresses()->contains($request->email)) {
if ($this->magicLinkRepository->validAddress($request->email)) {
$user = (User::make())->email($request->email);
}
}
Expand Down
33 changes: 32 additions & 1 deletion src/MagicLinkManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Codedge\MagicLink;

use Codedge\MagicLink\Repositories\SettingsRepository;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Collection;
use Statamic\Contracts\Auth\User;
Expand All @@ -13,12 +14,14 @@ final class MagicLinkManager
{
protected MagicLink $magicLink;
protected Filesystem $files;
protected SettingsRepository $settingsRepository;
protected string $path;
protected User $user;

public function __construct(Filesystem $files)
public function __construct(Filesystem $files, SettingsRepository $settingsRepository)
{
$this->files = $files;
$this->settingsRepository = $settingsRepository;
$this->path = storage_path('statamic-magiclink/magic-links.yaml');
}

Expand Down Expand Up @@ -75,4 +78,32 @@ public function save(Collection $content)

return $this->files->put($this->path, YAML::dump($merged->all()));
}

/**
* Validate a given email address against the addresses set either in
* - ALLOWED_ADDRESSES
* - ALLOWED_DOMAINS.
*
* If no allowed address or domain is set, the given email is considered valid.
*/
public function validAddress(string $email): bool
{
$valid = false;

if ($this->settingsRepository->allowedAddresses()->count() !== 0) {
if (in_array($email, $this->settingsRepository->allowedAddresses()->toArray())) {
$valid = true;
}
}

if ($this->settingsRepository->allowedDomains()->count() !== 0) {
$parts = explode('@', $email);
if (in_array($parts[1], $this->settingsRepository->allowedDomains()->toArray())
) {
$valid = true;
}
}

return $valid;
}
}
9 changes: 8 additions & 1 deletion src/Repositories/SettingsRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ final class SettingsRepository
const IS_ENABLED_KEY = 'enabled';
const EXPIRE_TIME_KEY = 'expireTime';
const ALLOWED_ADDRESSES = 'allowedAddresses';
const ALLOWED_DOMAINS = 'allowedDomains';

private array $defaultValues;

Expand All @@ -28,6 +29,7 @@ public function __construct(Filesystem $files)
self::IS_ENABLED_KEY => false,
self::EXPIRE_TIME_KEY => config('statamic-magiclink.expire_time'),
self::ALLOWED_ADDRESSES => [],
self::ALLOWED_DOMAINS => [],
];
}

Expand All @@ -46,6 +48,11 @@ public function allowedAddresses(): Collection
return collect($this->get()->get(self::ALLOWED_ADDRESSES));
}

public function allowedDomains(): Collection
{
return collect($this->get()->get(self::ALLOWED_DOMAINS));
}

public function get(): Collection
{
if (! $this->files->exists($this->path)) {
Expand All @@ -55,7 +62,7 @@ public function get(): Collection
return collect(YAML::parse($this->files->get($this->path)));
}

public function put($content)
public function put(Collection $content)
{
if (! $this->files->isDirectory($dir = dirname($this->path))) {
$this->files->makeDirectory($dir);
Expand Down
2 changes: 1 addition & 1 deletion src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function register()
});

$this->app->bind(MagicLinkManager::class, function () {
return new MagicLinkManager(new Filesystem());
return new MagicLinkManager(new Filesystem(), resolve(SettingsRepository::class));
});
}

Expand Down
Loading