diff --git a/app/Classes/FTN/Message.php b/app/Classes/FTN/Message.php index c9207cb..7362147 100644 --- a/app/Classes/FTN/Message.php +++ b/app/Classes/FTN/Message.php @@ -12,6 +12,7 @@ use Illuminate\Validation\Validator as ValidatorResult; use App\Classes\FTN as FTNBase; use App\Models\{Address,Domain}; use App\Rules\TwoByteInteger; +use App\Traits\EncodeUTF8; /** * Class Message @@ -21,6 +22,8 @@ use App\Rules\TwoByteInteger; */ class Message extends FTNBase { + use EncodeUTF8; + private const cast_utf8 = [ 'message', 'message_src', @@ -342,43 +345,7 @@ class Message extends FTNBase */ public function __serialize(): array { - $values = []; - - $properties = (new \ReflectionClass($this))->getProperties(); - - $class = get_class($this); - - foreach ($properties as $property) { - // Dont serialize the validation error - if ($property->name == 'errors') - continue; - - if ($property->isStatic()) { - continue; - } - - $property->setAccessible(true); - - if (! $property->isInitialized($this)) { - continue; - } - - $name = $property->getName(); - $encode = in_array($name,self::cast_utf8); - - if ($property->isPrivate()) { - $name = "\0{$class}\0{$name}"; - } elseif ($property->isProtected()) { - $name = "\0*\0{$name}"; - } - - $property->setAccessible(true); - $value = $property->getValue($this); - - $values[$name] = $encode ? utf8_encode($value) : $value; - } - - return $values; + return $this->encode(); } /** diff --git a/app/Http/Controllers/EchoareaController.php b/app/Http/Controllers/EchoareaController.php new file mode 100644 index 0000000..c8863c0 --- /dev/null +++ b/app/Http/Controllers/EchoareaController.php @@ -0,0 +1,49 @@ +middleware('auth'); + } + + /** + * Add or edit a echoarea + */ + public function add_edit(Request $request,Echoarea $o) + { + if ($request->post()) { + $this->authorize('admin',$o); + + $request->validate([ + // http://ftsc.org/docs/old/fsp-1028.002 + 'domain_id' => 'required|exists:domains,id', + 'name' => 'required|max:35|regex:/^[a-zA-Z-_~]{1,8}$/|unique:echoareas,name,'.($o->exists ? $o->id : 0), + 'description' => 'required', + 'active' => 'required|boolean', + 'public' => 'required|boolean', + ]); + + foreach (['name','description','active','public','notes','domain_id'] as $key) + $o->{$key} = $request->post($key); + + $o->save(); + + return redirect()->action([self::class,'home']); + } + + return view('echoarea.addedit') + ->with('o',$o); + } + + public function home() + { + return view('echoarea.home'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/FileareaController.php b/app/Http/Controllers/FileareaController.php new file mode 100644 index 0000000..e06b376 --- /dev/null +++ b/app/Http/Controllers/FileareaController.php @@ -0,0 +1,48 @@ +middleware('auth'); + } + + /** + * Add or edit a echoarea + */ + public function add_edit(Request $request,Filearea $o) + { + if ($request->post()) { + $this->authorize('admin',$o); + + $request->validate([ + // http://ftsc.org/docs/old/fsp-1028.002 + 'domain_id' => 'required|exists:domains,id', + 'name' => 'required|max:35|regex:/^[a-zA-Z-_~]{1,8}$/|unique:echoareas,name,'.($o->exists ? $o->id : 0), + 'description' => 'required', + 'active' => 'required|boolean', + 'public' => 'required|boolean', + ]); + + foreach (['name','description','active','public','notes','domain_id'] as $key) + $o->{$key} = $request->post($key); + + $o->save(); + + return redirect()->action([self::class,'home']); + } + + return view('filearea.addedit') + ->with('o',$o); + } + + public function home() + { + return view('filearea.home'); + } +} \ No newline at end of file diff --git a/app/Jobs/ProcessPacket.php b/app/Jobs/ProcessPacket.php index 7e8caab..bd7239f 100644 --- a/app/Jobs/ProcessPacket.php +++ b/app/Jobs/ProcessPacket.php @@ -10,7 +10,7 @@ use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Log; use App\Classes\FTN\{Message,Process}; -use App\Models\{Echomail,Netmail,Setup}; +use App\Models\{Echoarea,Echomail,Netmail,Setup}; class ProcessPacket implements ShouldQueue { @@ -141,7 +141,10 @@ class ProcessPacket implements ShouldQueue $this->msg->user_from, )); - // @todo Determine if we know about this echo area + $ea = Echoarea::where('name',$this->msg->echoarea) + ->where('domain_id',$this->msg->fftn_o->zone->domain_id) + ->single(); + // @todo Can the sender create it if it doesnt exist? // - Create it, or // - Else record in bad area @@ -155,7 +158,7 @@ class ProcessPacket implements ShouldQueue $o->tzoffset = $this->msg->date->utcOffset(); $o->fftn_id = ($x=$this->msg->fftn_o) ? $x->id : NULL; - $o->echoarea = $this->msg->echoarea; + $o->echoarea_id = $ea?->id; $o->msgid = $this->msg->msgid; $o->msg = $this->msg->message_src; diff --git a/app/Models/Domain.php b/app/Models/Domain.php index ab16d40..db8f5f2 100644 --- a/app/Models/Domain.php +++ b/app/Models/Domain.php @@ -23,6 +23,16 @@ class Domain extends Model /* RELATIONS */ + public function echoareas() + { + return $this->hasMany(Echoarea::class); + } + + public function fileareas() + { + return $this->hasMany(Filearea::class); + } + public function zones() { return $this->hasMany(Zone::class); diff --git a/app/Models/Echoarea.php b/app/Models/Echoarea.php new file mode 100644 index 0000000..81a732f --- /dev/null +++ b/app/Models/Echoarea.php @@ -0,0 +1,31 @@ +belongsToMany(Address::class); + } + + public function domain() + { + return $this->belongsTo(Domain::class); + } + + public function echomail() + { + return Echomail::select('*') + ->where('echoarea_id',$this->id); + } +} \ No newline at end of file diff --git a/app/Models/Echomail.php b/app/Models/Echomail.php index 247d7b1..857388b 100644 --- a/app/Models/Echomail.php +++ b/app/Models/Echomail.php @@ -2,17 +2,22 @@ namespace App\Models; -use Carbon\Exceptions\Exception; use Jenssegers\Mongodb\Eloquent\Model; use Jenssegers\Mongodb\Eloquent\SoftDeletes; use App\Classes\FTN\Message; use App\Interfaces\Packet; -use App\Traits\{MsgID,UseMongo}; +use App\Traits\{EncodeUTF8,MsgID,UseMongo}; class Echomail extends Model implements Packet { - use SoftDeletes,MsgID,UseMongo; + use SoftDeletes,MsgID,UseMongo,EncodeUTF8; + + protected $collection = FALSE; + + private const cast_utf8 = [ + 'msg' + ]; protected $dates = ['datetime']; @@ -28,6 +33,11 @@ class Echomail extends Model implements Packet /* METHODS */ + public function jsonSerialize(): array + { + return $this->encode(); + } + /** * Return this model as a packet */ diff --git a/app/Models/Filearea.php b/app/Models/Filearea.php new file mode 100644 index 0000000..d96437a --- /dev/null +++ b/app/Models/Filearea.php @@ -0,0 +1,25 @@ +belongsToMany(Address::class); + } + + public function domain() + { + return $this->belongsTo(Domain::class); + } +} \ No newline at end of file diff --git a/app/Models/Netmail.php b/app/Models/Netmail.php index f859670..ddbe44e 100644 --- a/app/Models/Netmail.php +++ b/app/Models/Netmail.php @@ -90,7 +90,6 @@ class Netmail extends Model implements Packet $o->via = $via; - return $o; } } \ No newline at end of file diff --git a/app/Traits/EncodeUTF8.php b/app/Traits/EncodeUTF8.php new file mode 100644 index 0000000..c1affdb --- /dev/null +++ b/app/Traits/EncodeUTF8.php @@ -0,0 +1,50 @@ +getProperties(); + + $class = get_class($this); + + foreach ($properties as $property) { + // Dont serialize the validation error + if ($property->name == 'errors') + continue; + + if ($property->isStatic()) { + continue; + } + + $property->setAccessible(true); + + if (! $property->isInitialized($this)) { + continue; + } + + $name = $property->getName(); + $encode = in_array($name,self::cast_utf8); + + if ($property->isPrivate()) { + $name = "\0{$class}\0{$name}"; + } elseif ($property->isProtected()) { + $name = "\0*\0{$name}"; + } + + $property->setAccessible(true); + $value = $property->getValue($this); + + $values[$name] = $encode ? utf8_encode($value) : $value; + } + + return $values; + } +} \ No newline at end of file diff --git a/database/migrations/2021_08_10_130352_echomail.php b/database/migrations/2021_08_10_130352_echomail.php new file mode 100644 index 0000000..f1b6bc9 --- /dev/null +++ b/database/migrations/2021_08_10_130352_echomail.php @@ -0,0 +1,97 @@ +id(); + $table->timestamps(); + $table->softDeletes(); + $table->string('name'); + $table->string('description'); + $table->boolean('active'); + $table->boolean('public'); + $table->string('notes')->nullable(); + + $table->integer('domain_id'); + $table->foreign('domain_id')->references('id')->on('domains'); + }); + + Schema::create('fileareas', function (Blueprint $table) { + $table->id(); + $table->timestamps(); + $table->softDeletes(); + $table->string('name'); + $table->string('description'); + $table->boolean('active'); + $table->boolean('public'); + $table->string('notes')->nullable(); + + $table->integer('domain_id'); + $table->foreign('domain_id')->references('id')->on('domains'); + }); + + Schema::create('address_echoarea', function (Blueprint $table) { + $table->integer('echoarea_id'); + $table->foreign('echoarea_id')->references('id')->on('echoareas'); + + $table->integer('address_id'); + $table->foreign('address_id')->references('id')->on('addresses'); + + $table->dateTime('subscribed'); + }); + + Schema::create('address_filearea', function (Blueprint $table) { + $table->integer('filearea_id'); + $table->foreign('filearea_id')->references('id')->on('fileareas'); + + $table->integer('address_id'); + $table->foreign('address_id')->references('id')->on('addresses'); + + $table->dateTime('subscribed'); + }); + + Schema::create('address_echomail', function (Blueprint $table) { + $table->integer('echomail_id'); + $table->string('packet'); + + $table->integer('address_id'); + $table->foreign('address_id')->references('id')->on('addresses'); + }); + + Schema::create('address_file', function (Blueprint $table) { + $table->integer('filearea_id'); + $table->boolean('sent'); + + $table->integer('address_id'); + $table->foreign('address_id')->references('id')->on('addresses'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('address_file'); + Schema::dropIfExists('address_echomail'); + + Schema::dropIfExists('address_filearea'); + Schema::dropIfExists('fileareas'); + + Schema::dropIfExists('address_echoarea'); + Schema::dropIfExists('echoareas'); + } +} diff --git a/database/seeders/InitialSetupSeeder.php b/database/seeders/InitialSetupSeeder.php index 77965c6..329fe7b 100644 --- a/database/seeders/InitialSetupSeeder.php +++ b/database/seeders/InitialSetupSeeder.php @@ -78,5 +78,19 @@ class InitialSetupSeeder extends Seeder 'active'=>TRUE, 'password'=>'$2y$10$bJQDLfxnKrh6o5Sa02MZOukXcLTNQiByXSTJ7fTr.kHMpV2wxbG6.', ]); + + DB::table('echoareas')->insert([ + 'name'=>'-BAD_AREA', + 'description'=>'Inbound invalid echomail', + 'active'=>TRUE, + 'domain_id'=>$do->id, + ]); + + DB::table('fileareas')->insert([ + 'name'=>'-BAD_AREA', + 'description'=>'Inbound invalid files', + 'active'=>TRUE, + 'domain_id'=>$do->id, + ]); } } diff --git a/resources/views/domain/view.blade.php b/resources/views/domain/view.blade.php index e5b685a..cae4845 100644 --- a/resources/views/domain/view.blade.php +++ b/resources/views/domain/view.blade.php @@ -26,7 +26,27 @@
This network provides the following Echomail areas:
+Echoarea | +Description | +Last Message | +
---|---|---|
{{ $oo->name }} | +{{ $oo->description }} | +{{ ($x=$oo->echomail()->orderBy('created_at','DESC')->first()) ? $x->created_at->format('Y-m-d H:i') : '-' }} | +
This network provides the following File areas:
+Filearea | +Description | +Last File Sent | +
---|---|---|
{{ $oo->name }} | +{{ $oo->description }} | +- | +
BBS Systems exchange public messages called echomail. Echomail is grouped into echoareas normally around a theme or a topic.
+Each echoarea has a unique areatag which helps a receiving BBS to know where to file the message when it is received.
+This system is aware of the following echoareas:
+ + @if (\App\Models\Echoarea::count() == 0) + @can('admin',(new \App\Models\Echoarea)) +There are no echoareas setup, to set up your first.
+ @else +There are no echoareas - you need to ask an admin to create one for you.
+ @endcan + @else +ID | +Areatag | +Description | +Active | +Domain | +
---|---|---|---|---|
Add New Echoarea | +||||
{{ $oo->id }} | +{{ $oo->name }} | +{{ $oo->description }} | +{{ $oo->active ? 'YES' : 'NO' }} | +{{ $oo->domain->name }} | +
BBS Systems exchange area able to exchange and distribute files. Files are grouped into fileareas normally around a theme or type.
+Each filerea has a unique filetag which helps a receiving BBS to know where to store the file when it is received.
+This system is aware of the following fileareas:
+ + @if (\App\Models\Filearea::count() == 0) + @can('admin',(new \App\Models\Filearea)) +There are no fileareas setup, to set up your first.
+ @else +There are no fileareas - you need to ask an admin to create one for you.
+ @endcan + @else +ID | +Filetag | +Description | +Active | +Domain | +
---|---|---|---|---|
Add New Filearea | +||||
{{ $oo->id }} | +{{ $oo->name }} | +{{ $oo->description }} | +{{ $oo->active ? 'YES' : 'NO' }} | +{{ $oo->domain->name }} | +