Skip to content

Commit

Permalink
Add date in file info; When you click calculate hash, it will be comp…
Browse files Browse the repository at this point in the history
…ared with the stored hash for the file; if they are different, the hash will be highlighted in red
  • Loading branch information
ImoutoChan committed Dec 1, 2024
1 parent b10a226 commit 46b4a1e
Show file tree
Hide file tree
Showing 25 changed files with 688 additions and 110 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
* Add Resqueue dashboard
* Add new videos in README for the initial launch and configuration of collections

### Navigator
* Add date in file info
* When you click calculate hash, it will be compared with the stored hash for the file;
if they are different, the hash will be highlighted in red

# 4.26.1

### Infrastructure
Expand Down
1 change: 1 addition & 0 deletions Source/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,6 @@
<PackageVersion Include="System.Private.Uri" Version="4.3.2"/>
<PackageVersion Include="System.Net.Http" Version="4.3.4"/>
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1"/>
<PackageVersion Include="NodaTime.Serialization.SystemTextJson" Version="1.2.0"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" />
<PackageReference Include="NodaTime" />
<PackageReference Include="NodaTime.Serialization.SystemTextJson" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace ImoutoRebirth.Common.WebApi.NodaTime;

internal class NamingPolicyParameterFilter : IParameterFilter
{
private readonly NodaTimeSchemaSettings _nodaTimeSchemaSettings;

public NamingPolicyParameterFilter(NodaTimeSchemaSettings nodaTimeSchemaSettings)
=> _nodaTimeSchemaSettings = nodaTimeSchemaSettings;

public void Apply(OpenApiParameter parameter, ParameterFilterContext context)
=> parameter.Name = _nodaTimeSchemaSettings.ResolvePropertyName(parameter.Name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using NodaTime;

namespace ImoutoRebirth.Common.WebApi.NodaTime;

public class NodaTimeSchemaSettings
{
public Func<string, string> ResolvePropertyName { get; }

public Func<object, string> FormatToJson { get; }

public IDateTimeZoneProvider DateTimeZoneProvider { get; }

public bool ShouldGenerateExamples { get; }

public SchemaExamples SchemaExamples { get; }

/// <param name="resolvePropertyName">Function that resolves property name by proper naming strategy.</param>
/// <param name="formatToJson">Function that formats object as json text.</param>
/// <param name="shouldGenerateExamples">Should the example node be generated.</param>
/// <param name="schemaExamples"><see cref="SchemaExamples"/> for schema example values.</param>
/// <param name="dateTimeZoneProvider"><see cref="IDateTimeZoneProvider"/> configured in Startup.</param>
public NodaTimeSchemaSettings(
Func<string, string> resolvePropertyName,
Func<object, string> formatToJson,
bool shouldGenerateExamples,
SchemaExamples? schemaExamples = null,
IDateTimeZoneProvider? dateTimeZoneProvider = null)
{
ResolvePropertyName = resolvePropertyName;
FormatToJson = formatToJson;

DateTimeZoneProvider = dateTimeZoneProvider ?? DateTimeZoneProviders.Tzdb;

ShouldGenerateExamples = shouldGenerateExamples;
SchemaExamples = schemaExamples ?? new SchemaExamples(
DateTimeZoneProvider,
dateTimeUtc: null,
dateTimeZone: null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Text.Json;

namespace ImoutoRebirth.Common.WebApi.NodaTime;

public static class NodaTimeSchemaSettingsFactory
{
public static NodaTimeSchemaSettings CreateNodaTimeSchemaSettings(
this JsonSerializerOptions jsonSerializerOptions)
{
return new NodaTimeSchemaSettings(ResolvePropertyName, FormatToJson, true);

string ResolvePropertyName(string propertyName)
=> jsonSerializerOptions.PropertyNamingPolicy?.ConvertName(propertyName) ?? propertyName;

string FormatToJson(object value)
=> JsonSerializer.Serialize(value, jsonSerializerOptions).Trim('\"');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using NodaTime;

namespace ImoutoRebirth.Common.WebApi.NodaTime;

public class SchemaExamples
{
public DateTimeZone DateTimeZone { get; set; }

public Instant Instant { get; set; }

public ZonedDateTime ZonedDateTime { get; set; }

public Interval Interval { get; set; }

public DateInterval DateInterval { get; set; }

public Period Period { get; set; }

public OffsetDate OffsetDate { get; set; }

public OffsetTime OffsetTime { get; set; }

public OffsetDateTime OffsetDateTime { get; set; }

/// <summary>
/// Creates example value by provided <see cref="DateTime"/> and <see cref="IDateTimeZoneProvider"/>.
/// </summary>
/// <param name="dateTimeZoneProvider">IDateTimeZoneProvider instance.</param>
/// <param name="dateTimeUtc"><see cref="DateTime"/>. If not set then <see cref="DateTime.UtcNow"/> will be used.</param>
/// <param name="dateTimeZone">Optional DateTimeZone name. If not set SystemDefault will be used.</param>
public SchemaExamples(
IDateTimeZoneProvider dateTimeZoneProvider,
DateTime? dateTimeUtc = null,
string? dateTimeZone = null)
{
var dateTimeUtcValue = dateTimeUtc ?? DateTime.UtcNow;

if (dateTimeUtcValue.Kind != DateTimeKind.Utc)
throw new ArgumentException("dateTimeUtc should be UTC", nameof(dateTimeUtc));

DateTimeZone = dateTimeZone != null
? dateTimeZoneProvider.GetZoneOrNull(dateTimeZone) ?? dateTimeZoneProvider.GetSystemDefault()
: dateTimeZoneProvider.GetSystemDefault();

Instant = Instant.FromDateTimeUtc(dateTimeUtcValue);

ZonedDateTime = Instant.InZone(DateTimeZone);

Interval = new Interval(Instant,
Instant.PlusTicks(TimeSpan.TicksPerDay)
.PlusTicks(TimeSpan.TicksPerHour)
.PlusTicks(TimeSpan.TicksPerMinute)
.PlusTicks(TimeSpan.TicksPerSecond)
.PlusTicks(TimeSpan.TicksPerMillisecond));

DateInterval = new DateInterval(ZonedDateTime.Date, ZonedDateTime.Date.PlusDays(1));

Period = Period.Between(
ZonedDateTime.LocalDateTime,
Interval.End.InZone(DateTimeZone).LocalDateTime,
PeriodUnits.AllUnits);

OffsetDate = new OffsetDate(ZonedDateTime.Date, ZonedDateTime.Offset);

OffsetTime = new OffsetTime(ZonedDateTime.TimeOfDay, ZonedDateTime.Offset);

OffsetDateTime = Instant.WithOffset(ZonedDateTime.Offset);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.OpenApi.Models;

namespace ImoutoRebirth.Common.WebApi.NodaTime;

public class Schemas
{
public required Func<OpenApiSchema> Instant { get; set; }

public required Func<OpenApiSchema> LocalDate { get; set; }

public required Func<OpenApiSchema> LocalTime { get; set; }

public required Func<OpenApiSchema> LocalDateTime { get; set; }

public required Func<OpenApiSchema> OffsetDateTime { get; set; }

public required Func<OpenApiSchema> ZonedDateTime { get; set; }

public required Func<OpenApiSchema> Interval { get; set; }

public required Func<OpenApiSchema> DateInterval { get; set; }

public required Func<OpenApiSchema> Offset { get; set; }

public required Func<OpenApiSchema> Period { get; set; }

public required Func<OpenApiSchema> Duration { get; set; }

public required Func<OpenApiSchema> OffsetDate { get; set; }

public required Func<OpenApiSchema> OffsetTime { get; set; }

public required Func<OpenApiSchema> DateTimeZone { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using NodaTime;

namespace ImoutoRebirth.Common.WebApi.NodaTime;

public class SchemasFactory
{
private readonly NodaTimeSchemaSettings _settings;

public SchemasFactory(NodaTimeSchemaSettings settings) => _settings = settings;

public Schemas CreateSchemas()
{
var examples = _settings.SchemaExamples;

// https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14
return new Schemas
{
Instant = () => StringSchema(examples.Instant, "date-time"),
LocalDate = () => StringSchema(examples.ZonedDateTime.Date, "date"),
LocalTime = () => StringSchema(examples.ZonedDateTime.TimeOfDay),
LocalDateTime = () => StringSchema(examples.ZonedDateTime.LocalDateTime),
OffsetDateTime = () => StringSchema(examples.OffsetDateTime, "date-time"),
ZonedDateTime = () => StringSchema(examples.ZonedDateTime),
Interval = () => new OpenApiSchema
{
Type = "object",
Properties = new Dictionary<string, OpenApiSchema>
{
{ ResolvePropertyName(nameof(Interval.Start)), StringSchema(examples.Interval.Start, "date-time") },
{ ResolvePropertyName(nameof(Interval.End)), StringSchema(examples.Interval.End, "date-time") },
},
},
DateInterval = () => new OpenApiSchema
{
Type = "object",
Properties = new Dictionary<string, OpenApiSchema>
{
{ ResolvePropertyName(nameof(DateInterval.Start)), StringSchema(examples.DateInterval.Start, "date") },
{ ResolvePropertyName(nameof(DateInterval.End)), StringSchema(examples.DateInterval.End, "date") },
},
},
Offset = () => StringSchema(examples.ZonedDateTime.Offset),
Period = () => StringSchema(examples.Period),
Duration = () => StringSchema(examples.Interval.Duration),
OffsetDate = () => StringSchema(examples.OffsetDate),
OffsetTime = () => StringSchema(examples.OffsetTime),
DateTimeZone = () => StringSchema(examples.DateTimeZone),
};
}

private OpenApiSchema StringSchema(object exampleObject, string? format = null)
{
return new OpenApiSchema
{
Type = "string",
Example = _settings.ShouldGenerateExamples
? new OpenApiString(FormatToJson(exampleObject))
: null,
Format = format
};
}

private string ResolvePropertyName(string propertyName) => _settings.ResolvePropertyName(propertyName);

private string FormatToJson(object value) => _settings.FormatToJson(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using NodaTime;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace ImoutoRebirth.Common.WebApi.NodaTime;

public static class SwaggerGenOptionsExtensions
{
public static void ConfigureForNodaTime(this SwaggerGenOptions config, JsonSerializerOptions options)
{
ArgumentNullException.ThrowIfNull(config);

var nodaTimeSchemaSettings = options.CreateNodaTimeSchemaSettings();
config.ConfigureForNodaTime(nodaTimeSchemaSettings);
}

public static void ConfigureForNodaTime(this SwaggerGenOptions config, NodaTimeSchemaSettings nodaTimeSchemaSettings)
{
config.ParameterFilter<NamingPolicyParameterFilter>(nodaTimeSchemaSettings);

var schemas = new SchemasFactory(nodaTimeSchemaSettings).CreateSchemas();

config.MapType<Instant> (schemas.Instant);
config.MapType<LocalDate> (schemas.LocalDate);
config.MapType<LocalTime> (schemas.LocalTime);
config.MapType<LocalDateTime> (schemas.LocalDateTime);
config.MapType<OffsetDateTime> (schemas.OffsetDateTime);
config.MapType<ZonedDateTime> (schemas.ZonedDateTime);
config.MapType<Interval> (schemas.Interval);
config.MapType<DateInterval> (schemas.DateInterval);
config.MapType<Offset> (schemas.Offset);
config.MapType<Period> (schemas.Period);
config.MapType<Duration> (schemas.Duration);
config.MapType<OffsetDate> (schemas.OffsetDate);
config.MapType<OffsetTime> (schemas.OffsetTime);
config.MapType<DateTimeZone> (schemas.DateTimeZone);

// Nullable structs
config.MapType<Instant?> (schemas.Instant);
config.MapType<LocalDate?> (schemas.LocalDate);
config.MapType<LocalTime?> (schemas.LocalTime);
config.MapType<LocalDateTime?> (schemas.LocalDateTime);
config.MapType<OffsetDateTime?>(schemas.OffsetDateTime);
config.MapType<ZonedDateTime?> (schemas.ZonedDateTime);
config.MapType<Interval?> (schemas.Interval);
config.MapType<Offset?> (schemas.Offset);
config.MapType<Duration?> (schemas.Duration);
config.MapType<OffsetDate?> (schemas.OffsetDate);
config.MapType<OffsetTime?> (schemas.OffsetTime);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public static IServiceCollection AddMinimalSwagger(
{
c.SchemaFilter<EnumFilter>();
c.SchemaFilter<RequireValueTypePropertiesSchemaFilter>();
c.SupportNonNullableReferenceTypes();
c.NonNullableReferenceTypesAsRequired();

c.SwaggerDoc("v1.0", new OpenApiInfo
{
Expand All @@ -76,7 +78,7 @@ public static IServiceCollection AddMinimalSwagger(

return upperControllerName + '_' + name;
});

configure?.Invoke(c);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ public async Task<int> CountFiles(
return roomIds.Count(x => lilinIdsHashSet.Contains(x));
}

public async Task<FileMetadata> GetFileMetadata(Guid fileId)
{
var meta = await _collectionFilesClient.GetCollectionFileMetadataAsync(fileId);
return new FileMetadata(fileId, meta.StoredMd5, meta.AddedOn);
}

public async Task<int> CountFiles1(
Guid? collectionId,
IReadOnlyCollection<SearchTag> tags,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ Task<int> CountFiles(
IReadOnlyCollection<SearchTag> tags,
CancellationToken cancellationToken);

Task<FileMetadata> GetFileMetadata(Guid fileId);

Task RemoveFile(Guid fileId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using ImoutoRebirth.Room.WebApi.Client;

namespace ImoutoRebirth.Navigator.Services.Tags.Model;

public record FileMetadata(Guid Id, string StoredMd5, DateTimeOffset AddedOn);
Loading

0 comments on commit 46b4a1e

Please sign in to comment.