added note visibility

This commit is contained in:
Ghostie 2025-01-12 15:10:44 -05:00
parent daa8b3eaeb
commit 518586b6ab
11 changed files with 130 additions and 16 deletions

View File

@ -2,7 +2,7 @@
- [-] Activitypub
- [x] Accounts
- [-] Posts
- [x] Posts
- [x] Local posts should be federated
- [x] Local posts should be deleted
- [x] Remote posts should be fetched
@ -18,10 +18,10 @@
- [x] Tags
- [x] Mentions
- [x] Local mentions
- [ ] Private post
- [x] Private post
- [x] Pinned Posts
- [x] Nodeinfo
- [ ] Notifications
- [x] Notifications
- [-] Social features
- [x] Profile

View File

@ -125,6 +125,7 @@ class ActionsPost
"summary" => $processed ["summary"],
"content" => $processed ["content"],
"attachments" => $processed ["attachments"],
"visibility" => $request ["visibility"],
"inReplyTo" => $processed ["inReplyTo"] ?? null,
"tags" => $processed ["tags"] ?? null,
"mentions" => $processed ["mentions"] ?? null

View File

@ -370,6 +370,7 @@ class APOutboxController extends Controller
}
}
$mentions = [];
if (isset ($request ["mentions"]))
{
foreach ($request ["mentions"] as $mention)
@ -387,9 +388,37 @@ class APOutboxController extends Controller
"note_id" => $note->id,
"actor_id" => $object->id
]);
$mentions[] = $object->actor_id;
}
}
if ($request ["visibility"] == "public")
{
$note->to = [
"https://www.w3.org/ns/activitystreams#Public"
];
$note->cc = [
$actor->followers
];
}
else if ($request ["visibility"] == "followers")
{
// TODO: Boosting should be disabled
$note->to = [
$actor->followers
];
$note->cc = [];
}
else if ($request ["visibility"] == "private")
{
// TODO: Boosting should be disabled
$note->to = $mentions;
}
$note->visibility = $request ["visibility"];
$note->save ();
$create_activity = TypeActivity::craft_create ($actor, $note);
$create_activity->to = $note->to;

View File

@ -21,6 +21,8 @@ class PostController extends Controller
if (!$actor)
return redirect ()->back ();
if (!$note->can_view ())
return redirect ()->back ()->with ("error", "You are not allowed to view this post.");
return view ("posts.show", compact ("note", "actor"));
}

View File

@ -32,7 +32,8 @@ class UserActionController extends Controller
$request->validate ([
"summary" => "nullable|string",
"content" => "required",
"files.*" => "max:4096"
"files.*" => "max:4096",
"visibility" => "required|in:public,private,followers",
]);
$response = ActionsPost::post_new ($request);

View File

@ -11,6 +11,6 @@ class Hashtag extends Model
];
public function get_notes () {
return $this->belongsToMany(Note::class, 'note_hashtag');
return $this->belongsToMany(Note::class, 'note_hashtag')->orderBy('created_at', 'desc');
}
}

View File

@ -20,7 +20,8 @@ class Note extends Model
"content",
"tag",
"to",
"cc"
"cc",
"visibility"
];
protected $casts = [
@ -88,4 +89,34 @@ class Note extends Model
{
return ProfilePin::where ("actor_id", $actor->id)->where ("note_id", $this->id)->first ();
}
public function can_view (Actor $actor = null)
{
$final_actor = $actor;
$note_actor = $this->get_actor ()->first ();
if (!$final_actor && auth ()->check ())
{
$final_actor = auth ()->user ()->actor;
}
if ($this->visibility == "public")
{
return true;
}
else if ($this->visibility == "followers" && $final_actor)
{
return $final_actor->friends_with ($note_actor);
}
else if ($this->visibility == "private" && $final_actor)
{
if ($final_actor == $note_actor)
return true;
$mention_exists = NoteMention::where ("note_id", $this->id)->where ("actor_id", $final_actor->id)->first ();
if ($mention_exists)
return true;
}
return false;
}
}

View File

@ -86,14 +86,6 @@ class TypeNote
"attributedTo" => $actor->actor_id,
"content" => $request ["content"] ?? null,
"tag" => $request ["tag"] ?? null,
// TODO: This should change when I implement visibilities and private notes
"to" => [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc" => [
$actor->followers
]
]);
$note->url = route ('posts.show', $note->id);
@ -107,6 +99,7 @@ class TypeNote
if ($activity)
$note->activity_id = $activity->id;
$note_actor = $actor;
if ($actor)
$note->actor_id = $actor->id;
else
@ -122,6 +115,7 @@ class TypeNote
}
$note->actor_id = $actor->id;
$note_actor = $actor;
}
$note->note_id = $request["id"] ?? null;
@ -132,6 +126,8 @@ class TypeNote
$note->content = $request["content"] ?? null;
$note->tag = $request["tag"] ?? null;
$note->created_at = $request["published"] ?? null;
$note->to = $request["to"] ?? null;
$note->cc = $request["cc"] ?? null;
$attachments = $note->attachments ()->get ();
foreach ($attachments as $attachment)
@ -238,6 +234,20 @@ class TypeNote
{
// TODO: Handle replies
}
$note_to = $note->to;
if (in_array ("https://www.w3.org/ns/activitystreams#Public", $note_to))
{
$note->visibility = "public";
}
else if (in_array ($note_actor->followers, $note_to))
{
$note->visibility = "followers";
}
else
{
$note->visibility = "private";
}
}
public static function create_from_request ($request, Activity $activity, Actor $actor)

View File

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('notes', function (Blueprint $table) {
$table->string ("visibility")->default ("public");
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('notes', function (Blueprint $table) {
$table->dropColumn ("visibility");
});
}
};

View File

@ -21,6 +21,9 @@ if ($actor->user_id)
$actor_url = route ('users.show', [ 'user_name' => $actor->user->name ]);
else
$actor_url = route ('users.show', [ 'user_name' => $actor->local_actor_id ]);
if (!$display_post->can_view ())
return;
@endphp
<tr>

View File

@ -10,9 +10,18 @@
<br>
<textarea name="content" placeholder="What's on your mind?" style="width: 100%"></textarea>
<input type="file" name="files[]" accept="image/*" multiple><br>
<button type="submit">Post</button>
<small>Markdown is supported</small>
<br>
<input type="file" name="files[]" accept="image/*" multiple><br>
<p>
<b>Visibility:</b>
<select name="visibility">
<option value="public">Public</option>
<option value="followers">Friends only</option>
<option value="private">Mentioned Only</option>
</select>
</p>
<button type="submit">Post</button>
@error ("content")
<div class="error">{{ $message }}</div>