def on_get(self, req, resp): # For now I will assume that webfinger only asks for the actor, so resources # is just one element. if not 'resource' in req.params.keys(): raise falcon.HTTPBadRequest(description="No resource was provided along the request.") resources = req.params['resource'] username, domain = extract_user(resources) if username == None and domain == None: raise falcon.HTTPBadRequest(description="Unable to decode resource.") if domain == DOMAIN: user = UserProfile.get_or_none(username=username) if user: response = Webfinger(user).generate() resp.body = json.dumps(response) resp.status = falcon.HTTP_200 else: raise falcon.HTTPNotFound(description="User was not found.") else: raise falcon.HTTPBadRequest(description="Resouce domain doesn't match local domain.")
def uri_to_resource(self, klass): if self._local_uri(self.uri): if klass.__name__ == 'User': return UserProfile.get_or_none(ap_id=self.uri) else: return self.get_or_create_remote_user()
def get_or_create_remote_user(self): """ Returns an instance of User after looking for it using it's ap_id """ logging.debug(self.uri) user = UserProfile.get_or_none(ap_id=self.uri) if user == None: user = self.dereference() hostname = urlparse(user.id).hostname #username = "******".format(user.preferredUsername, hostname) logging.debug( f"I'm going to request the creation of user with username @{user.preferredUsername}" ) user = new_user(username=user.preferredUsername, name=user.name, ap_id=user.id, is_remote=True, email=None, password="******", description=user.summary, is_private=user.manuallyApprovesFollowers, public_key=user.publicKey['publicKeyPem']) #print(user) logging.debug(f"remote user: {user}") return user
def on_get(self, req, resp, id): person = UserProfile.get_or_none(id=id) if person: resp.body = json.dumps(person.to_json(), default=json_serial) resp.status = falcon.HTTP_200 else: resp.status = falcon.HTTP_404
def loadUserPass(username, password): candidate = UserProfile.get_or_none(username=username) if candidate != None: if Argon2().check_password_hash(candidate.password, password): return candidate else: return None
def on_get(self, req, resp, id): user = UserProfile.get_or_none(id=id) if user: followers = [follower.to_json() for follower in user.followers()] resp.body = json.dumps(followers, default=str) resp.status = falcon.HTTP_200 else: resp.status = falcon.HTTP_404
def on_get(self, req, resp, username): user = UserProfile.get_or_none(username=username) if user: followers = [follower.uris.id for follower in user.followers()] resp.body = json.dumps( activities.OrderedCollection(followers).to_json(), default=str) resp.status = falcon.HTTP_200 else: resp.status = falcon.HTTP_404
def on_get(self, req, resp, username): user = UserProfile.get_or_none(username == username) objects = user.photos.select().order_by(Status.created_at.desc()) collectionPage = activities.OrderedCollectionPage( map(activities.Note, objects)) collection = activities.OrderedCollection([collectionPage]) resp.body = json.dumps(collection.to_json(context=True)) resp.status = falcon.HTTP_200
async def handle_follow(activity): # Find if the target user is in our system followed = UserProfile.get_or_none(ap_id=activity.object) if followed: logging.debug(f"Starting follow process for {followed.username}") # Get the ap_id for the actor ap_id = "" if isinstance(activity.actor, activities.Actor): ap_id = activity.actor.id elif isinstance(activity.actor, str): ap_id = activity.actor # A representation of the remote user follower = ActivityPubId(ap_id).get_or_create_remote_user() logging.debug(f"New follower: {follower}") # Handle if the user must manually approve request if followed.is_private: FollowRequest.create( account = follower, target = followed ) else: # Handle local things #follower.follow(followed) #NotificationManager(follower).create_follow_notification(followed) message = { "@context": "https://www.w3.org/ns/activitystreams", "type": "Accept", "to": follower.uris.inbox, "actor": followed.ap_id, # this is wrong per litepub, but mastodon < 2.4 is not compliant with that profile. "object": { "type": "Follow", "id": followed.ap_id, "object": "https://{}/actor".format('pleroma.test'), "actor": follower.ap_id }, "id": "https://{}/activities/{}".format('anfora.test', uuid.uuid4()), } await push_to_remote_actor(follower, message , f'{BASE_URL}/actor#main-key') return True else: logging.error(f"User not found: {activity.object}") return False
def on_get(self, req, resp, id): user = UserProfile.get_or_none(id=id) if user: statuses = [ x.to_json() for x in user.statuses.order_by(Status.created_at.desc()) ] resp.body = json.dumps(statuses, default=str) resp.status = falcon.HTTP_200 else: resp.body = json.dumps({"Error: No such user"}) resp.status = falcon.HTTP_404
def on_get(self, req, resp, id): user = UserProfile.get_or_none(id=id) if user: if 'max_id' in req.params.keys(): feed = generate_feed(user, req.params['max_id']) else: feed = generate_feed(user) resp.status = falcon.HTTP_200 resp.body = feed resp.content_type = falcon.MEDIA_XML else: resp.status = falcon.HTTP_404
def on_post(self, req, resp, username): user = UserProfile.get_or_none(username == username) if req.context['user'].username != username: resp.status = falcon.HTTP_401 resp.body = json.dumps({"Error": "Access denied"}) payload = req.get_param('data') activity = json.loads(payload, object_hook=as_activitystream) if activity.object.type == "Note": obj = activity.object activity = activities.Create(to=user.uris.followers, actor=user.uris.id, object=obj) activity.validate() if activity.type == "Create": if activity.object.type != "Note": resp.status = falcon.HTTP_500 resp.body = json.dumps({"Error": "You only can create notes"}) activity.object.id = photo.uris.id activity.id = store(activity, user) #deliver(activity) resp.body = json.dumps({"Success": "Delivered successfully"}) resp.status = falcon.HTTP_200 #Convert to jpeg else: resp.status = falcon.HTTP_500 resp.body = json.dumps({"Error": "No photo attached"}) if activity.type == "Follow": followed = ActivityPubId( activity.object).get_or_create_remote_user() user = req.context["user"] #print(followed.ap_id, user.username, followed.username) f = FollowerRelation.create(user=user, follows=followed) activity.actor = user.uris.id activity.to = followed.uris.id #activity.id = store(activity, user) deliver(activity) resp.body = json.dumps({"Success": "Delivered successfully"}) resp.status = falcon.HTTP_200
def handle_follow(activity): followed = UserProfile.get_or_none(ap_id=activity.object) print("=> Handling follow") if followed: if isinstance(activity.actor, activities.Actor): ap_id = activity.actor.id elif isinstance(activity.actor, str): ap_id = activity.actor follower = ActivityPubId(ap_id).get_or_create_remote_user() FollowerRelation.create(user=follower, follows=followed) response = {"Type": "Accept", "Object": activity} else: print("error handling follow")
def handle_follow(activity): followed = UserProfile.get_or_none(ap_id=activity.object) print(activity.object) if followed: ap_id = "" if isinstance(activity.actor, activities.Actor): ap_id = activity.actor.id elif isinstance(activity.actor, str): ap_id = activity.actor follower = ActivityPubId(ap_id).get_or_create_remote_user() if followed.is_private: FollowRequest.create(account=follower, target=followed) else: follower.follow(followed, valid=True) t = Accept(object=activity, actor=followed.ap_id) data = LinkedDataSignature(t.to_json()) signed = data.sign(followed) headers = { 'date': f'{datetime.datetime.utcnow():%d-%b-%YT%H:%M:%SZ}', "(request-target)": follower.uris.inbox, "content-type": "application/activity+json", "host": DOMAIN, } signature = SignatureVerification(headers, method="POST", path=activity.actor + '/inbox').sign(followed) headers.update({'signature': signature}) logger.debug('Records: %s', headers) r = requests.post(follower.ap_id, data=signed, headers=headers) print(r.status_code) logger.debug('Records: %s', r.status_code + "\n" + r.json()) print("sent ", signed, signature) return True else: return False
def get_or_create_remote_user(self): """ Returns an instance of User after looking for it using it's ap_id """ user = UserProfile.get_or_none(ap_id=self.uri) if not user: user = self.dereference() hostname = urlparse(user.id).hostname username = "******".format(user.preferredUsername, hostname) user = UserProfile.create( username=user.preferredUsername, name=user.name, ap_id=user.id, remote=True, password="******", description=user.summary, private=user.manuallyApprovesFollowers, public_key=user.publicKey['publicKeyPem']) #print(user) return user
def handle_follow(activity, original=None): # Find if the target user is in our system followed = UserProfile.get_or_none(ap_id=activity.object) if followed: logging.debug(f"Starting follow process for {followed.username}") # Get the ap_id for the actor ap_id = "" if isinstance(activity.actor, activities.Actor): ap_id = activity.actor.id elif isinstance(activity.actor, str): ap_id = activity.actor # A representation of the remote user follower = ActivityPubId(ap_id).get_or_create_remote_user() logging.debug(f"New follower: {follower}") # Handle if the user must manually approve request if followed.is_private: FollowRequest.create(account=follower, target=followed) else: # Handle local things follower.follow(followed) NotificationManager(follower).create_follow_notification(followed) message = { "@context": "https://www.w3.org/ns/activitystreams", "type": "Accept", "to": follower.ap_id, "actor": followed.ap_id, "object": original, "id": followed.ap_id + '#accepts/follows/' + str(uuid.uuid4()), } response = push_to_remote_actor(follower, message) return response else: logging.error(f"User not found: {activity.object}") return False
def loadUser(payload): candidate = UserProfile.get_or_none(username=payload['user']['username']) return candidate
def user_from_uri(uri): username, domain = extract_user(uri) user = UserProfile.get_or_none(username=username) return user