Skip to content

Commit 4c58424

Browse files
Boy132HarlequinSin
andcommitted
add srv records to subdomains
Co-authored-by: HarlequinSin <Zack.gothard@gmail.com>
1 parent a1c5c7a commit 4c58424

18 files changed

Lines changed: 428 additions & 62 deletions

File tree

subdomains/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Subdomains (by Boy132)
1+
# Subdomains (by Boy132 & HarlequinSin)
22

33
Allows users to create and manage custom subdomains for their game servers using Cloudflare DNS.
44

@@ -8,3 +8,10 @@ Allows users to create and manage custom subdomains for their game servers using
88
- Cloudflare DNS integration for automatic record management
99
- Admin management of Cloudflare domains
1010
- Per-server subdomain limits
11+
12+
## SRV Records
13+
14+
In order to create SRV records instead of A/AAAA you need to do the following:
15+
16+
1. Set a `SRV target` for the node
17+
2. Add a [SRV service type](https://github.com/pelican-dev/plugins/blob/main/subdomains/src/Enums/SRVServiceType.php#L10-L16) to the features of the egg, e.g. `srv-minecraft`
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
public function up(): void
10+
{
11+
Schema::table('nodes', function (Blueprint $table) {
12+
$table->string('srv_target')->nullable()->after('fqdn');
13+
});
14+
}
15+
16+
public function down(): void
17+
{
18+
Schema::table('nodes', function (Blueprint $table) {
19+
$table->dropColumn('srv_target');
20+
});
21+
}
22+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
return [
4+
'synced' => 'Domain wurde erfolgreich mit Cloudflare synchronisiert',
5+
'not_synced' => 'Domain konnte nicht mit Cloudflare synchronisiert werden',
6+
7+
'srv_target_updated' => 'SRV Ziel aktualisiert',
8+
];

subdomains/lang/de/strings.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
'create_subdomain' => 'Subdomain erstellen',
1414

1515
'name' => 'Name',
16+
'record_type' => 'Record Typ',
17+
'is_synced' => 'Ist synchronisiert?',
18+
'srv_target' => 'SRV Ziel',
19+
20+
'sync' => 'Synchronisieren',
21+
'set_srv_target' => 'SRV Ziel setzen',
1622

1723
'api_token' => 'Cloudflare API Token',
1824
'api_token_help' => 'Der Token benötigt Leseberechtigung für Zone.Zone und Schreibberechtigung für Zone.Dns. Für eine verbesserte Sicherheit können mit "Zone Resources" bestimmte Domains ausgeschlossen werden und die Panel-IP zum "Client IP Adress Filtering" hinzugefügt werden.',
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
return [
4+
'synced' => 'Domain synced with cloudflare',
5+
'not_synced' => 'Could not sync domain with cloudflare',
6+
7+
'srv_target_updated' => 'SRV target updated',
8+
];

subdomains/lang/en/strings.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@
77
'no_subdomains' => 'No Subdomains',
88
'subdomain' => 'Subdomain|Subdomains',
99
'limit' => 'Limit',
10-
'change_limit' => 'Change Limit',
10+
'change_limit' => 'Change limit',
1111
'limit_changed' => 'Limit changed',
12-
'limit_reached' => 'Subdomain Limit Reached',
12+
'limit_reached' => 'Subdomain limit reached',
1313
'create_subdomain' => 'Create Subdomain',
1414

1515
'name' => 'Name',
16+
'record_type' => 'Record type',
17+
'is_synced' => 'Is Synced?',
18+
'srv_target' => 'SRV target',
19+
20+
'sync' => 'Sync',
21+
'set_srv_target' => 'Set SRV target',
1622

1723
'api_token' => 'Cloudflare API Token',
1824
'api_token_help' => 'The token needs to have read permissions for Zone.Zone and write for Zone.Dns. For better security you can also set the "Zone Resources" to exclude certain domains and add the panel ip to the "Client IP Adress Filtering".',

subdomains/plugin.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "subdomains",
33
"name": "Subdomains",
4-
"author": "Boy132",
4+
"author": "Boy132 & HarlequinSin",
55
"version": "1.0.0",
66
"description": "Allows users to create subdomains for their servers",
77
"category": "plugin",
@@ -15,4 +15,4 @@
1515
],
1616
"panel_version": null,
1717
"composer_packages": null
18-
}
18+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace Boy132\Subdomains\Enums;
4+
5+
use App\Models\Server;
6+
use Filament\Support\Contracts\HasLabel;
7+
8+
enum SRVServiceType: string implements HasLabel
9+
{
10+
case Minecraft = '_minecraft._tcp';
11+
case Mumble = '_mumble._tcp';
12+
case Factorio = '_factorio._udp';
13+
case Rust = '_rust._udp';
14+
case SCPSL = '_scpsl._udp';
15+
case Teamspeak = '_ts3._udp';
16+
17+
public function getLabel(): string
18+
{
19+
return str($this->name)->title();
20+
}
21+
22+
public static function fromServer(Server $server): ?self
23+
{
24+
$features = $server->egg->features ?? [];
25+
26+
foreach (self::cases() as $type) {
27+
$name = str($type->name)->lower()->prepend('srv-');
28+
29+
if (in_array($name, $features)) {
30+
return $type;
31+
}
32+
}
33+
34+
return null;
35+
}
36+
}

subdomains/src/Filament/Admin/Resources/CloudflareDomains/CloudflareDomainResource.php

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
use Boy132\Subdomains\Filament\Admin\Resources\CloudflareDomains\Pages\ManageCloudflareDomains;
66
use Boy132\Subdomains\Models\CloudflareDomain;
7+
use Exception;
8+
use Filament\Actions\Action;
79
use Filament\Actions\DeleteAction;
8-
use Filament\Actions\EditAction;
9-
use Filament\Actions\ViewAction;
1010
use Filament\Forms\Components\TextInput;
1111
use Filament\Infolists\Components\TextEntry;
12+
use Filament\Notifications\Notification;
1213
use Filament\Resources\Resource;
1314
use Filament\Schemas\Schema;
15+
use Filament\Tables\Columns\IconColumn;
1416
use Filament\Tables\Columns\TextColumn;
1517
use Filament\Tables\Table;
1618

@@ -56,11 +58,36 @@ public static function table(Table $table): Table
5658
TextColumn::make('subdomains_count')
5759
->label(trans_choice('subdomains::strings.subdomain', 2))
5860
->counts('subdomains'),
61+
IconColumn::make('is_synced')
62+
->label(trans('subdomains::strings.is_synced'))
63+
->state(fn (CloudflareDomain $domain) => !is_null($domain->cloudflare_id))
64+
->boolean()
65+
->trueIcon('tabler-refresh')
66+
->falseIcon('tabler-refresh-off')
67+
->tooltip(fn (CloudflareDomain $domain) => $domain->cloudflare_id),
5968
])
6069
->recordActions([
61-
ViewAction::make()
62-
->hidden(fn ($record) => static::canEdit($record)),
63-
EditAction::make(),
70+
Action::make('sync')
71+
->label(trans('subdomains::strings.sync'))
72+
->icon('tabler-refresh')
73+
->visible(fn (CloudflareDomain $domain) => is_null($domain->cloudflare_id))
74+
->action(function (CloudflareDomain $domain) {
75+
try {
76+
$domain->fetchCloudflareId();
77+
78+
Notification::make()
79+
->title(trans('subdomains::notifications.synced'))
80+
->success()
81+
->send();
82+
} catch (Exception $exception) {
83+
Notification::make()
84+
->title(trans('subdomains::notifications.not_synced'))
85+
->body($exception->getMessage())
86+
->danger()
87+
->persistent()
88+
->send();
89+
}
90+
}),
6491
DeleteAction::make(),
6592
])
6693
->emptyStateIcon('tabler-world-www')

subdomains/src/Filament/Admin/Resources/CloudflareDomains/Pages/ManageCloudflareDomains.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
namespace Boy132\Subdomains\Filament\Admin\Resources\CloudflareDomains\Pages;
44

55
use Boy132\Subdomains\Filament\Admin\Resources\CloudflareDomains\CloudflareDomainResource;
6+
use Boy132\Subdomains\Models\CloudflareDomain;
7+
use Exception;
68
use Filament\Actions\CreateAction;
9+
use Filament\Notifications\Notification;
710
use Filament\Resources\Pages\ManageRecords;
811

912
class ManageCloudflareDomains extends ManageRecords
@@ -14,7 +17,19 @@ protected function getHeaderActions(): array
1417
{
1518
return [
1619
CreateAction::make()
17-
->createAnother(false),
20+
->createAnother(false)
21+
->using(function (array $data) {
22+
try {
23+
return CloudflareDomain::create($data);
24+
} catch (Exception $exception) {
25+
Notification::make()
26+
->title(trans('subdomains::notifications.not_synced'))
27+
->body($exception->getMessage())
28+
->danger()
29+
->persistent()
30+
->send();
31+
}
32+
}),
1833
];
1934
}
2035
}

0 commit comments

Comments
 (0)