mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-nostr.git
synced 2026-05-20 10:04:53 +00:00
🔥 Add initial database migrations, seeders, and factories
🎨 Refactor `Lecturer` model to include new fields and factory usage 🔧 Update `DatabaseSeeder` to handle default seeds 🛠️ Enhance `einundzwanzig` database configuration for SQLite compatibility
This commit is contained in:
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"laravel-boost": {
|
"laravel-boost": {
|
||||||
"command": "php",
|
"command": "/usr/bin/php",
|
||||||
"args": [
|
"args": [
|
||||||
"artisan",
|
"/var/home/user/Code/einundzwanzig-verein/artisan",
|
||||||
"boost:mcp"
|
"boost:mcp"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
|
||||||
class Category extends Model
|
class Category extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $connection = 'einundzwanzig';
|
protected $connection = 'einundzwanzig';
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Akuechler\Geoly;
|
use Akuechler\Geoly;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@@ -13,6 +14,7 @@ use Spatie\Sluggable\SlugOptions;
|
|||||||
class City extends Model
|
class City extends Model
|
||||||
{
|
{
|
||||||
use Geoly;
|
use Geoly;
|
||||||
|
use HasFactory;
|
||||||
use HasSlug;
|
use HasSlug;
|
||||||
|
|
||||||
protected $connection = 'einundzwanzig';
|
protected $connection = 'einundzwanzig';
|
||||||
@@ -20,6 +22,12 @@ class City extends Model
|
|||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
|
'country_id',
|
||||||
|
'latitude',
|
||||||
|
'longitude',
|
||||||
|
'osm_relation',
|
||||||
|
'simplified_geojson',
|
||||||
|
'created_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,16 +2,21 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
class Country extends Model
|
class Country extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $connection = 'einundzwanzig';
|
protected $connection = 'einundzwanzig';
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
|
'code',
|
||||||
|
'language_codes',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
@@ -14,6 +15,7 @@ use Spatie\Tags\HasTags;
|
|||||||
|
|
||||||
class Course extends Model implements HasMedia
|
class Course extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
use HasTags;
|
use HasTags;
|
||||||
use InteractsWithMedia;
|
use InteractsWithMedia;
|
||||||
|
|
||||||
@@ -23,6 +25,9 @@ class Course extends Model implements HasMedia
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'description',
|
'description',
|
||||||
|
'lecturer_id',
|
||||||
|
'duration_minutes',
|
||||||
|
'created_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,17 +2,23 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class CourseEvent extends Model
|
class CourseEvent extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $connection = 'einundzwanzig';
|
protected $connection = 'einundzwanzig';
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'from',
|
'from',
|
||||||
'to',
|
'to',
|
||||||
|
'course_id',
|
||||||
|
'venue_id',
|
||||||
|
'created_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class Event extends Model
|
class Event extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'event_id',
|
'event_id',
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@@ -16,6 +17,7 @@ use Spatie\Sluggable\SlugOptions;
|
|||||||
|
|
||||||
class Lecturer extends Model implements HasMedia
|
class Lecturer extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
use HasSlug;
|
use HasSlug;
|
||||||
use InteractsWithMedia;
|
use InteractsWithMedia;
|
||||||
|
|
||||||
@@ -24,6 +26,12 @@ class Lecturer extends Model implements HasMedia
|
|||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
|
'bio',
|
||||||
|
'npub',
|
||||||
|
'pubkey',
|
||||||
|
'website',
|
||||||
|
'active',
|
||||||
|
'created_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@@ -16,6 +17,7 @@ use Spatie\Sluggable\SlugOptions;
|
|||||||
|
|
||||||
class Meetup extends Model implements HasMedia
|
class Meetup extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
use HasSlug;
|
use HasSlug;
|
||||||
use InteractsWithMedia;
|
use InteractsWithMedia;
|
||||||
|
|
||||||
@@ -24,6 +26,13 @@ class Meetup extends Model implements HasMedia
|
|||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
|
'city_id',
|
||||||
|
'description',
|
||||||
|
'website',
|
||||||
|
'nostr_pubkey',
|
||||||
|
'github_data',
|
||||||
|
'simplified_geojson',
|
||||||
|
'created_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,16 +2,27 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class MeetupEvent extends Model
|
class MeetupEvent extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $connection = 'einundzwanzig';
|
protected $connection = 'einundzwanzig';
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'start',
|
'start',
|
||||||
|
'meetup_id',
|
||||||
|
'location',
|
||||||
|
'description',
|
||||||
|
'link',
|
||||||
|
'attendees',
|
||||||
|
'might_attendees',
|
||||||
|
'nostr_status',
|
||||||
|
'created_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class Profile extends Model
|
class Profile extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'pubkey',
|
'pubkey',
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class RenderedEvent extends Model
|
class RenderedEvent extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'event_id',
|
'event_id',
|
||||||
|
|||||||
@@ -3,10 +3,13 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class SecurityAttempt extends Model
|
class SecurityAttempt extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'ip_address',
|
'ip_address',
|
||||||
'user_agent',
|
'user_agent',
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@@ -16,6 +17,7 @@ use Staudenmeir\EloquentHasManyDeep\HasRelationships;
|
|||||||
|
|
||||||
class Venue extends Model implements HasMedia
|
class Venue extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
use HasRelationships;
|
use HasRelationships;
|
||||||
use HasSlug;
|
use HasSlug;
|
||||||
use InteractsWithMedia;
|
use InteractsWithMedia;
|
||||||
@@ -25,6 +27,11 @@ class Venue extends Model implements HasMedia
|
|||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
|
'city_id',
|
||||||
|
'description',
|
||||||
|
'address',
|
||||||
|
'website',
|
||||||
|
'created_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class Vote extends Model
|
class Vote extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'einundzwanzig_pleb_id',
|
'einundzwanzig_pleb_id',
|
||||||
|
|||||||
Generated
+469
-400
File diff suppressed because it is too large
Load Diff
+9
-1
@@ -97,7 +97,15 @@ return [
|
|||||||
'sslmode' => 'prefer',
|
'sslmode' => 'prefer',
|
||||||
],
|
],
|
||||||
|
|
||||||
'einundzwanzig' => [
|
'einundzwanzig' => env('DB_CONNECTION', 'sqlite') === 'sqlite' ? [
|
||||||
|
'driver' => 'sqlite',
|
||||||
|
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||||
|
'prefix' => '',
|
||||||
|
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||||
|
'busy_timeout' => null,
|
||||||
|
'journal_mode' => null,
|
||||||
|
'synchronous' => null,
|
||||||
|
] : [
|
||||||
'driver' => 'pgsql',
|
'driver' => 'pgsql',
|
||||||
'url' => env('DB_URL_EINUNDZANZIG'),
|
'url' => env('DB_URL_EINUNDZANZIG'),
|
||||||
'host' => env('DB_HOST_EINUNDZANZIG', '127.0.0.1'),
|
'host' => env('DB_HOST_EINUNDZANZIG', '127.0.0.1'),
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Category;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Category>
|
||||||
|
*/
|
||||||
|
class CategoryFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => fake()->unique()->randomElement([
|
||||||
|
'Grundlagen',
|
||||||
|
'Self Custody',
|
||||||
|
'Lightning',
|
||||||
|
'Nostr',
|
||||||
|
'Privacy',
|
||||||
|
'Mining',
|
||||||
|
'Wirtschaft',
|
||||||
|
'Recht',
|
||||||
|
'Technik',
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\City;
|
||||||
|
use App\Models\Country;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<City>
|
||||||
|
*/
|
||||||
|
class CityFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'country_id' => Country::factory(),
|
||||||
|
'name' => fake()->city(),
|
||||||
|
'latitude' => fake()->latitude(47, 55),
|
||||||
|
'longitude' => fake()->longitude(6, 16),
|
||||||
|
'osm_relation' => null,
|
||||||
|
'simplified_geojson' => null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function vienna(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Wien',
|
||||||
|
'latitude' => 48.2082,
|
||||||
|
'longitude' => 16.3738,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function berlin(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Berlin',
|
||||||
|
'latitude' => 52.5200,
|
||||||
|
'longitude' => 13.4050,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function munich(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'München',
|
||||||
|
'latitude' => 48.1351,
|
||||||
|
'longitude' => 11.5820,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function zurich(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Zürich',
|
||||||
|
'latitude' => 47.3769,
|
||||||
|
'longitude' => 8.5417,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Country;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Country>
|
||||||
|
*/
|
||||||
|
class CountryFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => fake()->unique()->country(),
|
||||||
|
'code' => strtoupper(fake()->unique()->lexify('??')),
|
||||||
|
'language_codes' => ['de'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function germany(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Deutschland',
|
||||||
|
'code' => 'DE',
|
||||||
|
'language_codes' => ['de'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function austria(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Österreich',
|
||||||
|
'code' => 'AT',
|
||||||
|
'language_codes' => ['de'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function switzerland(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Schweiz',
|
||||||
|
'code' => 'CH',
|
||||||
|
'language_codes' => ['de', 'fr', 'it'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Course;
|
||||||
|
use App\Models\CourseEvent;
|
||||||
|
use App\Models\Venue;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<CourseEvent>
|
||||||
|
*/
|
||||||
|
class CourseEventFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$from = fake()->dateTimeBetween('+1 day', '+90 days');
|
||||||
|
$to = (clone $from)->modify('+2 hours');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'course_id' => Course::factory(),
|
||||||
|
'venue_id' => Venue::factory(),
|
||||||
|
'from' => $from,
|
||||||
|
'to' => $to,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function past(): static
|
||||||
|
{
|
||||||
|
return $this->state(function () {
|
||||||
|
$from = fake()->dateTimeBetween('-90 days', '-1 day');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'from' => $from,
|
||||||
|
'to' => (clone $from)->modify('+2 hours'),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Course;
|
||||||
|
use App\Models\Lecturer;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Course>
|
||||||
|
*/
|
||||||
|
class CourseFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$titles = [
|
||||||
|
'Bitcoin Basics',
|
||||||
|
'Self Custody und Hardware Wallets',
|
||||||
|
'Lightning Network 101',
|
||||||
|
'Nostr Einführung',
|
||||||
|
'Bitcoin für Unternehmer',
|
||||||
|
'Privacy & Coinjoin',
|
||||||
|
'Running Your Own Node',
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'lecturer_id' => Lecturer::factory(),
|
||||||
|
'name' => fake()->randomElement($titles),
|
||||||
|
'description' => fake()->paragraphs(2, true),
|
||||||
|
'duration_minutes' => fake()->randomElement([60, 90, 120, 180]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bitcoinBasics(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Bitcoin Basics',
|
||||||
|
'description' => 'Eine umfassende Einführung in Bitcoin: Was ist Bitcoin, wie funktioniert die Blockchain, warum ist es revolutionär. Perfekt für Einsteiger.',
|
||||||
|
'duration_minutes' => 90,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Event;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Event>
|
||||||
|
*/
|
||||||
|
class EventFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$eventId = bin2hex(random_bytes(32));
|
||||||
|
$pubkey = bin2hex(random_bytes(32));
|
||||||
|
$createdAt = fake()->dateTimeBetween('-1 year')->getTimestamp();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'event_id' => $eventId,
|
||||||
|
'parent_event_id' => null,
|
||||||
|
'pubkey' => $pubkey,
|
||||||
|
'type' => fake()->randomElement(['note', 'long-form', 'reaction']),
|
||||||
|
'json' => json_encode([
|
||||||
|
'id' => $eventId,
|
||||||
|
'pubkey' => $pubkey,
|
||||||
|
'created_at' => $createdAt,
|
||||||
|
'kind' => 1,
|
||||||
|
'tags' => [],
|
||||||
|
'content' => fake()->paragraph(),
|
||||||
|
'sig' => bin2hex(random_bytes(64)),
|
||||||
|
], JSON_THROW_ON_ERROR),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fromMarkusTurm(): static
|
||||||
|
{
|
||||||
|
return $this->state(function () {
|
||||||
|
$eventId = bin2hex(random_bytes(32));
|
||||||
|
$pubkey = 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba';
|
||||||
|
$createdAt = fake()->dateTimeBetween('-30 days')->getTimestamp();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'event_id' => $eventId,
|
||||||
|
'pubkey' => $pubkey,
|
||||||
|
'type' => 'note',
|
||||||
|
'json' => json_encode([
|
||||||
|
'id' => $eventId,
|
||||||
|
'pubkey' => $pubkey,
|
||||||
|
'created_at' => $createdAt,
|
||||||
|
'kind' => 1,
|
||||||
|
'tags' => [['t', 'bitcoin'], ['t', 'einundzwanzig']],
|
||||||
|
'content' => 'Bitcoin fixes this. #bitcoin #einundzwanzig',
|
||||||
|
'sig' => bin2hex(random_bytes(64)),
|
||||||
|
], JSON_THROW_ON_ERROR),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Lecturer;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Lecturer>
|
||||||
|
*/
|
||||||
|
class LecturerFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => fake()->name(),
|
||||||
|
'bio' => fake()->paragraph(),
|
||||||
|
'pubkey' => bin2hex(random_bytes(32)),
|
||||||
|
'website' => fake()->url(),
|
||||||
|
'active' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markusTurm(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Markus Turm',
|
||||||
|
'bio' => 'Hobby Hedge Fund Manager. Bitcoin, Austrian Economics, Laissez-Faire Radical.',
|
||||||
|
'npub' => 'npub17fqtu2mgf7zueq2kdusgzwr2lqwhgfl2scjsez77ddag2qx8vxaq3vnr8y',
|
||||||
|
'pubkey' => 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
|
||||||
|
'website' => 'https://einundzwanzig.space',
|
||||||
|
'active' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function inactive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => ['active' => false]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Meetup;
|
||||||
|
use App\Models\MeetupEvent;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<MeetupEvent>
|
||||||
|
*/
|
||||||
|
class MeetupEventFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'meetup_id' => Meetup::factory(),
|
||||||
|
'start' => fake()->dateTimeBetween('+1 day', '+90 days'),
|
||||||
|
'location' => fake()->company().', '.fake()->streetAddress(),
|
||||||
|
'description' => fake()->paragraph(),
|
||||||
|
'link' => fake()->url(),
|
||||||
|
'attendees' => [
|
||||||
|
'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
|
||||||
|
bin2hex(random_bytes(32)),
|
||||||
|
],
|
||||||
|
'might_attendees' => [bin2hex(random_bytes(32))],
|
||||||
|
'nostr_status' => 'Sent event '.bin2hex(random_bytes(8)).' to wss://simple-relay.codingarena.top',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function past(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'start' => fake()->dateTimeBetween('-90 days', '-1 day'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function upcoming(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'start' => fake()->dateTimeBetween('+1 day', '+30 days'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\City;
|
||||||
|
use App\Models\Meetup;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Meetup>
|
||||||
|
*/
|
||||||
|
class MeetupFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$name = 'Einundzwanzig '.fake()->city();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'city_id' => City::factory(),
|
||||||
|
'name' => $name,
|
||||||
|
'description' => fake()->paragraph(),
|
||||||
|
'website' => 'https://einundzwanzig.space/meetups/'.str()->slug($name),
|
||||||
|
'nostr_pubkey' => bin2hex(random_bytes(32)),
|
||||||
|
'github_data' => [
|
||||||
|
'repo' => 'einundzwanzig-portal',
|
||||||
|
'path' => 'meetups/'.str()->slug($name).'.json',
|
||||||
|
],
|
||||||
|
'simplified_geojson' => null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function vienna(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Einundzwanzig Wien',
|
||||||
|
'description' => 'Das Bitcoin-only Meetup in Wien. Jeden ersten Donnerstag im Monat.',
|
||||||
|
'website' => 'https://einundzwanzig.space/meetups/wien',
|
||||||
|
'nostr_pubkey' => 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function berlin(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Einundzwanzig Berlin',
|
||||||
|
'description' => 'Bitcoin Meetup in der Hauptstadt. Plebs willkommen.',
|
||||||
|
'website' => 'https://einundzwanzig.space/meetups/berlin',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Profile;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Profile>
|
||||||
|
*/
|
||||||
|
class ProfileFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$name = fake()->userName();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'pubkey' => bin2hex(random_bytes(32)),
|
||||||
|
'name' => $name,
|
||||||
|
'display_name' => fake()->name(),
|
||||||
|
'picture' => 'https://image.nostr.build/'.fake()->uuid().'.jpg',
|
||||||
|
'banner' => null,
|
||||||
|
'website' => fake()->url(),
|
||||||
|
'about' => fake()->sentence(12),
|
||||||
|
'nip05' => $name.'@einundzwanzig.space',
|
||||||
|
'lud16' => $name.'@walletofsatoshi.com',
|
||||||
|
'lud06' => null,
|
||||||
|
'deleted' => false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markusTurm(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'pubkey' => 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
|
||||||
|
'name' => 'markusturm',
|
||||||
|
'display_name' => 'Markus Turm',
|
||||||
|
'picture' => 'https://m.primal.net/HQqf.jpg',
|
||||||
|
'banner' => 'https://m.primal.net/HQqg.jpg',
|
||||||
|
'website' => 'https://einundzwanzig.space',
|
||||||
|
'about' => '#Bitcoin | Austrian Economics | Laissez-Faire Radical | @_einundzwanzig_',
|
||||||
|
'nip05' => 'markusturm@einundzwanzig.space',
|
||||||
|
'lud16' => 'markusturm@walletofsatoshi.com',
|
||||||
|
'deleted' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Event;
|
||||||
|
use App\Models\RenderedEvent;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<RenderedEvent>
|
||||||
|
*/
|
||||||
|
class RenderedEventFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'event_id' => Event::factory()->create()->event_id,
|
||||||
|
'html' => '<p>'.fake()->paragraph().'</p>',
|
||||||
|
'profile_image' => 'https://m.primal.net/'.fake()->uuid().'.jpg',
|
||||||
|
'profile_name' => fake()->userName(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\SecurityAttempt;
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
|
use Illuminate\Auth\AuthenticationException;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<SecurityAttempt>
|
||||||
|
*/
|
||||||
|
class SecurityAttemptFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'ip_address' => fake()->ipv4(),
|
||||||
|
'user_agent' => fake()->userAgent(),
|
||||||
|
'method' => fake()->randomElement(['GET', 'POST']),
|
||||||
|
'url' => fake()->url(),
|
||||||
|
'route_name' => fake()->randomElement(['association.profile', 'association.elections', 'association.projectSupport']),
|
||||||
|
'exception_class' => fake()->randomElement([
|
||||||
|
ValidationException::class,
|
||||||
|
AuthenticationException::class,
|
||||||
|
AuthorizationException::class,
|
||||||
|
]),
|
||||||
|
'exception_message' => fake()->sentence(),
|
||||||
|
'component_name' => fake()->randomElement(['association.profile', 'association.election.show']),
|
||||||
|
'target_property' => fake()->randomElement(['name', 'email', 'npub']),
|
||||||
|
'payload' => ['attempt' => fake()->word()],
|
||||||
|
'severity' => fake()->randomElement(['low', 'medium', 'high', 'critical']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function high(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => ['severity' => 'high']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function critical(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => ['severity' => 'critical']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\City;
|
||||||
|
use App\Models\Venue;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Venue>
|
||||||
|
*/
|
||||||
|
class VenueFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'city_id' => City::factory(),
|
||||||
|
'name' => fake()->randomElement(['Bitcoin Bar', 'Plebsfreundlicher Coworking', 'Hodler Hangout', 'Lightning Lounge']).' '.fake()->lastName(),
|
||||||
|
'description' => fake()->paragraph(),
|
||||||
|
'address' => fake()->streetAddress(),
|
||||||
|
'website' => fake()->url(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bitcoinBarVienna(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'name' => 'Bitcoin Bar Wien',
|
||||||
|
'description' => 'Die erste Bitcoin-only Bar im 7. Bezirk.',
|
||||||
|
'address' => 'Neubaugasse 21, 1070 Wien',
|
||||||
|
'website' => 'https://bitcoin-bar.at',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\EinundzwanzigPleb;
|
||||||
|
use App\Models\ProjectProposal;
|
||||||
|
use App\Models\Vote;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Vote>
|
||||||
|
*/
|
||||||
|
class VoteFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'einundzwanzig_pleb_id' => EinundzwanzigPleb::factory(),
|
||||||
|
'project_proposal_id' => ProjectProposal::factory(),
|
||||||
|
'value' => fake()->boolean(70),
|
||||||
|
'reason' => fake()->optional(0.3)->sentence(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => ['value' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => ['value' => false]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('countries', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('code', 8)->unique();
|
||||||
|
$table->json('language_codes')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('countries');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('cities', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('country_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('slug')->nullable()->index();
|
||||||
|
$table->decimal('latitude', 10, 7)->nullable();
|
||||||
|
$table->decimal('longitude', 10, 7)->nullable();
|
||||||
|
$table->json('osm_relation')->nullable();
|
||||||
|
$table->json('simplified_geojson')->nullable();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('cities');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('lecturers', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('slug')->nullable()->index();
|
||||||
|
$table->text('bio')->nullable();
|
||||||
|
$table->string('npub', 63)->nullable()->index();
|
||||||
|
$table->string('pubkey', 64)->nullable()->index();
|
||||||
|
$table->string('website')->nullable();
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('lecturers');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('categories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name')->unique();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('categories');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('meetups', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('city_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('slug')->nullable()->index();
|
||||||
|
$table->text('description')->nullable();
|
||||||
|
$table->string('website')->nullable();
|
||||||
|
$table->string('nostr_pubkey', 64)->nullable();
|
||||||
|
$table->json('github_data')->nullable();
|
||||||
|
$table->json('simplified_geojson')->nullable();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('meetups');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('meetup_events', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('meetup_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->timestamp('start');
|
||||||
|
$table->string('location')->nullable();
|
||||||
|
$table->text('description')->nullable();
|
||||||
|
$table->string('link')->nullable();
|
||||||
|
$table->json('attendees')->nullable();
|
||||||
|
$table->json('might_attendees')->nullable();
|
||||||
|
$table->string('nostr_status')->nullable();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('meetup_events');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('venues', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('city_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('slug')->nullable()->index();
|
||||||
|
$table->text('description')->nullable();
|
||||||
|
$table->string('address')->nullable();
|
||||||
|
$table->string('website')->nullable();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('venues');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('courses', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('lecturer_id')->nullable()->constrained()->nullOnDelete();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('slug')->nullable()->index();
|
||||||
|
$table->text('description')->nullable();
|
||||||
|
$table->unsignedInteger('duration_minutes')->nullable();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('courses');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('course_events', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('course_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('venue_id')->nullable()->constrained()->nullOnDelete();
|
||||||
|
$table->timestamp('from');
|
||||||
|
$table->timestamp('to')->nullable();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('course_events');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('category_course', function (Blueprint $table) {
|
||||||
|
$table->foreignId('category_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('course_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->primary(['category_id', 'course_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('category_course');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('meetup_user', function (Blueprint $table) {
|
||||||
|
$table->foreignId('meetup_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->primary(['meetup_id', 'user_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('meetup_user');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\Course;
|
||||||
|
use App\Models\CourseEvent;
|
||||||
|
use App\Models\Lecturer;
|
||||||
|
use App\Models\Venue;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class CourseSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$categories = collect([
|
||||||
|
'Grundlagen',
|
||||||
|
'Self Custody',
|
||||||
|
'Lightning',
|
||||||
|
'Nostr',
|
||||||
|
'Privacy',
|
||||||
|
'Wirtschaft',
|
||||||
|
])->map(fn (string $name) => Category::query()->create(['name' => $name]));
|
||||||
|
|
||||||
|
$markus = Lecturer::factory()->markusTurm()->create();
|
||||||
|
$otherLecturers = Lecturer::factory()->count(3)->create();
|
||||||
|
|
||||||
|
$bitcoinBasics = Course::factory()->bitcoinBasics()->for($markus)->create();
|
||||||
|
$bitcoinBasics->categories()->attach([
|
||||||
|
$categories->firstWhere('name', 'Grundlagen')->id,
|
||||||
|
$categories->firstWhere('name', 'Wirtschaft')->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$lightningCourse = Course::factory()
|
||||||
|
->state(['name' => 'Lightning Network 101'])
|
||||||
|
->for($markus)
|
||||||
|
->create();
|
||||||
|
$lightningCourse->categories()->attach($categories->firstWhere('name', 'Lightning')->id);
|
||||||
|
|
||||||
|
foreach ($otherLecturers as $lecturer) {
|
||||||
|
$course = Course::factory()->for($lecturer)->create();
|
||||||
|
$course->categories()->attach($categories->random(rand(1, 3))->pluck('id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$venues = Venue::query()->take(3)->get();
|
||||||
|
if ($venues->isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Course::query()->get() as $course) {
|
||||||
|
CourseEvent::factory()->for($course)->for($venues->random())->past()->create();
|
||||||
|
CourseEvent::factory()->for($course)->for($venues->random())->create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,21 +3,26 @@
|
|||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
class DatabaseSeeder extends Seeder
|
class DatabaseSeeder extends Seeder
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Seed the application's database.
|
|
||||||
*/
|
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
// User::factory(10)->create();
|
User::query()->updateOrCreate(
|
||||||
|
['email' => 'test@example.com'],
|
||||||
|
['name' => 'Test User', 'password' => bcrypt('password')]
|
||||||
|
);
|
||||||
|
|
||||||
User::factory()->create([
|
$this->call([
|
||||||
'name' => 'Test User',
|
PlebSeeder::class,
|
||||||
'email' => 'test@example.com',
|
ProjectProposalSeeder::class,
|
||||||
|
ElectionSeeder::class,
|
||||||
|
NostrSeeder::class,
|
||||||
|
MeetupSeeder::class,
|
||||||
|
CourseSeeder::class,
|
||||||
|
NotificationSeeder::class,
|
||||||
|
SecuritySeeder::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Election;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class ElectionSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$candidates = config('einundzwanzig.config.current_board');
|
||||||
|
|
||||||
|
Election::query()->updateOrCreate(
|
||||||
|
['year' => 2025],
|
||||||
|
[
|
||||||
|
'candidates' => $candidates,
|
||||||
|
'end_time' => now()->setDate(2025, 4, 15),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
Election::query()->updateOrCreate(
|
||||||
|
['year' => 2026],
|
||||||
|
[
|
||||||
|
'candidates' => $candidates,
|
||||||
|
'end_time' => now()->addMonths(2),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
Election::query()->updateOrCreate(
|
||||||
|
['year' => 2027],
|
||||||
|
[
|
||||||
|
'candidates' => [],
|
||||||
|
'end_time' => now()->addYear()->addMonths(3),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\City;
|
||||||
|
use App\Models\Country;
|
||||||
|
use App\Models\Meetup;
|
||||||
|
use App\Models\MeetupEvent;
|
||||||
|
use App\Models\Venue;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class MeetupSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$de = Country::factory()->germany()->create();
|
||||||
|
$at = Country::factory()->austria()->create();
|
||||||
|
$ch = Country::factory()->switzerland()->create();
|
||||||
|
|
||||||
|
$vienna = City::factory()->vienna()->for($at)->create();
|
||||||
|
$berlin = City::factory()->berlin()->for($de)->create();
|
||||||
|
$munich = City::factory()->munich()->for($de)->create();
|
||||||
|
$zurich = City::factory()->zurich()->for($ch)->create();
|
||||||
|
|
||||||
|
$viennaMeetup = Meetup::factory()->vienna()->for($vienna)->create();
|
||||||
|
$berlinMeetup = Meetup::factory()->berlin()->for($berlin)->create();
|
||||||
|
$munichMeetup = Meetup::factory()->state(['name' => 'Einundzwanzig München'])->for($munich)->create();
|
||||||
|
$zurichMeetup = Meetup::factory()->state(['name' => 'Einundzwanzig Zürich'])->for($zurich)->create();
|
||||||
|
|
||||||
|
Venue::factory()->bitcoinBarVienna()->for($vienna)->create();
|
||||||
|
Venue::factory()->count(2)->for($berlin)->create();
|
||||||
|
Venue::factory()->count(2)->for($munich)->create();
|
||||||
|
Venue::factory()->count(1)->for($zurich)->create();
|
||||||
|
|
||||||
|
foreach ([$viennaMeetup, $berlinMeetup, $munichMeetup, $zurichMeetup] as $meetup) {
|
||||||
|
MeetupEvent::factory()->past()->for($meetup)->count(2)->create();
|
||||||
|
MeetupEvent::factory()->upcoming()->for($meetup)->count(2)->create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Event;
|
||||||
|
use App\Models\Profile;
|
||||||
|
use App\Models\RenderedEvent;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class NostrSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
Profile::factory()->markusTurm()->create();
|
||||||
|
|
||||||
|
$boardProfiles = [
|
||||||
|
[
|
||||||
|
'pubkey' => '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
|
||||||
|
'name' => 'pleb1',
|
||||||
|
'display_name' => 'Vorstandsmitglied 1',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'pubkey' => '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
|
||||||
|
'name' => 'pleb2',
|
||||||
|
'display_name' => 'Vorstandsmitglied 2',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'pubkey' => '7acf30cf60b85c62b8f654556cc21e4016df8f5604b3b6892794f88bb80d7a1d',
|
||||||
|
'name' => 'pleb3',
|
||||||
|
'display_name' => 'Vorstandsmitglied 3',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'pubkey' => '19e358b8011f5f4fc653c565c6d4c2f33f32661f4f90982c9eedc292a8774ec3',
|
||||||
|
'name' => 'pleb4',
|
||||||
|
'display_name' => 'Vorstandsmitglied 4',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($boardProfiles as $data) {
|
||||||
|
Profile::query()->create([
|
||||||
|
...$data,
|
||||||
|
'about' => 'Vorstand bei Einundzwanzig. Bitcoin only.',
|
||||||
|
'nip05' => $data['name'].'@einundzwanzig.space',
|
||||||
|
'lud16' => $data['name'].'@walletofsatoshi.com',
|
||||||
|
'website' => 'https://einundzwanzig.space',
|
||||||
|
'picture' => 'https://m.primal.net/'.fake()->uuid().'.jpg',
|
||||||
|
'deleted' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::factory()
|
||||||
|
->fromMarkusTurm()
|
||||||
|
->count(5)
|
||||||
|
->create()
|
||||||
|
->each(function (Event $event): void {
|
||||||
|
RenderedEvent::query()->create([
|
||||||
|
'event_id' => $event->event_id,
|
||||||
|
'html' => '<div class="prose"><p>'.fake()->paragraph().'</p></div>',
|
||||||
|
'profile_image' => 'https://m.primal.net/HQqf.jpg',
|
||||||
|
'profile_name' => 'markusturm',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Enums\NewsCategory;
|
||||||
|
use App\Models\EinundzwanzigPleb;
|
||||||
|
use App\Models\Notification;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class NotificationSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$markus = EinundzwanzigPleb::query()
|
||||||
|
->where('npub', 'npub17fqtu2mgf7zueq2kdusgzwr2lqwhgfl2scjsez77ddag2qx8vxaq3vnr8y')
|
||||||
|
->first() ?? EinundzwanzigPleb::query()->first();
|
||||||
|
|
||||||
|
if (! $markus) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$news = [
|
||||||
|
[
|
||||||
|
'name' => 'Generalversammlung 2026 - Save the Date',
|
||||||
|
'description' => "Die nächste Generalversammlung findet am 21. Juni 2026 in Wien statt. Alle Mitglieder sind herzlich eingeladen.\n\nAgenda:\n- Bericht des Vorstands\n- Wahl des neuen Vorstands\n- Project Support Abstimmungen",
|
||||||
|
'category' => NewsCategory::Veranstaltungen,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Neuer Lightning Watchtower verfügbar',
|
||||||
|
'description' => 'Mitglieder können ab sofort unseren Watchtower nutzen. Details zur Konfiguration im Mitgliederbereich.',
|
||||||
|
'category' => NewsCategory::Bitcoin,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Meetup-Welle im Sommer 2026',
|
||||||
|
'description' => 'Über 30 Einundzwanzig Meetups im DACH-Raum geplant. Termine im Portal.',
|
||||||
|
'category' => NewsCategory::Meetups,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Q1 2026 Finanzbericht',
|
||||||
|
'description' => 'Der Finanzbericht für das erste Quartal 2026 ist im Mitgliederbereich abrufbar.',
|
||||||
|
'category' => NewsCategory::Finanzen,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Neue Bildungsinitiative gestartet',
|
||||||
|
'description' => 'Die Einundzwanzig Bitcoin Schule startet im September. Anmeldung ab sofort möglich.',
|
||||||
|
'category' => NewsCategory::Bildung,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($news as $item) {
|
||||||
|
Notification::query()->create([
|
||||||
|
...$item,
|
||||||
|
'einundzwanzig_pleb_id' => $markus->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Enums\AssociationStatus;
|
||||||
|
use App\Models\EinundzwanzigPleb;
|
||||||
|
use App\Models\PaymentEvent;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class PlebSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array<int, array{npub:string, pubkey:string, email:string, nip05:string, status:AssociationStatus, paid_years:array<int>}>
|
||||||
|
*/
|
||||||
|
private array $boardMembers = [
|
||||||
|
[
|
||||||
|
'npub' => 'npub17fqtu2mgf7zueq2kdusgzwr2lqwhgfl2scjsez77ddag2qx8vxaq3vnr8y',
|
||||||
|
'pubkey' => 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
|
||||||
|
'email' => 'markus@einundzwanzig.space',
|
||||||
|
'nip05' => 'markusturm',
|
||||||
|
'status' => AssociationStatus::HONORARY,
|
||||||
|
'paid_years' => [2024, 2025, 2026],
|
||||||
|
'name' => 'Markus Turm',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'npub' => 'npub1pt0kw36ue3w2g4haxq3wgm6a2fhtptmzsjlc2j2vphtcgle72qesgpjyc6',
|
||||||
|
'pubkey' => '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
|
||||||
|
'email' => 'board1@einundzwanzig.space',
|
||||||
|
'nip05' => 'pleb1',
|
||||||
|
'status' => AssociationStatus::HONORARY,
|
||||||
|
'paid_years' => [2024, 2025, 2026],
|
||||||
|
'name' => 'Vorstand 1',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'npub' => 'npub1gvqkjccl9urg93svaw60jqkk3ux8r3ycl5t3rlvc9uzjeu0agfuss8x8qy',
|
||||||
|
'pubkey' => '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
|
||||||
|
'email' => 'board2@einundzwanzig.space',
|
||||||
|
'nip05' => 'pleb2',
|
||||||
|
'status' => AssociationStatus::HONORARY,
|
||||||
|
'paid_years' => [2025, 2026],
|
||||||
|
'name' => 'Vorstand 2',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'npub' => 'npub10t8npnmqhpwx9w8k232kess7gqtdlr6kqjemdzf8jnughwqd0gwsez0924',
|
||||||
|
'pubkey' => '7acf30cf60b85c62b8f654556cc21e4016df8f5604b3b6892794f88bb80d7a1d',
|
||||||
|
'email' => 'board3@einundzwanzig.space',
|
||||||
|
'nip05' => 'pleb3',
|
||||||
|
'status' => AssociationStatus::HONORARY,
|
||||||
|
'paid_years' => [2025, 2026],
|
||||||
|
'name' => 'Vorstand 3',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'npub' => 'npub1r8343wqpra05l3jnc4jud4xz7vlnyeslf7gfsty7ahpf92rhfmpsmqwym8',
|
||||||
|
'pubkey' => '19e358b8011f5f4fc653c565c6d4c2f33f32661f4f90982c9eedc292a8774ec3',
|
||||||
|
'email' => 'board4@einundzwanzig.space',
|
||||||
|
'nip05' => 'pleb4',
|
||||||
|
'status' => AssociationStatus::HONORARY,
|
||||||
|
'paid_years' => [2026],
|
||||||
|
'name' => 'Vorstand 4',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
foreach ($this->boardMembers as $member) {
|
||||||
|
$pleb = EinundzwanzigPleb::query()->create([
|
||||||
|
'npub' => $member['npub'],
|
||||||
|
'pubkey' => $member['pubkey'],
|
||||||
|
'email' => $member['email'],
|
||||||
|
'nip05_handle' => $member['nip05'],
|
||||||
|
'association_status' => $member['status'],
|
||||||
|
'application_text' => 'Ich bin Teil des Einundzwanzig Vorstands und unterstütze die Mission, Bitcoin in den deutschsprachigen Raum zu bringen.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($member['paid_years'] as $year) {
|
||||||
|
PaymentEvent::query()->create([
|
||||||
|
'einundzwanzig_pleb_id' => $pleb->id,
|
||||||
|
'year' => $year,
|
||||||
|
'amount' => 21000,
|
||||||
|
'paid' => true,
|
||||||
|
'event_id' => 'seed_'.bin2hex(random_bytes(16)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EinundzwanzigPleb::factory()
|
||||||
|
->count(8)
|
||||||
|
->active()
|
||||||
|
->create()
|
||||||
|
->each(function (EinundzwanzigPleb $pleb): void {
|
||||||
|
PaymentEvent::factory()
|
||||||
|
->paid()
|
||||||
|
->withYear((int) date('Y'))
|
||||||
|
->for($pleb, 'pleb')
|
||||||
|
->create();
|
||||||
|
});
|
||||||
|
|
||||||
|
EinundzwanzigPleb::factory()
|
||||||
|
->count(5)
|
||||||
|
->state(['association_status' => AssociationStatus::PASSIVE])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
EinundzwanzigPleb::factory()
|
||||||
|
->count(3)
|
||||||
|
->state([
|
||||||
|
'association_status' => AssociationStatus::DEFAULT,
|
||||||
|
'application_text' => 'Ich möchte Mitglied bei Einundzwanzig werden und die Bitcoin-Community im deutschsprachigen Raum mitgestalten.',
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\EinundzwanzigPleb;
|
||||||
|
use App\Models\ProjectProposal;
|
||||||
|
use App\Models\Vote;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class ProjectProposalSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array<int, array{name:string, description:string, support_in_sats:int, website:string, accepted:bool}>
|
||||||
|
*/
|
||||||
|
private array $proposals = [
|
||||||
|
[
|
||||||
|
'name' => 'Einundzwanzig Portal Refactoring',
|
||||||
|
'description' => "Das Einundzwanzig Portal benötigt ein größeres Refactoring, um die Performance zu verbessern und neue Features wie Meetup-Anmeldung über Nostr DMs zu ermöglichen.\n\n**Geplante Änderungen:**\n- Migration auf Livewire 4\n- Nostr Login per NIP-46\n- Meetup Kalender als ICS-Feed\n- API für externe Tools",
|
||||||
|
'support_in_sats' => 2_100_000,
|
||||||
|
'website' => 'https://github.com/einundzwanzig-portal/einundzwanzig-portal',
|
||||||
|
'accepted' => true,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Bitcoin Schule für Plebs',
|
||||||
|
'description' => "Curriculum für eine deutschsprachige Bitcoin-Schule mit modular aufgebauten Kursen für Einsteiger und Fortgeschrittene.\n\n- Onboarding für totale Beginner\n- Self Custody Workshops\n- Lightning Network Hands-on\n- Privacy & Coinjoin Module",
|
||||||
|
'support_in_sats' => 1_500_000,
|
||||||
|
'website' => 'https://einundzwanzig.school',
|
||||||
|
'accepted' => true,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Lightning Watchtower für Mitglieder',
|
||||||
|
'description' => 'Hosting eines Lightning Watchtower Service exklusiv für Einundzwanzig Mitglieder, um Channel-Verlust durch böswillige Counterparties zu verhindern.',
|
||||||
|
'support_in_sats' => 500_000,
|
||||||
|
'website' => 'https://einundzwanzig.space/benefits',
|
||||||
|
'accepted' => false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Nostr Relay Hosting',
|
||||||
|
'description' => 'Betrieb eines schnellen Nostr Relay (`wss://simple-relay.codingarena.top`) für die Einundzwanzig Community. Optimiert für deutschsprachige Inhalte und Meetup-Events.',
|
||||||
|
'support_in_sats' => 800_000,
|
||||||
|
'website' => 'https://simple-relay.codingarena.top',
|
||||||
|
'accepted' => true,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Meetup Sticker Druck Q3 2026',
|
||||||
|
'description' => 'Bestellung von 5000 Einundzwanzig Stickern für die Meetups im DACH-Raum. Verteilung über die lokalen Meetup Organisatoren.',
|
||||||
|
'support_in_sats' => 210_000,
|
||||||
|
'website' => 'https://einundzwanzig.space',
|
||||||
|
'accepted' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$plebs = EinundzwanzigPleb::query()->get();
|
||||||
|
if ($plebs->isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$markus = EinundzwanzigPleb::query()
|
||||||
|
->where('npub', 'npub17fqtu2mgf7zueq2kdusgzwr2lqwhgfl2scjsez77ddag2qx8vxaq3vnr8y')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
foreach ($this->proposals as $index => $data) {
|
||||||
|
$pleb = $markus && $index < 2 ? $markus : $plebs->random();
|
||||||
|
|
||||||
|
$proposal = ProjectProposal::query()->create([
|
||||||
|
'einundzwanzig_pleb_id' => $pleb->id,
|
||||||
|
'name' => $data['name'],
|
||||||
|
'description' => $data['description'],
|
||||||
|
'support_in_sats' => $data['support_in_sats'],
|
||||||
|
'website' => $data['website'],
|
||||||
|
'accepted' => $data['accepted'],
|
||||||
|
'sats_paid' => $data['accepted'] ? $data['support_in_sats'] : null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($plebs->random(min($plebs->count(), 6)) as $voter) {
|
||||||
|
Vote::query()->updateOrCreate(
|
||||||
|
[
|
||||||
|
'einundzwanzig_pleb_id' => $voter->id,
|
||||||
|
'project_proposal_id' => $proposal->id,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'value' => fake()->boolean(70),
|
||||||
|
'reason' => fake()->optional(0.4)->sentence(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\SecurityAttempt;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class SecuritySeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
SecurityAttempt::factory()->count(15)->create();
|
||||||
|
SecurityAttempt::factory()->high()->count(4)->create();
|
||||||
|
SecurityAttempt::factory()->critical()->count(1)->create();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -243,7 +243,7 @@ new class extends Component {
|
|||||||
->whereIn('association_status', [3, 4])
|
->whereIn('association_status', [3, 4])
|
||||||
->where(fn ($query) => $query
|
->where(fn ($query) => $query
|
||||||
->where('pubkey', 'like', "%$value%")
|
->where('pubkey', 'like', "%$value%")
|
||||||
->orWhereHas('profile', fn ($query) => $query->where('name', 'ilike', "%$value%")))
|
->orWhereHas('profile', fn ($query) => $query->whereLike('name', "%$value%")))
|
||||||
->orderBy('association_status', 'desc')
|
->orderBy('association_status', 'desc')
|
||||||
->get()
|
->get()
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ new class extends Component
|
|||||||
if ($this->search) {
|
if ($this->search) {
|
||||||
$query->where(function ($query) {
|
$query->where(function ($query) {
|
||||||
$query->whereHas('profile', function ($query) {
|
$query->whereHas('profile', function ($query) {
|
||||||
$query->where('name', 'ilike', '%'.$this->search.'%');
|
$query->whereLike('name', '%'.$this->search.'%');
|
||||||
})->orWhere('npub', 'like', '%'.$this->search.'%');
|
})->orWhere('npub', 'like', '%'.$this->search.'%');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,10 +54,10 @@ new class extends Component {
|
|||||||
])
|
])
|
||||||
->where(function ($query) {
|
->where(function ($query) {
|
||||||
$query
|
$query
|
||||||
->where('name', 'ilike', '%'.$this->search.'%')
|
->whereLike('name', '%'.$this->search.'%')
|
||||||
->orWhere('description', 'ilike', '%'.$this->search.'%')
|
->orWhereLike('description', '%'.$this->search.'%')
|
||||||
->orWhereHas('einundzwanzigPleb.profile', function ($q) {
|
->orWhereHas('einundzwanzigPleb.profile', function ($q) {
|
||||||
$q->where('name', 'ilike', '%'.$this->search.'%');
|
$q->whereLike('name', '%'.$this->search.'%');
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
|
|||||||
Reference in New Issue
Block a user