Beispiel #1
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", new ASTerm(uploadUri + fileName));

            if (obj["type"].Any(a => (string)a.Primitive == "Create"))
            {
                try
                {
                    obj = await handler.Post(HttpContext, (string)HttpContext.Items["fullPath"], obj);
                }
                catch (UnauthorizedAccessException e)
                {
                    return(StatusCode(403, e));
                }
                catch (InvalidOperationException e)
                {
                    return(StatusCode(401, e));
                }

                if (obj == null)
                {
                    return(NotFound());
                }
            }
            else
            {
                obj["id"].Clear();
                obj.Replace("attributedTo", new ASTerm(User.FindFirstValue(JwtTokenSettings.ActorClaim)));
                obj = (await _flattener.FlattenAndStore(_entityStore, obj)).Data;
                await _entityStore.CommitChanges();
            }

            obj = await _flattener.Unflatten(_entityStore, APEntity.From(obj, true));

            return(Content(obj.Serialize().ToString(), "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""));
        }
Beispiel #2
0
        public async Task Do(string[] args)
        {
            foreach (var loadUrl in args)
            {
                var htc = new HttpClient();
                htc.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", application/activity+json, application/json, application/atom+xml, text/html");

                var response = await htc.GetAsync(loadUrl);

                if (!response.IsSuccessStatusCode)
                {
                    response = await htc.GetAsync(loadUrl + ".atom"); // hack!

                    if (!response.IsSuccessStatusCode)
                    {
                        continue;
                    }
                }

                var converter = new AS2ConverterFactory();

                var data = await converter.Build(_provider, null).Parse(await response.Content.ReadAsStreamAsync());

                var result = await _entityFlattener.FlattenAndStore(_entityStore, data, false);

                Console.WriteLine($"{result.Id} stored");
            }
        }
Beispiel #3
0
        public async Task <IActionResult> SharedInbox()
        {
            var userId = await _verifier.Verify(Request.Scheme + "://" + Request.Host.ToUriComponent() + Request.Path, HttpContext);

            if (userId == null)
            {
                return(Unauthorized());
            }
            var reader = new StreamReader(Request.Body);
            var data   = ASObject.Parse(await reader.ReadToEndAsync());

            if (!_entityConfiguration.IsActivity(data))
            {
                return(StatusCode(403, "Not an activity?"));
            }
            if (!data["actor"].Any((a) => (string)a.Primitive == userId))
            {
                return(StatusCode(403, "Invalid signature!"));
            }

            var temporaryStore = new StagingEntityStore(_entityStore);
            var resultEntity   = await _entityFlattener.FlattenAndStore(temporaryStore, data, false);

            temporaryStore.TrimDown((new Uri(new Uri(userId), "/")).ToString());
            await temporaryStore.CommitChanges(); // shouuuuld be safe

            var users = await _deliveryService.GetUsersForSharedInbox(data);

            foreach (var user in users)
            {
                if (user.IsOwner)
                {
                    _context.EventQueue.Add(DeliverToActivityPubTask.Make(new DeliverToActivityPubData {
                        ObjectId = resultEntity.Id, TargetInbox = (string)user.Data["inbox"].First().Primitive
                    }));
                }
            }

            await _context.SaveChangesAsync();

            return(StatusCode(202));
        }
Beispiel #4
0
        public async Task <APEntity> ServerToServer(APEntity inbox, ASObject activity, string subject = null)
        {
            var stagingStore = new StagingEntityStore(_mainStore);
            var userId       = inbox.Data["attributedTo"].Single().Id;
            var user         = await _mainStore.GetEntity(userId, false);

            APEntity flattened;

            string prefix = "";

            if (subject != null)
            {
                var subjectUri = new Uri(subject);
                prefix = $"{subjectUri.Scheme}://{subjectUri.Host}";
                if (!subjectUri.IsDefaultPort)
                {
                    prefix += $":{subjectUri.Port}";
                }
                prefix += "/";
            }

            var id = activity.Id;

            flattened = await _mainStore.GetEntity(id, false);

            if (flattened == null)
            {
                flattened = await _flattener.FlattenAndStore(stagingStore, activity, false);
            }

            await stagingStore.TrimDown(prefix);     // remove all staging entities that may be faked

            var sentBy = activity["actor"].First().Id;

            if (subject != null && sentBy != subject)
            {
                throw new UnauthorizedAccessException("Invalid authorization header for this subject!");
            }

            if (user.Data["blocks"].Any())
            {
                var blocks = await _mainStore.GetEntity(user.Data["blocks"].First().Id, false);

                var blocked = await _mainStore.GetEntity(blocks.Data["blocked"].First().Id, false);

                if (await _collectionTools.Contains(blocked, sentBy))
                {
                    throw new UnauthorizedAccessException("You are blocked.");
                }
            }

            if (await _collectionTools.Contains(inbox, id))
            {
                return(flattened);
            }

            await stagingStore.CommitChanges();

            foreach (var type in ServerConfig.ServerToServerHandlers)
            {
                var handler = (BaseHandler)ActivatorUtilities.CreateInstance(_serviceProvider, type,
                                                                             _mainStore, flattened, user, inbox, _user);
                var handled = await handler.Handle();

                flattened = handler.MainObject;
                if (!handled)
                {
                    break;
                }
            }

            return(flattened);
        }
Beispiel #5
0
            public async Task <ASObject> ServerToServer(APEntity inbox, ASObject activity, string subject = null)
            {
                var stagingStore = new StagingEntityStore(_mainStore);
                var userId       = (string)inbox.Data["attributedTo"].Single().Primitive;
                var user         = await _mainStore.GetEntity(userId, false);

                APEntity flattened;

                var subjectUri = new Uri(subject);
                var prefix     = $"{subjectUri.Scheme}://{subjectUri.Host}";

                if (subjectUri.Port != 0)
                {
                    prefix += $":{subjectUri.Port}";
                }
                prefix += "/";

                var id = (string)activity["id"].Single().Primitive;

                flattened = await _mainStore.GetEntity(id, false);

                if (flattened == null)
                {
                    flattened = await _flattener.FlattenAndStore(stagingStore, activity, false);
                }

                stagingStore.TrimDown(prefix); // remove all staging entities that may be faked

                var sentBy = (string)activity["actor"].First().Primitive;

                if (subject != null && sentBy != subject)
                {
                    throw new UnauthorizedAccessException("Invalid authorization header for this subject!");
                }

                if (user.Data["blocks"].Any())
                {
                    var blocks = await _mainStore.GetEntity((string)user.Data["blocks"].First().Primitive, false);

                    if (await _collectionTools.Contains((string)blocks.Data["_blocked"].First().Primitive, sentBy))
                    {
                        throw new UnauthorizedAccessException("You are blocked.");
                    }
                }

                if (await _collectionTools.Contains(inbox.Id, id))
                {
                    return(flattened.Data);
                }

                _serverToServerMutex.WaitOne();

                try
                {
                    using (var transaction = _context.Database.BeginTransaction())
                    {
                        foreach (var type in _serverToServerHandlers)
                        {
                            var handler = (BaseHandler)ActivatorUtilities.CreateInstance(_serviceProvider, type,
                                                                                         stagingStore, flattened, user, inbox, _user);
                            var handled = await handler.Handle();

                            flattened = handler.MainObject;
                            if (!handled)
                            {
                                break;
                            }
                        }

                        await _context.SaveChangesAsync();

                        transaction.Commit();

                        return(flattened.Data);
                    }
                }
                finally
                {
                    _serverToServerMutex.Release();
                }
            }
Beispiel #6
0
        public async Task <APEntity> GetEntity(string id, bool doRemote)
        {
            if (id == "https://www.w3.org/ns/activitystreams#Public")
            {
                var aso = new ASObject();
                aso.Type.Add("https://www.w3.org/ns/activitystreams#Collection");
                aso.Id = "https://www.w3.org/ns/activitystreams#Public";

                var ent = APEntity.From(aso);
                return(ent);
            }
            try {
                if ((new Uri(id)).Host == "localhost")
                {
                    return(await Bypass.GetEntity(id, doRemote));
                }
            } catch (UriFormatException) { /* nom */ }

            APEntity entity = null;

            if (Bypass != null)
            {
                entity = await Bypass.GetEntity(id, doRemote);
            }
            if (entity != null && !entity.IsOwner && entity.Data.Type.Any(_collections.Contains) && doRemote)
            {
                entity = null;
            }

            if (entity?.Type == "_:LazyLoad" && !doRemote)
            {
                return(null);
            }
            if ((entity != null && entity.Type != "_:LazyLoad") || !doRemote)
            {
                return(entity);
            }

            var loadUrl = id;

            if (entity?.Type == "_:LazyLoad")
            {
                loadUrl = (string)entity.Data["href"].First().Primitive;
            }

            if (loadUrl.StartsWith("tag:"))
            {
                return(null);
            }

            var htc = new HttpClient();

            htc.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/activity+json; application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", application/json, application/atom+xml, text/html");

            if (_context != null)
            {
                var signatureVerifier = _serviceProvider.GetRequiredService <SignatureVerifier>();
                var user = await Bypass.GetEntity(_context.User.FindFirstValue(JwtTokenSettings.ActorClaim), false);

                if (user != null)
                {
                    var jwt = await signatureVerifier.BuildJWS(user, id);

                    if (jwt != null)
                    {
                        htc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwt);
                    }
                }
            }

            HttpResponseMessage response = null;

            try
            {
                response = await htc.GetAsync(loadUrl);

                if (!response.IsSuccessStatusCode)
                {
                    response = await htc.GetAsync(loadUrl + ".atom"); // hack!

                    if (!response.IsSuccessStatusCode)
                    {
                        return(null);
                    }
                }
            }
            catch (TaskCanceledException)
            {
                return(null); // timeout
            }
            catch (HttpRequestException)
            {
                return(null);
            }

            var converters = new List <IConverterFactory> {
                new AS2ConverterFactory(), new AtomConverterFactory(false)
            };

tryAgain:
            ASObject data = null;

            foreach (var converter in converters)
            {
                if (converter.CanParse && ConverterHelpers.GetBestMatch(converter.MimeTypes, response.Content.Headers.ContentType.ToString()) != null)
                {
                    data = await converter.Build(_serviceProvider, null).Parse(await response.Content.ReadAsStreamAsync());

                    break;
                }
            }

            if (data == null)
            {
                if (response.Headers.Contains("Link"))
                {
                    var split = string.Join(", ", response.Headers.GetValues("Link")).Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var spl in split)
                    {
                        var args = spl.Split(';').Select(a => a.Trim()).ToArray();
                        if (args.Contains("rel=\"alternate\"") && args.Contains("type=\"application/atom+xml\""))
                        {
                            response = await htc.GetAsync(args[0].Substring(1, args[0].Length - 2));

                            goto tryAgain;
                        }
                    }
                }

                try
                {
                    var links = (await response.Content.ReadAsStringAsync()).Split('\n');
                    var alt   = links.FirstOrDefault(a => a.Contains("application/atom+xml") && a.Contains("alternate"));
                    if (alt == null)
                    {
                        return(null);
                    }
                    var l = XDocument.Parse(alt + "</link>").Root;
                    if (l.Attribute(XNamespace.None + "type")?.Value == "application/atom+xml")
                    {
                        response = await htc.GetAsync(l.Attribute(XNamespace.None + "href")?.Value);

                        goto tryAgain;
                    }
                }
                catch (Exception) { }

                return(null);
            }

            // forces out the old lazy load, if used
            await _entityFlattener.FlattenAndStore(Bypass, data, false);

            return(await Bypass.GetEntity(id, true));
        }
Beispiel #7
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"));
            }
        }
Beispiel #8
0
        public async Task <APEntity> GetEntity(string id, bool doRemote)
        {
            if (id == "https://www.w3.org/ns/activitystreams#Public")
            {
                var aso = new ASObject();
                aso.Type.Add("https://www.w3.org/ns/activitystreams#Collection");
                aso.Id = "https://www.w3.org/ns/activitystreams#Public";

                var ent = APEntity.From(aso);
                return(ent);
            }
            string origin = id;

            try {
                var uri = new Uri(id);
                if (uri.Host == "localhost")
                {
                    return(await Bypass.GetEntity(id, doRemote));
                }
                origin = uri.GetLeftPart(UriPartial.Authority);
            } catch (UriFormatException) { /* nom */ }

            APEntity entity = null;

            if (Bypass != null)
            {
                entity = await Bypass.GetEntity(id, doRemote);
            }

/*            if (entity == null)
 *          {
 *              var possibilities = (await _getRE().Query(new RelevantEntitiesService.ContainsAnyStatement("https://www.w3.org/ns/activitystreams#url") { id })).Where(a => Uri.IsWellFormedUriString(a.Id, UriKind.Absolute) && (new Uri(a.Id)).GetLeftPart(UriPartial.Authority) == origin).ToList();
 *              if (possibilities.Count == 1) entity = possibilities.First();
 *          }*/
            if (entity != null && !entity.IsOwner && entity.Data.Type.Any(_collections.Contains) && doRemote)
            {
                entity = null;
            }
            if (entity != null || !doRemote)
            {
                return(entity);
            }

            var htc     = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Get, id);

            request.Headers.TryAddWithoutValidation("Accept", "application/activity+json; application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", application/json, text/html");

            if (_context != null)
            {
                var signatureVerifier = _serviceProvider.GetRequiredService <SignatureVerifier>();
                var user = await Bypass.GetEntity(_context.User.FindFirstValue("actor"), false);

                if (user != null)
                {
                    var jwt = await signatureVerifier.BuildJWS(user, id);

                    if (jwt != null)
                    {
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwt);
                    }
                    request.Headers.TryAddWithoutValidation("Signature", await _keyService.BuildHTTPSignature(user.Id, request));
                }
            }

            HttpResponseMessage response = null;

            try
            {
                response = await htc.SendAsync(request);
            }
            catch (TaskCanceledException)
            {
                return(null); // timeout
            }
            catch (HttpRequestException)
            {
                return(null);
            }

            ASObject data = null;
            await response.Content.LoadIntoBufferAsync();

            foreach (var converter in ServerConfig.Converters)
            {
                if (converter.CanParse && ConverterHelpers.GetBestMatch(converter.MimeTypes, response.Content.Headers.ContentType.ToString()) != null)
                {
                    try {
                        data = await converter.Build(_serviceProvider, null).Parse(await response.Content.ReadAsStreamAsync());

                        break;
                    } catch (NullReferenceException e) { Console.WriteLine(e); /* nom */ }
                }
            }

            if (data == null)
            {
                return(null);
            }

            // forces out the old lazy load, if used
            await _entityFlattener.FlattenAndStore(Bypass, data, false);

            return(await Bypass.GetEntity(id, true));
        }