mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-02-02 16:21:32 -08:00
federation: subscribe to remote community
This commit is contained in:
parent
c9beb0c0da
commit
d2a81ef76c
12 changed files with 71 additions and 18 deletions
|
@ -419,7 +419,12 @@ def shared_inbox():
|
|||
community = find_actor_or_create(community_ap_id)
|
||||
if user and community:
|
||||
member = CommunityMember.query.filter_by(user_id=user.id, community_id=community.id).first()
|
||||
db.session.delete(member)
|
||||
join_request = CommunityJoinRequest.query.filter_by(user_id=user.id,
|
||||
community_id=community.id).first()
|
||||
if member:
|
||||
db.session.delete(member)
|
||||
if join_request:
|
||||
db.session.delete(join_request)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Like': # Undoing an upvote
|
||||
|
|
|
@ -247,10 +247,10 @@ class HttpSignature:
|
|||
key_id: str,
|
||||
content_type: str = "application/json",
|
||||
method: Literal["get", "post"] = "post",
|
||||
timeout: int = 1,
|
||||
timeout: int = 5,
|
||||
):
|
||||
"""
|
||||
Performs an async request to the given path, with a document, signed
|
||||
Performs a request to the given path, with a document, signed
|
||||
as an identity.
|
||||
"""
|
||||
if "://" not in uri:
|
||||
|
@ -265,6 +265,34 @@ class HttpSignature:
|
|||
}
|
||||
# If we have a body, add a digest and content type
|
||||
if body is not None:
|
||||
if '@context' not in body: # add a default json-ld context if necessary
|
||||
body['@context'] = [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"piefed": "https://piefed.social/ns#",
|
||||
"lemmy": "https://join-lemmy.org/ns#",
|
||||
"litepub": "http://litepub.social/ns#",
|
||||
"pt": "https://joinpeertube.org/ns#",
|
||||
"sc": "http://schema.org/",
|
||||
"nsfl": "piefed:nsfl",
|
||||
"ChatMessage": "litepub:ChatMessage",
|
||||
"commentsEnabled": "pt:commentsEnabled",
|
||||
"sensitive": "as:sensitive",
|
||||
"matrixUserId": "lemmy:matrixUserId",
|
||||
"postingRestrictedToMods": "lemmy:postingRestrictedToMods",
|
||||
"removeData": "lemmy:removeData",
|
||||
"stickied": "lemmy:stickied",
|
||||
"moderators": {
|
||||
"@type": "@id",
|
||||
"@id": "lemmy:moderators"
|
||||
},
|
||||
"expires": "as:endTime",
|
||||
"distinguished": "lemmy:distinguished",
|
||||
"language": "sc:inLanguage",
|
||||
"identifier": "sc:identifier"
|
||||
}
|
||||
]
|
||||
body_bytes = json.dumps(body).encode("utf8")
|
||||
headers["Digest"] = cls.calculate_digest(body_bytes)
|
||||
headers["Content-Type"] = content_type
|
||||
|
@ -298,8 +326,7 @@ class HttpSignature:
|
|||
}
|
||||
)
|
||||
|
||||
# Announce ourselves with an agent similar to Mastodon
|
||||
headers["User-Agent"] = 'PieFed'
|
||||
headers["User-Agent"] = 'PieFed/1.0'
|
||||
|
||||
# Send the request with all those headers except the pseudo one
|
||||
del headers["(request-target)"]
|
||||
|
|
|
@ -201,7 +201,7 @@ def find_actor_or_create(actor: str) -> Union[User, Community, None]:
|
|||
ap_profile_id=actor).first() # finds communities formatted like https://localhost/c/*
|
||||
|
||||
if current_app.config['SERVER_NAME'] + '/u/' in actor:
|
||||
user = User.query.filter_by(username=actor.split('/')[-1], ap_id=None, banned=False).first() # finds local users
|
||||
user = User.query.filter_by(user_name=actor.split('/')[-1], ap_id=None, banned=False).first() # finds local users
|
||||
if user is None:
|
||||
return None
|
||||
elif actor.startswith('https://'):
|
||||
|
|
|
@ -28,7 +28,7 @@ class AddLocalCommunity(FlaskForm):
|
|||
|
||||
|
||||
class SearchRemoteCommunity(FlaskForm):
|
||||
address = StringField(_l('Server address'), validators=[DataRequired()])
|
||||
address = StringField(_l('Community address'), render_kw={'placeholder': 'e.g. !name@server'}, validators=[DataRequired()])
|
||||
submit = SubmitField(_l('Search'))
|
||||
|
||||
|
||||
|
|
|
@ -119,14 +119,14 @@ def subscribe(actor):
|
|||
db.session.commit()
|
||||
follow = {
|
||||
"actor": f"https://{current_app.config['SERVER_NAME']}/u/{current_user.user_name}",
|
||||
"to": [community.ap_id],
|
||||
"object": community.ap_id,
|
||||
"to": [community.ap_profile_id],
|
||||
"object": community.ap_profile_id,
|
||||
"type": "Follow",
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/follow/{join_request.id}"
|
||||
}
|
||||
try:
|
||||
message = HttpSignature.signed_request(community.ap_inbox_url, follow, current_user.private_key,
|
||||
current_user.ap_profile_id + '#main-key')
|
||||
current_user.profile_id() + '#main-key')
|
||||
if message.status_code == 200:
|
||||
flash('Your request to subscribe has been sent to ' + community.title)
|
||||
else:
|
||||
|
|
|
@ -264,6 +264,9 @@ class User(UserMixin, db.Model):
|
|||
return Community.query.filter(Community.banned == False).\
|
||||
join(CommunityMember).filter(CommunityMember.is_banned == False).all()
|
||||
|
||||
def profile_id(self):
|
||||
return self.ap_profile_id if self.ap_profile_id else f"{self.user_name}@{current_app.config['SERVER_NAME']}"
|
||||
|
||||
@staticmethod
|
||||
def verify_reset_password_token(token):
|
||||
try:
|
||||
|
|
|
@ -360,7 +360,7 @@ fieldset legend {
|
|||
}
|
||||
.post_list .post_teaser h3 {
|
||||
font-size: 120%;
|
||||
margin-top: 8px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.post_list .post_teaser .meta_row a, .post_list .post_teaser .main_row a, .post_list .post_teaser .utilities_row a {
|
||||
|
|
|
@ -121,7 +121,7 @@ nav, etc which are used site-wide */
|
|||
|
||||
h3 {
|
||||
font-size: 120%;
|
||||
margin-top: 8px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -391,6 +391,14 @@ nav.navbar {
|
|||
color: #777;
|
||||
}
|
||||
|
||||
.communities_table tr td {
|
||||
vertical-align: middle;
|
||||
padding-top: 6px;
|
||||
}
|
||||
.communities_table tr td:first-child {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #777;
|
||||
|
|
|
@ -165,6 +165,15 @@ nav.navbar {
|
|||
}
|
||||
}
|
||||
|
||||
.communities_table tr td {
|
||||
vertical-align: middle;
|
||||
padding-top: 6px;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: $dark-grey;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<div class="card mt-5">
|
||||
<div class="card-body p-6">
|
||||
<div class="card-title">{{ _('Search') }}</div>
|
||||
<p>Type address in the format !community@server.name. Search on <a href="https://lemmyverse.net/communities" target='_blank'>Lemmyverse.net</a> to find some.</p>
|
||||
{{ render_form(form) }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -22,12 +23,12 @@
|
|||
<p>
|
||||
<a href="/c/{{ new_community.link() }}"><img src="{{ new_community.icon_image()}}" class="community_icon rounded-circle" /></a>
|
||||
<a href="/c/{{ new_community.link() }}">{{ new_community.title }}@{{ new_community.ap_domain }}</a>
|
||||
{% if subscribed %}
|
||||
<a class="btn btn-primary mt-4" href="/c/{{ new_community.link() }}/unsubscribe">{{ _('Unsubscribe') }}</a>
|
||||
</p>
|
||||
<p> {% if subscribed %}
|
||||
<a class="btn btn-primary mt-4" href="/community/{{ new_community.link() }}/unsubscribe">{{ _('Unsubscribe') }}</a>
|
||||
{% else %}
|
||||
<a class="btn btn-primary mt-4" href="/c/{{ new_community.link() }}/subscribe">{{ _('Subscribe') }}</a>
|
||||
<a class="btn btn-primary mt-4" href="/community/{{ new_community.link() }}/subscribe">{{ _('Subscribe') }}</a>
|
||||
{% endif %}
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</div>
|
||||
{% if len(communities) > 0 %}
|
||||
<div class="table-responsive-md">
|
||||
<table class="table table-striped table-hover w-100">
|
||||
<table class="communities_table table table-striped table-hover w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" colspan="2">{{ _('Name') }}</th>
|
||||
|
@ -45,7 +45,7 @@
|
|||
{% for community in communities %}
|
||||
<tr class="">
|
||||
<td><a href="/c/{{ community.link() }}"><img src="{{ community.icon_image() }}" class="community_icon rounded-circle" loading="lazy" /></a></td>
|
||||
<th scope="row"><a href="/c/{{ community.link() }}">{{ community.display_name() }}</a></th>
|
||||
<td scope="row"><a href="/c/{{ community.link() }}">{{ community.display_name() }}</a></td>
|
||||
<td>{{ community.post_count }}</td>
|
||||
<td>{{ community.post_reply_count }}</td>
|
||||
<td>{{ moment(community.last_active).fromNow(refresh=True) }}</td>
|
||||
|
|
Loading…
Add table
Reference in a new issue