public async Task <Build> Save(AppDbContext dbContext, bool clearCache = true) { if (_owner == null && _ownerBuilder == null) { throw new Exception("Must set owner."); } if (_payload == null && _payloadBuilder == null) { throw new Exception("Must set payload."); } _owner ??= await _ownerBuilder !.Save(dbContext, clearCache: false); _payload ??= await _payloadBuilder !.Save(dbContext, clearCache: false); var request = new BuildService.CreateRequest( _owner.UserName, "simple-book", "Simple Blueprint Book", null, _tags, (_payload.Hash, null, null, Enumerable.Empty <GameIcon>()), null); var service = new BuildService(new NullLogger <BuildService>(), dbContext, TestUtils.Tags.Value); var result = await service.CreateOrAddVersion(request, new NullTempCoverHandle(), _owner.ToClaimsPrincipal()); result.Should().BeOfType <BuildService.CreateResult.Success>(); if (clearCache) { dbContext.ClearCache(); } return(((BuildService.CreateResult.Success)result).Build); }
public async Task <IActionResult> CreateBuild([FromForm, Required] CreateBuildRequest request) { using var cover = await SaveTempCover(request.Cover); var result = await _buildService.CreateOrAddVersion(new BuildService.CreateRequest( User.GetUserName(), request.Slug, request.Title, request.Description, request.Tags, (request.Hash, request.Version.Name, request.Version.Description, request.Version.Icons), null), cover, User); return(result switch { BuildService.CreateResult.Success success => Created(Url.ActionLink(nameof(GetDetails), "Build", new { owner = success.Build.OwnerSlug, slug = success.Build.Slug, }), success.Build.ToThinViewModel(Url)), BuildService.CreateResult.DuplicateHash error => Conflict(error.ToProblem()), BuildService.CreateResult.DuplicateSlug error => Conflict(error.ToProblem()), { } error => BadRequest(error.ToProblem()), });
public async Task CreateOrAddVersion_ShouldSaveBlueprintGraph_WhenAddingANewBlueprint() { var owner = await new UserBuilder().Save(_dbContext); var payload = await new PayloadBuilder().WithEncoded(TestData.SimpleBookEncoded).Save(_dbContext); var request = new BuildService.CreateRequest( owner.UserName, "test-1", "test blueprint 1", "the description", new[] { "/belt/balancer", "/state/early game" }, (payload.Hash, null, null, Enumerable.Empty <GameIcon>()), null); var result = await _service.CreateOrAddVersion(request, new NullTempCoverHandle(), owner.ToClaimsPrincipal()); result.Should().BeOfType <BuildService.CreateResult.Success>(); _dbContext.Builds.Should().HaveCount(1); _dbContext.Payloads.Should().HaveCount(1); _dbContext.Versions.Should().HaveCount(1); var build = ((BuildService.CreateResult.Success)result).Build; build.Slug.Should().Be("test-1"); build.Title.Should().Be("test blueprint 1"); build.Description.Should().Be("the description"); build.CreatedAt.ToDateTimeUtc().Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(2)); build.UpdatedAt.Should().Be(build.CreatedAt); build.Tags !.Should().BeEquivalentTo("/belt/balancer", "/state/early game"); }
public async Task CreateOrAddVersion_ShouldUpdateBlueprintMetadata_WhenAddingAVersion() { var owner = await new UserBuilder().Save(_dbContext); var payload = await new PayloadBuilder().WithEncoded(TestData.SimpleBookEncoded).Save(_dbContext); var existingPayload = await new PayloadBuilder().WithEncoded(TestData.SimpleBlueprintEncoded).Save(_dbContext); var existing = await new BuildBuilder().WithPayload(existingPayload).WithOwner(owner).Save(_dbContext); var request = new BuildService.CreateRequest( owner.UserName, existing.Slug, "different title", "different description", new[] { "/belt/balancer", "/state/mid game", "/production/smelting" }, (payload.Hash, null, null, Enumerable.Empty <GameIcon>()), existing.LatestVersionId); var result = await _service.CreateOrAddVersion(request, new NullTempCoverHandle(), owner.ToClaimsPrincipal()); result.Should().BeOfType <BuildService.CreateResult.Success>(); _dbContext.Builds.Should().HaveCount(1); _dbContext.Payloads.Should().HaveCount(2); _dbContext.Versions.Should().HaveCount(2); var build = ((BuildService.CreateResult.Success)result).Build; build.Slug.Should().Be(existing.Slug); build.Title.Should().Be("different title"); build.Description.Should().Be("different description"); build.UpdatedAt.ToDateTimeUtc().Should().BeAfter(existing.UpdatedAt.ToDateTimeUtc()); build.Tags !.Should().BeEquivalentTo("/belt/balancer", "/state/mid game", "/production/smelting"); }
private async Task SeedBuilds(IReadOnlyCollection <SeedBlueprint> blueprints) { _logger.LogInformation("Seeding {TotalCount} builds", blueprints.Count); var createdCount = 0; var skippedCount = 0; var errorCount = 0; foreach (var blueprint in blueprints) { var slug = blueprint.Title.ToSlug(); var username = blueprint.Owner.ToSlug(); var existing = await _dbContext.Builds.FirstOrDefaultAsync(bp => bp.OwnerSlug == username && bp.Slug == slug); if (existing != null) { skippedCount++; _logger.LogInformation("Blueprint {Title} by {Owner} already exists", blueprint.Title, blueprint.Owner); continue; } var owner = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserName == username); if (owner == null) { var email = Guid.NewGuid() + "@test.local.factorio.tech"; _logger.LogInformation("Creating user {DisplayName} / {UserName} / {Email}", blueprint.Owner, username, email); owner = new User { DisplayName = blueprint.Owner, UserName = username, NormalizedUserName = username.ToUpperInvariant(), Email = email, NormalizedEmail = email.ToUpperInvariant(), EmailConfirmed = true, RegisteredAt = SystemClock.Instance.GetCurrentInstant(), }; _dbContext.Add(owner); await _dbContext.SaveChangesAsync(); } var envelope = await _blueprintConverter.Decode(blueprint.Encoded); var payload = new Payload( Hash.Compute(blueprint.Encoded), _blueprintConverter.ParseType(envelope.Entity.Item), _blueprintConverter.DecodeGameVersion(envelope.Entity.Version), blueprint.Encoded); var cache = new PayloadCache(); cache.TryAdd(envelope, payload); await cache.EnsureInitializedGraph(envelope); await _buildService.SavePayloadGraph(payload.Hash, cache.Values); var tags = blueprint.Tags .Select(t => t.TrimEnd('/')) .Where(_buildTags.Contains) .ToArray(); var request = new BuildService.CreateRequest( username, slug, blueprint.Title, blueprint.Description, tags.Any() ? tags : GetSomeRandomTags(), (payload.Hash, null, null, envelope.Entity.Icons.ToGameIcons()), null); var principal = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new(ClaimTypes.NameIdentifier, owner.Id.ToString()), }));