diff --git a/app/Http/Controllers/AP/APActorController.php b/app/Http/Controllers/AP/APActorController.php new file mode 100644 index 0000000..2364167 --- /dev/null +++ b/app/Http/Controllers/AP/APActorController.php @@ -0,0 +1,19 @@ +actor ()->get (); + $response = Actor::build_response ($actor->first ()); + return response ()->json ($response)->header ("Content-Type", "application/activity+json"); + } +} diff --git a/app/Http/Controllers/AP/APInboxController.php b/app/Http/Controllers/AP/APInboxController.php new file mode 100644 index 0000000..ce9ee36 --- /dev/null +++ b/app/Http/Controllers/AP/APInboxController.php @@ -0,0 +1,18 @@ +input ("resource"); + if (!isset ($resource)) { + return response ()->json ([ "error" => "missing resource parameter" ], 400); + } + + $host = parse_url ($resource, PHP_URL_HOST); + $user = explode (":", $resource); + if (count ($user) != 2) { + return response ()->json ([ "error" => "invalid resource parameter" ], 400); + } + + $user = $user[1]; + $user = explode ("@", $user); + if (count ($user) != 2) { + return response ()->json ([ "error" => "invalid resource parameter" ], 400); + } + + $user = $user[0]; + $actual_user = User::where ("name", $user)->first (); + $webfinger = [ + "subject" => $resource, + "links" => [ + [ + "rel" => "self", + "type" => "application/activity+json", + "href" => $actual_user->actor ()->first ()->actor_id + ] + ] + ]; + return response ()->json ($webfinger)->header ("Content-Type", "application/jrd+json"); + } +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index a56abfe..0d032ba 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -3,6 +3,8 @@ namespace App\Http\Controllers; use App\Models\User; +use App\Models\Actor; + use Illuminate\Http\Request; class UserController extends Controller @@ -26,6 +28,8 @@ class UserController extends Controller ]); $user = User::create ($incoming_fields); + $actor = new Actor (); + $actor->create_from_user ($user); auth ()->login ($user); return redirect ()->route ("home")->with ("success", "You have successfuly signed up!"); diff --git a/app/Models/Actor.php b/app/Models/Actor.php new file mode 100644 index 0000000..c57dcee --- /dev/null +++ b/app/Models/Actor.php @@ -0,0 +1,106 @@ + 4096, + "private_key_type" => OPENSSL_KEYTYPE_RSA + ]; + + $res = openssl_pkey_new ($config); + openssl_pkey_export ($res, $private_key); + + $public_key = openssl_pkey_get_details ($res); + + return $this->create ([ + "user_id" => $user->id, + + "type" => "Person", + "actor_id" => $app_url . "/ap/v1/user/" . $user->name, + + "following" => $app_url . "/ap/v1/user/" . $user->name . "/following", + "followers" => $app_url . "/ap/v1/user/" . $user->name . "/followers", + + "liked" => $app_url . "/ap/v1/user/" . $user->name . "/liked", + + "inbox" => $app_url . "/ap/v1/user/" . $user->name . "/inbox", + "outbox" => $app_url . "/ap/v1/user/" . $user->name . "/outbox", + + "sharedInbox" => $app_url . "/ap/v1/inbox", + + "preferredUsername" => $user->name, + "name" => $user->name, + "summary" => "", + + "public_key" => $public_key["key"], + "private_key" => $private_key + ]); + } + + public static function build_response (Actor $actor) + { + return [ + "@context" => [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1" + ], + "id" => $actor->actor_id, + "type" => $actor->type, + + "following" => $actor->following, + "followers" => $actor->followers, + + "liked" => $actor->liked, + + "inbox" => $actor->inbox, + "outbox" => $actor->outbox, + + "sharedInbox" => $actor->sharedInbox, + + "preferredUsername" => $actor->preferredUsername, + "name" => $actor->name, + "summary" => $actor->summary, + + "publicKey" => [ + "id" => $actor->actor_id . "#main-key", + "owner" => $actor->actor_id, + "publicKeyPem" => $actor->public_key + ] + ]; + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 71fb32d..9d71f7b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -53,4 +53,9 @@ class User extends Authenticatable return $value ? "/storage/avatars/" . $value : "/resources/img/default.jpg"; }); } + + public function actor () + { + return $this->hasOne (Actor::class); + } } diff --git a/database/migrations/2024_12_27_002726_create_actors_table.php b/database/migrations/2024_12_27_002726_create_actors_table.php new file mode 100644 index 0000000..425ec43 --- /dev/null +++ b/database/migrations/2024_12_27_002726_create_actors_table.php @@ -0,0 +1,50 @@ +id(); + + $table->foreignId ("user_id")->nullable ()->constrained ()->onDelete ("cascade"); + + $table->string ("type")->nullable (); + $table->string ("actor_id")->unique (); + + $table->string ("following")->nullable (); + $table->string ("followers")->nullable (); + + $table->string ("liked")->nullable (); + + $table->string ("inbox")->nullable (); + $table->string ("outbox")->nullable (); + + $table->string ("sharedInbox")->nullable (); + + $table->string ("preferredUsername")->nullable (); + $table->string ("name")->nullable (); + $table->string ("summary")->nullable (); + + $table->string ("public_key")->nullable (); + $table->string ("private_key")->nullable (); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('actors'); + } +}; diff --git a/resources/views/auth/signup.blade.php b/resources/views/auth/signup.blade.php index db5749e..f90d825 100644 --- a/resources/views/auth/signup.blade.php +++ b/resources/views/auth/signup.blade.php @@ -22,12 +22,12 @@