Beispiel #1
0
        public override async Task <bool> Handle()
        {
            if (MainObject.Type != "https://www.w3.org/ns/activitystreams#Delete")
            {
                return(true);
            }

            var oldObject = await EntityStore.GetEntity(MainObject.Data["object"].Single().Id, true);

            var newData = oldObject.Data;

            foreach (var kv in newData)
            {
                if (!DeleteWhitelist.Contains(kv.Key))
                {
                    kv.Value.Clear();
                }
            }

            newData.Type.Clear();
            newData.Type.Add("https://www.w3.org/ns/activitystreams#Tombstone");
            newData.Replace("deleted", ASTerm.MakePrimitive(DateTime.Now.ToString("o")));

            var newObject = APEntity.From(newData);
            await EntityStore.StoreEntity(newObject);

            return(true);
        }
        private async Task <ASObject> _buildPage(APEntity entity, int from_id, int to_id)
        {
            var collection = entity.Data;
            var maxitem    = (await _collectionTools.GetItems(entity.Id, count: 1)).FirstOrDefault()?.CollectionItemId;
            var items      = await _collectionTools.GetItems(entity.Id, from_id, to_id, 11);

            var hasItems = items.Any();
            var page     = new ASObject();

            page.Type.Add("https://www.w3.org/ns/activitystreams#OrderedCollectionPage");
            page["summary"].Add(ASTerm.MakePrimitive("A collection"));
            page.Id = entity.Id + "?from_id=" + (hasItems ? from_id : 0);
            page["partOf"].Add(ASTerm.MakeId(entity.Id));
            if (collection["attributedTo"].Any())
            {
                page["attributedTo"].Add(collection["attributedTo"].First());
            }
            if (items.Count > 0 && items[0].CollectionItemId != maxitem)
            {
                page["prev"].Add(ASTerm.MakeId(entity.Id + "?to_id=" + items[0].CollectionItemId.ToString()));
            }
            if (items.Count > 10)
            {
                page["next"].Add(ASTerm.MakeId(entity.Id + "?from_id=" + (items[9].CollectionItemId - 1).ToString()));
            }
            page["orderedItems"].AddRange(items.Take(10).Select(a => ASTerm.MakeId(a.Entity.Id)));
            return(page);
        }
Beispiel #3
0
        public override async Task <bool> Handle()
        {
            if (MainObject.Type != "https://www.w3.org/ns/activitystreams#Create")
            {
                return(true);
            }

            var activityData = MainObject.Data;
            var objectEntity = await EntityStore.GetEntity(activityData["object"].First().Id, false);

            if (!_entityData.IsActor(objectEntity.Data))
            {
                return(true);
            }
            var objectData = objectEntity.Data;
            var id         = objectEntity.Id;

            await AddCollection(objectData, "inbox", id);
            await AddCollection(objectData, "outbox", id);
            await AddCollection(objectData, "following", id);
            await AddCollection(objectData, "followers", id);
            await AddCollection(objectData, "liked", id);

            var blocks = await AddCollection(objectData, "blocks", id);

            var blocked = await _collection.NewCollection(EntityStore, null, "blocked", blocks.Id);

            var blocksData = blocks.Data;

            blocksData["blocked"].Add(ASTerm.MakeId(blocked.Id));
            blocks.Data = blocksData;

            if (!objectData["manuallyApprovesFollowers"].Any())
            {
                objectData.Replace("manuallyApprovesFollowers", ASTerm.MakePrimitive(false));
            }

            objectEntity.Data = objectData;

            await EntityStore.StoreEntity(blocked);

            await EntityStore.StoreEntity(blocks);

            await EntityStore.StoreEntity(objectEntity);

            var userId = UserOverride ?? User.FindFirst(ClaimTypes.NameIdentifier).Value;

            if (!activityData["actor"].Any())
            {
                activityData["actor"].Add(ASTerm.MakeId(objectEntity.Id));
            }

            MainObject.Data = activityData;
            await EntityStore.StoreEntity(MainObject);

            await _connection.ExecuteAsync("insert into \"UserActorPermissions\" (\"UserId\", \"ActorId\", \"IsAdmin\") values (@UserId, @ActorId, TRUE)", new { UserId = userId, ActorId = objectEntity.DbId });

            return(true);
        }
Beispiel #4
0
        public async Task <IActionResult> UploadMedia()
        {
            var @object = Request.Form["object"];
            var file    = Request.Form.Files["file"];

            var handler = ActivatorUtilities.CreateInstance <GetEntityMiddleware.GetEntityHandler>(_provider, User);
            var obj     = ASObject.Parse(@object);
            var mainObj = obj;

            if (obj["object"].Any())
            {
                mainObj = obj["object"].Single().SubObject;
            }

            var uploadPath = _configuration.GetSection("Kroeg")["FileUploadPath"];
            var uploadUri  = _configuration.GetSection("Kroeg")["FileUploadUrl"];

            var extension = file.FileName.Split('.').Last().Replace('/', '_');

            var fileName = Guid.NewGuid().ToString() + "." + extension;

            var str = System.IO.File.OpenWrite(uploadPath + fileName);
            await file.CopyToAsync(str);

            str.Dispose();

            mainObj.Replace("url", ASTerm.MakePrimitive(uploadUri + fileName));

            var entity = await _entityStore.GetEntity((string)HttpContext.Items["fullPath"], false);

            try
            {
                using (var transaction = _connection.BeginTransaction())
                {
                    var entOut = await handler.Post(HttpContext, (string)HttpContext.Items["fullPath"], entity, obj);

                    if (entOut == null)
                    {
                        return(NotFound());
                    }
                    obj = await _flattener.Unflatten(_entityStore, entOut);

                    transaction.Commit();
                    return(Content(obj.Serialize().ToString(), "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""));
                }
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e);
                return(StatusCode(403, e));
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine(e);
                return(StatusCode(401, e));
            }
        }
Beispiel #5
0
        private async Task <ASObject> _getCollection(APEntity entity, IQueryCollection arguments)
        {
            var  from_id    = arguments["from_id"].FirstOrDefault();
            var  to_id      = arguments["to_id"].FirstOrDefault();
            var  collection = entity.Data;
            bool seePrivate = collection["attributedTo"].Any() && _user.FindFirstValue("actor") == collection["attributedTo"].First().Id;

            if (from_id != null || to_id != null)
            {
                var fromId = from_id != null?int.Parse(from_id) : int.MaxValue;

                var toId = to_id != null?int.Parse(to_id) : int.MinValue;

                var maxitem = (await _collectionTools.GetItems(entity.Id, count: 1)).FirstOrDefault()?.CollectionItemId;
                var items   = await _collectionTools.GetItems(entity.Id, fromId, toId, count : 11);

                var hasItems = items.Any();
                var page     = new ASObject();
                page.Type.Add("https://www.w3.org/ns/activitystreams#OrderedCollectionPage");
                page["summary"].Add(ASTerm.MakePrimitive("A collection"));
                page.Id = entity.Id + "?from_id=" + (hasItems ? fromId : 0);
                page["partOf"].Add(ASTerm.MakeId(entity.Id));
                if (collection["attributedTo"].Any())
                {
                    page["attributedTo"].Add(collection["attributedTo"].First());
                }
                if (items.Count > 0 && items[0].CollectionItemId != maxitem)
                {
                    page["prev"].Add(ASTerm.MakeId(entity.Id + "?to_id=" + items[0].CollectionItemId.ToString()));
                }
                if (items.Count > 10)
                {
                    page["next"].Add(ASTerm.MakeId(entity.Id + "?from_id=" + (items[9].CollectionItemId - 1).ToString()));
                }
                page["orderedItems"].AddRange(items.Take(10).Select(a => ASTerm.MakeId(a.Entity.Id)));

                return(page);
            }
            else
            {
                var items = await _collectionTools.GetItems(entity.Id, count : 1);

                var hasItems = items.Any();
                var page     = entity.Id + "?from_id=" + (hasItems ? items.First().CollectionItemId + 1 : 0);
                collection["current"].Add(ASTerm.MakeId(entity.Id));
                collection["totalItems"].Add(ASTerm.MakePrimitive(await _collectionTools.Count(entity.Id), ASTerm.NON_NEGATIVE_INTEGER));
                collection["first"].Add(ASTerm.MakeId(page));
                return(collection);
            }
        }
        private async Task <ASObject> _buildCollection(APEntity entity)
        {
            var collection = entity.Data;

            collection["current"].Add(ASTerm.MakeId(entity.Id));
            collection["totalItems"].Add(ASTerm.MakePrimitive(await _collectionTools.Count(entity.Id), ASTerm.NON_NEGATIVE_INTEGER));
            var item = await _collectionTools.GetItems(entity.Id, count : 1);

            if (item.Any())
            {
                collection["first"].Add(ASTerm.MakeId(entity.Id + $"?from_id={item.First().CollectionItemId + 1}"));
            }
            else
            {
                collection["first"].Add(ASTerm.MakeId(entity.Id + $"?from_id=0"));
            }
            return(collection);
        }
Beispiel #7
0
        public async Task <ASObject> BuildFakeObject(APEntity entity, string fragment)
        {
            if (!EntityData.IsActor(entity.Data))
            {
                return(null);
            }

            if (fragment == "key")
            {
                var key = await _keyService.GetKey(entity.Id);

                var salm    = new MagicKey(key.PrivateKey);
                var pemData = salm.AsPEM;

                var keyObj = new ASObject();
                keyObj.Replace("owner", ASTerm.MakeId(entity.Id));
                keyObj.Replace("publicKeyPem", ASTerm.MakePrimitive(pemData));
                keyObj.Id = $"{entity.Id}#key";
                return(keyObj);
            }
            else if (fragment == "endpoints")
            {
                var data = entity.Data;
                var idu  = new Uri(entity.Id);

                var basePath = $"{idu.Scheme}://{idu.Host}{(idu.IsDefaultPort?"":$":{idu.Port}")}{_configuration.BasePath}";

                var endpoints = new ASObject();
                endpoints.Replace("oauthAuthorizationEndpoint", ASTerm.MakeId(basePath + "oauth/authorize?id=" + Uri.EscapeDataString(entity.Id)));
                endpoints.Replace("oauthTokenEndpoint", ASTerm.MakeId(basePath + "oauth/token?"));
                endpoints.Replace("settingsEndpoint", ASTerm.MakeId(basePath + "settings/auth"));
                endpoints.Replace("uploadMedia", data["outbox"].Single());
                endpoints.Replace("relevantObjects", ASTerm.MakeId(basePath + "settings/relevant"));
                endpoints.Replace("proxyUrl", ASTerm.MakeId(basePath + "auth/proxy"));
                endpoints.Replace("jwks", ASTerm.MakeId(basePath + "auth/jwks?id=" + Uri.EscapeDataString(entity.Id)));
                endpoints.Replace("sharedInbox", ASTerm.MakeId(basePath + "auth/sharedInbox"));
                endpoints.Replace("search", ASTerm.MakeId(basePath + "auth/search"));
                endpoints.Id = entity.Id + "#endpoints";
                return(endpoints);
            }

            return(null);
        }
Beispiel #8
0
        public async Task <IActionResult> MakeNewActor(NewActorModel model)
        {
            var data = await _getUserInfo();

            if (string.IsNullOrWhiteSpace(model.Username))
            {
                return(View("NewActor", model));
            }
            var user = model.Username;

            var obj = new ASObject();

            obj.Type.Add("https://www.w3.org/ns/activitystreams#Person");
            obj["preferredUsername"].Add(ASTerm.MakePrimitive(user));
            obj["name"].Add(ASTerm.MakePrimitive(string.IsNullOrWhiteSpace(model.Name) ? "Unnamed" : model.Name));
            if (!string.IsNullOrWhiteSpace(model.Summary))
            {
                obj["summary"].Add(ASTerm.MakePrimitive(model.Summary));
            }

            var create = new ASObject();

            create.Type.Add("https://www.w3.org/ns/activitystreams#Create");
            create["object"].Add(ASTerm.MakeSubObject(obj));
            create["to"].Add(ASTerm.MakeId("https://www.w3.org/ns/activitystreams#Public"));

            var stagingStore = new StagingEntityStore(_entityStore);
            var apo          = await _flattener.FlattenAndStore(stagingStore, create);

            var handler = new CreateActorHandler(stagingStore, apo, null, null, User, _collectionTools, _entityData, _connection);
            await handler.Handle();

            var resultUser = await _entityStore.GetEntity(handler.MainObject.Data["object"].First().Id, false);

            var outbox = await _entityStore.GetEntity(resultUser.Data["outbox"].First().Id, false);

            var delivery = new DeliveryHandler(stagingStore, handler.MainObject, resultUser, outbox, User, _collectionTools, _provider.GetRequiredService <DeliveryService>());
            await delivery.Handle();

            return(RedirectToAction("Edit", new { id = resultUser.Id }));
        }
Beispiel #9
0
        public override async Task <bool> Handle()
        {
            if (MainObject.Type != "https://www.w3.org/ns/activitystreams#Update" && MainObject.Type != "https://www.w3.org/ns/activitystreams#Delete")
            {
                return(true);
            }

            var activityData = MainObject.Data;

            var oldObject =
                await EntityStore.Bypass.GetEntity(activityData["object"].Single().Id, false);

            if (oldObject == null)
            {
                throw new InvalidOperationException("Cannot remove or update a non-existant object!");
            }

            if (!oldObject.IsOwner)
            {
                throw new InvalidOperationException("Cannot remove or update an object not on this server!");
            }

            var originatingCreate = (await _relevantEntities.FindRelevantObject("https://www.w3.org/ns/activitystreams#Create", oldObject.Id)).FirstOrDefault();

            if (originatingCreate.Data["actor"].Single().Id != Actor.Id)
            {
                throw new InvalidOperationException("Cannot remove or update objects that weren't made by you!");
            }

            if (MainObject.Type == "https://www.w3.org/ns/activitystreams#Update")
            {
                var newObject = await EntityStore.GetEntity(activityData["object"].Single().Id, false);

                if (newObject == oldObject)
                {
                    throw new InvalidOperationException("No new object passed!");
                }

                var data = oldObject.Data;
                foreach (var item in newObject.Data)
                {
                    // SequenceEqual ensures that clients doing full-object updates won't cause this exception on e.g. type, attributedTo, etc
                    if (UpdateBlacklist.Contains(item.Key) && (data[item.Key].Count != item.Value.Count || data[item.Key].Zip(item.Value, _isEqual).Any(a => !a)))
                    {
                        throw new InvalidOperationException($"Cannot update key {item.Key} as it's on the blacklist!");
                    }

                    data[item.Key].Clear();
                    data[item.Key].AddRange(item.Value);
                }

                data.Replace("updated", ASTerm.MakePrimitive(DateTime.Now.ToString("o")));

                newObject.Data = data;
                newObject.Type = oldObject.Type;
                await EntityStore.StoreEntity(newObject);
            }
            else
            {
                var newData = oldObject.Data;
                foreach (var kv in newData)
                {
                    if (!DeleteWhitelist.Contains(kv.Key))
                    {
                        kv.Value.Clear();
                    }
                }

                newData.Type.Clear();
                newData.Type.Add("https://www.w3.org/ns/activitystreams#Tombstone");
                newData.Replace("deleted", ASTerm.MakePrimitive(DateTime.Now.ToString("o")));

                var newObject = APEntity.From(newData, true);
                await EntityStore.StoreEntity(newObject);
            }

            return(true);
        }
Beispiel #10
0
        private ASObject _parseAuthor(XElement element)
        {
            var ao = new ASObject();

            ao.Type.Add("https://www.w3.org/ns/activitystreams#Person");

            // set preferredUsername and name
            {
                var atomName              = element.Element(Atom + "name")?.Value;
                var pocoDisplayName       = element.Element(PortableContacts + "displayName")?.Value;
                var pocoPreferredUsername = element.Element(PortableContacts + "preferredUsername")?.Value;

                ao.Replace("preferredUsername", ASTerm.MakePrimitive(pocoPreferredUsername ?? atomName));
                ao.Replace("name", ASTerm.MakePrimitive(pocoDisplayName ?? pocoPreferredUsername ?? atomName));
            }

            // set summary
            {
                var atomSummary = element.Element(Atom + "summary")?.Value;
                var pocoNote    = element.Element(PortableContacts + "note")?.Value;

                ao.Replace("summary", ASTerm.MakePrimitive(pocoNote ?? atomSummary));
            }

            string retrievalUrl = null;

            {
                foreach (var link in element.Elements(Atom + "link"))
                {
                    var rel  = link.Attribute(NoNamespace + "rel")?.Value;
                    var type = link.Attribute(NoNamespace + "type")?.Value;
                    var href = link.Attribute(NoNamespace + "href")?.Value;

                    switch (rel)
                    {
                    case "avatar":
                        var avatarObject = new ASObject();
                        avatarObject.Type.Add("https://www.w3.org/ns/activitystreams#Image");
                        avatarObject.Replace("mediaType", ASTerm.MakePrimitive(type));
                        var width  = link.Attribute(AtomMedia + "width")?.Value;
                        var height = link.Attribute(AtomMedia + "height")?.Value;

                        if (width != null && height != null)
                        {
                            avatarObject.Replace("width", ASTerm.MakePrimitive(int.Parse(width)));
                            avatarObject.Replace("height", ASTerm.MakePrimitive(int.Parse(height)));
                        }

                        avatarObject.Replace("url", ASTerm.MakePrimitive(href));

                        ao["icon"].Add(ASTerm.MakeSubObject(avatarObject));
                        break;

                    case "alternate":
                        if (type == "text/html")
                        {
                            if (retrievalUrl == null)
                            {
                                retrievalUrl = href;
                            }

                            ao["atomUri"].Add(ASTerm.MakePrimitive(href));
                        }
                        break;

                    case "self":
                        if (type == "application/atom+xml")
                        {
                            retrievalUrl = href;
                        }
                        break;
                    }
                }
            }

            // should be Mastodon *and* GNU social compatible: Mastodon uses uri as id

            if (element.Element(Atom + "id") != null)
            {
                ao.Id = element.Element(Atom + "id")?.Value;
            }
            else
            {
                ao.Id = element.Element(Atom + "uri")?.Value;
            }

            if (element.Element(Atom + "uri") != null)
            {
                ao["url"].Add(ASTerm.MakePrimitive(element.Element(Atom + "uri")?.Value));
            }

            if (element.Element(Atom + "email") != null)
            {
                ao["email"].Add(ASTerm.MakePrimitive(element.Element(Atom + "email")?.Value));
            }

            foreach (var url in element.Elements(PortableContacts + "urls"))
            {
                ao["url"].Add(ASTerm.MakePrimitive(url.Element(PortableContacts + "value")?.Value));
            }

            if (retrievalUrl != null)
            {
                ao.Replace("atomUri", ASTerm.MakePrimitive(retrievalUrl));
            }

            return(ao);
        }
Beispiel #11
0
        private async Task <ASObject> _parseFeed(XElement element, string targetUser)
        {
            var ao = new ASObject();

            ao.Type.Add("https://www.w3.org/ns/activitystreams#OrderedCollectionPage");
            ao.Replace("_:origin", ASTerm.MakePrimitive("atom"));
            ao.Id = element.Element(Atom + "id").Value;

            if (element.Element(Atom + "title") != null)
            {
                ao.Replace("summary", ASTerm.MakePrimitive(element.Element(Atom + "title").Value));
            }
            if (element.Element(Atom + "updated") != null)
            {
                ao.Replace("updated", ASTerm.MakePrimitive(element.Element(Atom + "updated").Value));
            }

            var author = _parseAuthor(element.Element(Atom + "author"));

            ao.Replace("attributedTo", ASTerm.MakeSubObject(author));

            var authorId = author.Id;

            foreach (var entry in element.Elements(Atom + "entry"))
            {
                ao["orderedItems"].Add(await _parseActivity(entry, authorId, targetUser));
            }


            foreach (var link in element.Elements(Atom + "link"))
            {
                var rel  = link.Attribute(NoNamespace + "rel").Value;
                var type = link.Attribute(NoNamespace + "type")?.Value;
                var href = link.Attribute(NoNamespace + "href").Value;

                if (rel == "alternate" && type == "text/html")
                {
                    ao["url"].Add(ASTerm.MakePrimitive(href));
                }
                else if (rel == "self" && type == "application/atom+xml")
                {
                    author.Replace("atomUri", ASTerm.MakePrimitive(href));
                }
                else
                {
                    switch (rel)
                    {
                    case "salmon":
                        ao["_:salmonUrl"].Add(ASTerm.MakePrimitive(href));
                        break;

                    case "hub":
                        ao["_:hubUrl"].Add(ASTerm.MakePrimitive(href));
                        break;

                    case "prev":
                        ao["prev"].Add(ASTerm.MakeId(href));
                        break;

                    case "next":
                        ao["next"].Add(ASTerm.MakeId(href));
                        break;
                    }
                }
            }

            author["_:salmonUrl"].AddRange(ao["_:salmonUrl"]);
            author["_:hubUrl"].AddRange(ao["_:hubUrl"]);

            return(ao);
        }
Beispiel #12
0
        private async Task <ASTerm> _parseActivity(XElement element, string authorId, string targetUser)
        {
            if (await _isSelf(element.Element(Atom + "id").Value))
            {
                return(ASTerm.MakeId(await _fixActivityToObjectId(element.Element(Atom + "id").Value)));
            }

            var ao = new ASObject();

            ao.Id = element.Element(Atom + "id").Value;
            ao.Replace("_:origin", ASTerm.MakePrimitive("atom"));

            var verb         = _objectTypeToType(element.Element(ActivityStreams + "verb")?.Value) ?? "Post";
            var originalVerb = verb;

            if (verb == "Unfollow" && (await _entityStore.GetEntity(element.Element(Atom + "id").Value, false))?.Type == "Follow") // egh egh egh, why, mastodon
            {
                ao.Id += "#unfollow";
            }

            if (verb == "Unfavorite")
            {
                verb = "Undo";
            }
            if (verb == "Unfollow")
            {
                verb = "Undo";
            }
            if (verb == "Request-friend")
            {
                return(null);
            }

            if (verb == "Post")
            {
                verb = "Create";
            }
            else if (verb == "Share")
            {
                verb = "Announce";
            }
            else if (verb == "Favorite")
            {
                verb = "Like";
            }


#pragma warning disable 618
            if (!_entityConfiguration.IsActivity(verb))
            {
                return(null);
            }
#pragma warning restore 618

            ao.Type.Add("https://www.w3.org/ns/activitystreams#" + verb);

            if (element.Element(Atom + "title") != null)
            {
                ao.Replace("summary", ASTerm.MakePrimitive(element.Element(Atom + "title").Value));
            }
            if (element.Element(Atom + "published") != null)
            {
                ao.Replace("published", ASTerm.MakePrimitive(element.Element(Atom + "published").Value));
            }
            if (element.Element(Atom + "updated") != null)
            {
                ao.Replace("updated", ASTerm.MakePrimitive(element.Element(Atom + "updated").Value));
            }

            if (element.Element(Atom + "author") != null)
            {
                var newAuthor = _parseAuthor(element.Element(Atom + "author"));
                authorId = newAuthor.Id;
            }

            if (authorId != null)
            {
                ao.Replace("actor", ASTerm.MakeId(authorId));
            }


            string retrievalUrl = null;

            foreach (var link in element.Elements(Atom + "link"))
            {
                var rel  = link.Attribute(NoNamespace + "rel").Value;
                var type = link.Attribute(NoNamespace + "type")?.Value;
                var href = link.Attribute(NoNamespace + "href").Value;

                if (rel == "self" && type == "application/atom+xml")
                {
                    retrievalUrl = href;
                }
                else if (rel == "alternate" && type == "text/html")
                {
                    ao["url"].Add(ASTerm.MakePrimitive(href));

                    if (retrievalUrl == null)
                    {
                        retrievalUrl = href;
                    }
                }
                else if (rel == "mentioned")
                {
                    if (href == "http://activityschema.org/collection/public")
                    {
                        href = "https://www.w3.org/ns/activitystreams#Public";
                    }

                    ao["to"].Add(ASTerm.MakeId(href));
                }
            }

            if (targetUser != null)
            {
                ao["cc"].Add(ASTerm.MakeId(targetUser));
            }

            if (retrievalUrl != null)
            {
                ao.Replace("atomUri", ASTerm.MakePrimitive(retrievalUrl));
            }

            if (element.Element(ActivityStreams + "object") != null)
            {
                var parsedActivityObject = await _parseActivityObject(element.Element(ActivityStreams + "object"), authorId, targetUser);

                if (verb == "Undo" && originalVerb == "Unfavorite")
                {
                    parsedActivityObject = ASTerm.MakeId((await _relevantEntities.FindRelevantObject(authorId, "https://www.w3.org/ns/activitystreams#Like", _getId(parsedActivityObject))).FirstOrDefault()?.Id);
                }
                else if (verb == "Undo" && originalVerb == "Unfollow")
                {
                    parsedActivityObject = ASTerm.MakeId((await _relevantEntities.FindRelevantObject(authorId, "https://www.w3.org/ns/activitystreams#Follow", _getId(parsedActivityObject))).FirstOrDefault()?.Id);
                }

                ao.Replace("object", parsedActivityObject);
            }
            else if (element.Element(ActivityStreams + "object-type") == null && originalVerb == "Unfollow")
            {
                // you thought Mastodon was bad?
                // GNU Social doesn't send an object in an unfollow.

                // .. what

                ao.Replace("object", ASTerm.MakeId((await _relevantEntities.FindRelevantObject(authorId, "https://www.w3.org/ns/activitystreams#Follow", targetUser)).FirstOrDefault()?.Id));
            }
            else
            {
                ao.Replace("object", await _parseActivityObject(element, authorId, targetUser, true));
            }

            return(ASTerm.MakeSubObject(ao));
        }
Beispiel #13
0
        private async Task <ASTerm> _parseActivityObject(XElement element, string authorId, string targetUser, bool isActivity = false)
        {
            if (!isActivity && element.Element(ActivityStreams + "verb") != null)
            {
                return(await _parseActivity(element, authorId, targetUser));
            }
            var entity = await _entityStore.GetEntity(element.Element(Atom + "id")?.Value, true);

            if (entity != null)
            {
                if (entity.Type.Contains("https://www.w3.org/ns/activitystreams#Create"))
                {
                    return(ASTerm.MakeId(entity.Data["object"].First().Id));
                }

                return(ASTerm.MakeId(element.Element(Atom + "id")?.Value));
            }

            var ao = new ASObject();

            ao.Id = element.Element(Atom + "id")?.Value + (isActivity ? "#object" : "");
            ao.Replace("kroeg:origin", ASTerm.MakePrimitive("atom"));

            var objectType = _objectTypeToType(element.Element(ActivityStreams + "object-type")?.Value);

            if (objectType == "https://www.w3.org/ns/activitystreams#Person")
            {
                return(ASTerm.MakeSubObject(_parseAuthor(element)));
            }

            ao.Type.Add(objectType);
            ao.Replace("attributedTo", ASTerm.MakeId(authorId));


            if (element.Element(Atom + "summary") != null)
            {
                ao.Replace("summary", ASTerm.MakePrimitive(element.Element(Atom + "summary")?.Value));
            }
            if (element.Element(Atom + "published") != null)
            {
                ao.Replace("published", ASTerm.MakePrimitive(element.Element(Atom + "published")?.Value));
            }
            if (element.Element(Atom + "updated") != null)
            {
                ao.Replace("updated", ASTerm.MakePrimitive(element.Element(Atom + "updated")?.Value));
            }

            ao.Replace("content", ASTerm.MakePrimitive(element.Element(Atom + "content")?.Value));
            var mediaType = element.Element(Atom + "content")?.Attribute(NoNamespace + "type")?.Value;

            if (mediaType != null)
            {
                if (mediaType == "text")
                {
                    mediaType = "text/plain";
                }
                if (mediaType.Contains("/"))
                {
                    ao.Replace("mediaType", ASTerm.MakePrimitive(mediaType));
                }
            }

            if (element.Element(OStatus + "conversation") != null)
            {
                ao.Replace("conversation", ASTerm.MakePrimitive(element.Element(OStatus + "conversation").Attribute(NoNamespace + "ref")?.Value ?? element.Element(OStatus + "conversation").Value));
            }

            if (element.Element(AtomThreading + "in-reply-to") != null)
            {
                var elm  = element.Element(AtomThreading + "in-reply-to");
                var @ref = await _findInReplyTo(elm.Attribute(NoNamespace + "ref").Value);

                var hrel = elm.Attribute(NoNamespace + "href")?.Value;

                if (hrel == null)
                {
                    ao.Replace("inReplyTo", ASTerm.MakeId(@ref));
                }
                else if (await _entityStore.GetEntity(@ref, false) != null)
                {
                    ao.Replace("inReplyTo", ASTerm.MakeId(@ref));
                }
                else
                {
                    var lazyLoad = new ASObject();
                    lazyLoad.Id = @ref;
                    lazyLoad.Type.Add("_:LazyLoad");
                    lazyLoad.Replace("href", ASTerm.MakePrimitive(hrel));
                    ao.Replace("inReplyTo", ASTerm.MakeSubObject(lazyLoad));
                }
            }

            foreach (var tag in element.Elements(Atom + "category"))
            {
                var val = tag.Attribute(NoNamespace + "term").Value;

                var tagao = new ASObject();
                tagao.Id = $"{_entityConfiguration.BaseUri}/tag/{val}";
                tagao["name"].Add(ASTerm.MakePrimitive("#" + val));
                tagao.Type.Add("Hashtag");

                ao["tag"].Add(ASTerm.MakeSubObject(tagao));
            }

            string retrievalUrl = null;

            foreach (var link in element.Elements(Atom + "link"))
            {
                var rel  = link.Attribute(NoNamespace + "rel").Value;
                var type = link.Attribute(NoNamespace + "type")?.Value;
                var href = link.Attribute(NoNamespace + "href").Value;

                if (rel == "self" && type == "application/atom+xml")
                {
                    retrievalUrl = href;
                }
                else if (rel == "alternate" && type == "text/html")
                {
                    ao["url"].Add(ASTerm.MakePrimitive(href));

                    if (retrievalUrl == null)
                    {
                        retrievalUrl = href;
                    }
                }
                else if (rel == "mentioned")
                {
                    if (href == "http://activityschema.org/collection/public")
                    {
                        href = "https://www.w3.org/ns/activitystreams#Public";
                    }

                    ao["to"].Add(ASTerm.MakeId(href));
                }
                else if (rel == "enclosure")
                {
                    // image
                    var subAo = new ASObject();
                    subAo["url"].Add(ASTerm.MakePrimitive(href));
                    subAo["mediaType"].Add(ASTerm.MakePrimitive(type));

                    switch (type.Split('/')[0])
                    {
                    case "image":
                        subAo.Type.Add("https://www.w3.org/ns/activitystreams#Image");
                        break;

                    case "video":
                        subAo.Type.Add("https://www.w3.org/ns/activitystreams#Video");
                        break;

                    default:
                        continue;
                    }

                    if (link.Attribute(NoNamespace + "length") != null)
                    {
                        subAo["fileSize"].Add(ASTerm.MakePrimitive(int.Parse(link.Attribute(NoNamespace + "length").Value)));
                    }

                    ao["attachment"].Add(ASTerm.MakeSubObject(subAo));
                }
            }

            return(ASTerm.MakeSubObject(ao));
        }
Beispiel #14
0
        public async Task <IActionResult> DoRegister(RegisterViewModel model)
        {
            if (!_configuration.GetSection("Kroeg").GetValue <bool>("CanRegister"))
            {
                return(NotFound());
            }
            var apuser = new APUser
            {
                Username = model.Username,
                Email    = model.Email
            };

            if ((await _relevantEntities.FindEntitiesWithPreferredUsername(model.Username)).Count > 0)
            {
                ModelState.AddModelError("", "Username is already in use!");
            }

            if (model.Password != model.VerifyPassword)
            {
                ModelState.AddModelError("", "Passwords don't match!");
            }

            if (!ModelState.IsValid)
            {
                return(View("Register", model));
            }

            await _connection.OpenAsync();

            using (var trans = _connection.BeginTransaction())
            {
                var result = await _userManager.CreateAsync(apuser, model.Password);

                if (!result.Succeeded)
                {
                    ModelState.AddModelError("", result.Errors.First().Description);
                }

                if (!ModelState.IsValid)
                {
                    return(View("Register", model));
                }

                if (await _connection.ExecuteAsync("select count(*) from \"Users\"") == 1)
                {
//                    await _userManager.AddClaimAsync(apuser, new Claim("admin", "true"));
                }

                await _signInManager.SignInAsync(apuser, false);

                var user = model.Username;

                var obj = new ASObject();
                obj.Type.Add("https://www.w3.org/ns/activitystreams#Person");
                obj["preferredUsername"].Add(ASTerm.MakePrimitive(user));
                obj["name"].Add(ASTerm.MakePrimitive(user));

                var create = new ASObject();
                create.Type.Add("https://www.w3.org/ns/activitystreams#Create");
                create["object"].Add(ASTerm.MakeSubObject(obj));
                create["to"].Add(ASTerm.MakeId("https://www.w3.org/ns/activitystreams#Public"));

                Console.WriteLine($"--- creating actor. Unflattened:\n{create.Serialize().ToString(Formatting.Indented)}");
                var apo = await _entityFlattener.FlattenAndStore(_entityStore, create);

                Console.WriteLine($"Flat: {apo.Data.Serialize().ToString(Formatting.Indented)}\n----");
                var handler = new CreateActorHandler(_entityStore, apo, null, null, User, _collectionTools, _entityConfiguration, _connection);
                handler.UserOverride = apuser.Id;
                await handler.Handle();

                var resultUser = await _entityStore.GetEntity(handler.MainObject.Data["object"].First().Id, false);

                var outbox = await _entityStore.GetEntity(resultUser.Data["outbox"].First().Id, false);

                var delivery = new DeliveryHandler(_entityStore, handler.MainObject, resultUser, outbox, User, _collectionTools, _provider.GetRequiredService <DeliveryService>());
                await delivery.Handle();

                trans.Commit();
                return(RedirectToActionPermanent("Index", "Settings"));
            }
        }