fix: a lots of issues
This commit is contained in:
parent
ef1395945f
commit
3c17f95100
@ -58,7 +58,7 @@ public partial class RepositoryModel : ReactiveModel
|
||||
|
||||
public partial class Issue : ReactiveModel
|
||||
{
|
||||
[Reactive] private ulong _id;
|
||||
[Reactive] private int _id;
|
||||
|
||||
[Reactive] private string _title;
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ namespace Flawless.Client.Remote
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
[Headers("Accept: text/plain, application/json, text/json")]
|
||||
[Get("/api/admin/logs")]
|
||||
Task<ICollection<LogEntryResponse>> Logs([Query] System.DateTimeOffset? startTime, [Query] System.DateTimeOffset? endTime, [Query] LogLevel? level, [Query] int? page, [Query] int? pageSize, CancellationToken cancellationToken = default);
|
||||
Task<ICollection<LogEntryResponse>> Logs([Query] System.DateTimeOffset startTime, [Query] System.DateTimeOffset endTime, [Query] int level, [Query] int page, [Query] int pageSize, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <returns>OK</returns>
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
@ -148,7 +148,7 @@ namespace Flawless.Client.Remote
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
[Headers("Content-Type: application/json")]
|
||||
[Post("/api/issue/{userName}/{repositoryName}/{issueId}/comment")]
|
||||
Task Comment(string userName, string repositoryName, long issueId, [Body] AddCommentRequest body, CancellationToken cancellationToken = default);
|
||||
Task Comment(string userName, string repositoryName, int issueId, [Body] AddCommentRequest body, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
@ -165,13 +165,13 @@ namespace Flawless.Client.Remote
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
[Headers("Accept: text/plain, application/json, text/json")]
|
||||
[Get("/api/issue/{userName}/{repositoryName}/{issueId}")]
|
||||
Task<IssueDetailInfo> Issue(string userName, string repositoryName, long issueId, CancellationToken cancellationToken = default);
|
||||
Task<IssueDetailInfo> Issue(string userName, string repositoryName, int issueId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
[Headers("Content-Type: application/json")]
|
||||
[Patch("/api/issue/{userName}/{repositoryName}/{issueId}/edit")]
|
||||
Task Edit(string userName, string repositoryName, long issueId, [Body] UpdateIssueRequest body, CancellationToken cancellationToken = default);
|
||||
Task Edit(string userName, string repositoryName, int issueId, [Body] UpdateIssueRequest body, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
@ -182,7 +182,7 @@ namespace Flawless.Client.Remote
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
[Headers("Accept: text/plain, application/json, text/json")]
|
||||
[Get("/api/issue/{userName}/{repositoryName}/{issueId}/comments")]
|
||||
Task<CommentResponseListingResponse> Comments(string userName, string repositoryName, long issueId, CancellationToken cancellationToken = default);
|
||||
Task<CommentResponseListingResponse> Comments(string userName, string repositoryName, int issueId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
|
||||
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
|
||||
@ -540,7 +540,7 @@ namespace Flawless.Client.Remote
|
||||
{
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public long Id { get; set; }
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("author")]
|
||||
public string Author { get; set; }
|
||||
@ -570,7 +570,7 @@ namespace Flawless.Client.Remote
|
||||
{
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public long Id { get; set; }
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("author")]
|
||||
public string Author { get; set; }
|
||||
@ -887,7 +887,7 @@ namespace Flawless.Client.Remote
|
||||
public string NickName { get; set; }
|
||||
|
||||
[JsonPropertyName("gender")]
|
||||
public UserSex? Gender { get; set; }
|
||||
public int Gender { get; set; }
|
||||
|
||||
[JsonPropertyName("bio")]
|
||||
public string Bio { get; set; }
|
||||
@ -911,7 +911,7 @@ namespace Flawless.Client.Remote
|
||||
public string NickName { get; set; }
|
||||
|
||||
[JsonPropertyName("gender")]
|
||||
public UserSex Gender { get; set; }
|
||||
public int Gender { get; set; }
|
||||
|
||||
[JsonPropertyName("bio")]
|
||||
public string Bio { get; set; }
|
||||
@ -945,20 +945,6 @@ namespace Flawless.Client.Remote
|
||||
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")]
|
||||
public enum UserSex
|
||||
{
|
||||
|
||||
Unset = 0,
|
||||
|
||||
Male = 1,
|
||||
|
||||
Female = 2,
|
||||
|
||||
WalmartPlasticBag = 3,
|
||||
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")]
|
||||
public partial class WebhookCreateRequest
|
||||
{
|
||||
@ -978,11 +964,11 @@ namespace Flawless.Client.Remote
|
||||
public enum WebhookEventType
|
||||
{
|
||||
|
||||
Push = 0,
|
||||
_0 = 0,
|
||||
|
||||
IssueCreated = 1,
|
||||
_1 = 1,
|
||||
|
||||
IssueUpdate = 2
|
||||
_2 = 2,
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -298,7 +298,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
}
|
||||
|
||||
var issues = (await api.Gateway.List(repo.OwnerName, repo.Name))
|
||||
.Result.ToImmutableDictionary(x => (ulong) x.Id);
|
||||
.Result.ToImmutableDictionary(x => x.Id);
|
||||
|
||||
for (var i = 0; i < repo.Issues.Count; i++)
|
||||
{
|
||||
@ -350,7 +350,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
return true;
|
||||
}
|
||||
|
||||
public async ValueTask<bool> UpdateIssueDetailsFromServerAsync(RepositoryModel repo, ulong issueId, bool titleOnly)
|
||||
public async ValueTask<bool> UpdateIssueDetailsFromServerAsync(RepositoryModel repo, int issueId, bool titleOnly)
|
||||
{
|
||||
var api = Api.C;
|
||||
try
|
||||
@ -361,7 +361,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
return false;
|
||||
}
|
||||
|
||||
var issue = await api.Gateway.Issue(repo.Name, repo.OwnerName, (long)issueId);
|
||||
var issue = await api.Gateway.Issue(repo.Name, repo.OwnerName, issueId);
|
||||
|
||||
var entity = repo.Issues.FirstOrDefault(x => x.Id == issueId);
|
||||
var tags = issue.Tag.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
@ -371,7 +371,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
entity = new RepositoryModel.Issue
|
||||
{
|
||||
Author = issue.Author,
|
||||
Id = (ulong) issue.Id,
|
||||
Id = issue.Id,
|
||||
Title = issue.Title,
|
||||
Description = null,
|
||||
Closed = issue.Closed,
|
||||
@ -384,7 +384,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
|
||||
if (!titleOnly)
|
||||
{
|
||||
var details = (await api.Gateway.Comments(repo.Name, repo.OwnerName, (long)issueId))
|
||||
var details = (await api.Gateway.Comments(repo.Name, repo.OwnerName, issueId))
|
||||
.Result.ToImmutableDictionary(x => x.CommentId);
|
||||
|
||||
entity.Comments.AddRange(details.Select(x => new RepositoryModel.Comment
|
||||
@ -409,7 +409,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
|
||||
if (!titleOnly)
|
||||
{
|
||||
var details = (await api.Gateway.Comments(repo.Name, repo.OwnerName, (long)issueId))
|
||||
var details = (await api.Gateway.Comments(repo.Name, repo.OwnerName, issueId))
|
||||
.Result.ToImmutableDictionary(x => x.CommentId);
|
||||
|
||||
for (var i = 0; i < entity.Comments.Count; i++)
|
||||
@ -457,7 +457,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
return true;
|
||||
}
|
||||
|
||||
public async ValueTask<ulong?> CreateIssueAsync(RepositoryModel repo, string title, string description, IEnumerable<string>? tags)
|
||||
public async ValueTask<int?> CreateIssueAsync(RepositoryModel repo, string title, string description, IEnumerable<string>? tags)
|
||||
{
|
||||
var api = Api.C;
|
||||
try
|
||||
@ -482,7 +482,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
var entity = new RepositoryModel.Issue
|
||||
{
|
||||
Author = issue.Author,
|
||||
Id = (ulong) issue.Id,
|
||||
Id = issue.Id,
|
||||
Title = issue.Title,
|
||||
Description = null,
|
||||
Closed = issue.Closed,
|
||||
@ -504,7 +504,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<bool> CloseIssueAsync(RepositoryModel repo, ulong issueId)
|
||||
public async ValueTask<bool> CloseIssueAsync(RepositoryModel repo, int issueId)
|
||||
{
|
||||
var api = Api.C;
|
||||
try
|
||||
@ -527,7 +527,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<bool> ReopenIssueAsync(RepositoryModel repo, ulong issueId)
|
||||
public async ValueTask<bool> ReopenIssueAsync(RepositoryModel repo, int issueId)
|
||||
{
|
||||
var api = Api.C;
|
||||
try
|
||||
@ -550,7 +550,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<bool> AddCommentAsync(RepositoryModel repo, ulong issueId, string content, ulong? replyTo)
|
||||
public async ValueTask<bool> AddCommentAsync(RepositoryModel repo, int issueId, string content, ulong? replyTo)
|
||||
{
|
||||
var api = Api.C;
|
||||
try
|
||||
@ -561,7 +561,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
return false;
|
||||
}
|
||||
|
||||
await api.Gateway.Comment(repo.OwnerName, repo.Name, (long) issueId,
|
||||
await api.Gateway.Comment(repo.OwnerName, repo.Name, issueId,
|
||||
new AddCommentRequest { Content = content, ReplyTo = replyTo.HasValue ? (long) replyTo.Value : null });
|
||||
return true;
|
||||
}
|
||||
@ -575,7 +575,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
|
||||
|
||||
|
||||
public async ValueTask<bool> UpdateIssueAsync(RepositoryModel repo, ulong issueId, string? title, string? description, IEnumerable<string>? tags)
|
||||
public async ValueTask<bool> UpdateIssueAsync(RepositoryModel repo, int issueId, string? title, string? description, IEnumerable<string>? tags)
|
||||
{
|
||||
var api = Api.C;
|
||||
try
|
||||
@ -592,7 +592,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
new StringBuilder().AppendJoin(',', tags);
|
||||
}
|
||||
|
||||
await api.Gateway.Edit(repo.OwnerName, repo.Name, (long) issueId,
|
||||
await api.Gateway.Edit(repo.OwnerName, repo.Name, issueId,
|
||||
new UpdateIssueRequest { Title = title, Description = description, Tag = tagString?.ToString()});
|
||||
return true;
|
||||
}
|
||||
@ -1290,6 +1290,7 @@ public class RepositoryService : BaseService<RepositoryService>
|
||||
|
||||
var accessor = await DownloadDepotsAndUseLocalCachesToGenerateRepositoryFileTreeAccessorFromServerAsync(repo, commitId);
|
||||
if (accessor == null) return null; //todo this is a really fatal issue...
|
||||
await accessor.CreateCacheAsync();
|
||||
if (localDb.RepoAccessor != null)
|
||||
{
|
||||
try
|
||||
|
||||
@ -24,14 +24,14 @@ public partial class IssueDetailViewModel : RoutableViewModelBase
|
||||
|
||||
private readonly RepositoryModel _repo;
|
||||
|
||||
public IssueDetailViewModel(IScreen screen, RepositoryModel repo, ulong issueId) : base(screen)
|
||||
public IssueDetailViewModel(IScreen screen, RepositoryModel repo, int issueId) : base(screen)
|
||||
{
|
||||
_repo = repo;
|
||||
_service = RepositoryService.Current;
|
||||
LoadDataAsync(repo, issueId, true);
|
||||
}
|
||||
|
||||
private async Task LoadDataAsync(RepositoryModel repo, ulong issueId, bool quitIfFailed)
|
||||
private async Task LoadDataAsync(RepositoryModel repo, int issueId, bool quitIfFailed)
|
||||
{
|
||||
using var _ = UIHelper.MakeLoading("Fetching comments from server...");
|
||||
if (!await _service.UpdateIssueDetailsFromServerAsync(repo, issueId, false))
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Flawless.Client.Remote;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.SourceGenerators;
|
||||
@ -12,4 +13,6 @@ public partial class WebhookEditDialogViewModel : ReactiveObject
|
||||
|
||||
[Reactive] private WebhookEventType _eventType;
|
||||
|
||||
[Reactive] private Type _eventTypeType = typeof(WebhookEventType);
|
||||
|
||||
}
|
||||
|
||||
@ -588,8 +588,9 @@ public partial class RepositoryViewModel : RoutableViewModelBase
|
||||
var manifest = await RepositoryService.C.CommitWorkspaceAsync(Repository, changes, LocalDatabase.CommitMessage!);
|
||||
if (manifest == null) return;
|
||||
|
||||
LocalDatabase.LocalAccessor.SetBaseline(manifest.Value.FilePaths);
|
||||
// LocalDatabase.LocalAccessor.SetBaseline(manifest.Value.FilePaths);
|
||||
LocalDatabase.CommitMessage = string.Empty;
|
||||
await RepositoryService.C.UpdateCommitsHistoryFromServerAsync(Repository);
|
||||
await DetectLocalChangesAsyncCommand.Execute();
|
||||
await RendererFileTreeAsync();
|
||||
SyncCommitsFromRepository();
|
||||
@ -818,7 +819,7 @@ public partial class RepositoryViewModel : RoutableViewModelBase
|
||||
ByDay = [
|
||||
new ColumnSeries<DateTimePoint>
|
||||
{
|
||||
Values = rsp.CommitByDay.Select(k => new DateTimePoint(k.Day.LocalDateTime, k.Count)).ToList(),
|
||||
Values = rsp.CommitByDay.Select(k => new DateTimePoint(k.Day.Date, k.Count)).ToList(),
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using DynamicData;
|
||||
@ -43,18 +44,22 @@ public partial class SettingViewModel : RoutableViewModelBase
|
||||
|
||||
[Reactive] private UserModel.SexType _gender;
|
||||
|
||||
[Reactive] private Type _genderType = typeof(UserModel.SexType);
|
||||
|
||||
[Reactive] private string _bio;
|
||||
|
||||
[Reactive] private DateTime
|
||||
[Reactive] private DateTimeOffset
|
||||
_logSearchFrom = DateTime.Now.AddDays(-1),
|
||||
_logSearchTo = DateTime.Now;
|
||||
|
||||
[Reactive] private int _page = 1;
|
||||
[Reactive] private int? _page = 1;
|
||||
|
||||
[Reactive] private int _pageSize = 50;
|
||||
[Reactive] private int? _pageSize = 50;
|
||||
|
||||
[Reactive] private Microsoft.Extensions.Logging.LogLevel _loglevel = Microsoft.Extensions.Logging.LogLevel.Information;
|
||||
|
||||
[Reactive] private Type _loglevelType = typeof(Microsoft.Extensions.Logging.LogLevel);
|
||||
|
||||
[Reactive] private string _serverBlacklist, _serverWhitelist;
|
||||
|
||||
public SettingViewModel(IScreen hostScreen) : base(hostScreen)
|
||||
@ -102,8 +107,9 @@ public partial class SettingViewModel : RoutableViewModelBase
|
||||
await Api.C.Gateway.UpdateInfo(new UserInfoModifyResponse
|
||||
{
|
||||
NickName = this.Nickname == LoginUser.Nickname ? null! : this.Nickname,
|
||||
Gender = this.Gender == LoginUser.Sex ? null : (UserSex) this.Gender,
|
||||
Bio = this.Bio == LoginUser.Bio ? null! : this.Bio
|
||||
Gender = (int) this.Gender,
|
||||
Bio = this.Bio == LoginUser.Bio ? null! : this.Bio,
|
||||
PublicEmail = false
|
||||
});
|
||||
|
||||
if (Email != LoginUser.Email)
|
||||
@ -114,6 +120,9 @@ public partial class SettingViewModel : RoutableViewModelBase
|
||||
await Api.C.Gateway.UpdatePhone(new UserContactModifyResponse
|
||||
{ Phone = PhoneNumber, });
|
||||
|
||||
LoginUser.Bio = Bio;
|
||||
LoginUser.Sex = Gender;
|
||||
LoginUser.Email = Email;
|
||||
UIHelper.NotifySuccess("Saved");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -358,9 +367,12 @@ public partial class SettingViewModel : RoutableViewModelBase
|
||||
{
|
||||
try
|
||||
{
|
||||
var logs = await Api.C.Gateway.Logs(
|
||||
LogSearchFrom, LogSearchTo, (LogLevel?)Loglevel, Page, PageSize);
|
||||
Page ??= 1;
|
||||
PageSize ??= 50;
|
||||
var logs = await Api.C.Gateway.Logs(
|
||||
LogSearchFrom, LogSearchTo, (int)Loglevel, Page.Value, PageSize.Value);
|
||||
|
||||
Logs.Clear();
|
||||
Logs.AddRange(logs.Select(Log.From));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
<TextBox Text="{Binding Secret}"/>
|
||||
</u:FormItem>
|
||||
<u:FormItem Grid.Row="1" Label="Event Type">
|
||||
<u:EnumSelector SelectedValue="{Binding EventType}"/>
|
||||
<u:EnumSelector EnumType="{Binding EventTypeType}" Value="{Binding EventType}"/>
|
||||
</u:FormItem>
|
||||
</u:Form>
|
||||
</UserControl>
|
||||
|
||||
@ -105,7 +105,8 @@
|
||||
</StackPanel>
|
||||
<StackPanel HorizontalAlignment="Stretch" Orientation="Vertical">
|
||||
<Label>Every Day Commits</Label>
|
||||
<lvc:CartesianChart Series="{Binding ByDay}" XAxes="{Binding XAxesByDay}"/>
|
||||
<lvc:CartesianChart Series="{Binding ByDay, Mode=TwoWay}" XAxes="{Binding XAxesByDay, Mode=TwoWay}">
|
||||
</lvc:CartesianChart>
|
||||
</StackPanel>
|
||||
<StackPanel HorizontalAlignment="Stretch" Orientation="Vertical">
|
||||
<Label>Depot Sizes</Label>
|
||||
|
||||
@ -25,7 +25,8 @@
|
||||
<TextBox u:FormItem.Label="Nickname" Text="{Binding Nickname}"/>
|
||||
<TextBox u:FormItem.Label="Email" Text="{Binding Email}"/>
|
||||
<TextBox u:FormItem.Label="Phone Number" Text="{Binding PhoneNumber}"/>
|
||||
<u:EnumSelector u:FormItem.Label="Gender" SelectedValue="{Binding Gender}"/>
|
||||
<u:EnumSelector u:FormItem.Label="Gender" EnumType="{Binding GenderType}"
|
||||
Value="{Binding Gender}"/>
|
||||
<TextBox u:FormItem.Label="Bio" Classes="TextArea" Text="{Binding Bio}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
@ -36,22 +37,7 @@
|
||||
</u:Form>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
<!-- <TabItem Header="Preference"> -->
|
||||
<!-- <ScrollViewer Width="600" HorizontalAlignment="Left" Margin="6"> -->
|
||||
<!-- <u:Form HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> -->
|
||||
<!-- ~1~ <u:FormItem Label="Default Storage Location"> @1@ -->
|
||||
<!-- ~1~ <u:PathPicker/> @1@ -->
|
||||
<!-- ~1~ </u:FormItem> @1@ -->
|
||||
<!-- <u:FormGroup Header="Extern Tools"> -->
|
||||
<!-- <u:PathPicker u:FormItem.Label="Diff Tool"/> -->
|
||||
<!-- </u:FormGroup> -->
|
||||
<!-- <StackPanel Orientation="Horizontal" Spacing="4"> -->
|
||||
<!-- <u:IconButton Content="Save" Command="{Binding SaveClientPreferenceCommand}"/> -->
|
||||
<!-- <u:IconButton Classes="Danger" Content="Reset" Command="{Binding ResetClientPreferenceCommand}"/> -->
|
||||
<!-- </StackPanel> -->
|
||||
<!-- </u:Form> -->
|
||||
<!-- </ScrollViewer> -->
|
||||
<!-- </TabItem> -->
|
||||
|
||||
<TabItem IsVisible="{Binding LoginUser.IsAdmin}" Header="Server">
|
||||
<ScrollViewer Width="600" HorizontalAlignment="Left" Margin="6">
|
||||
<u:Form HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
@ -138,19 +124,19 @@
|
||||
<DatePicker SelectedDate="{Binding LogSearchTo}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<u:EnumSelector SelectedValue="{Binding Loglevel, Mode=TwoWay}"/>
|
||||
<u:EnumSelector EnumType="{Binding LoglevelType}" Value="{Binding Loglevel, Mode=TwoWay}"/>
|
||||
<NumericUpDown Value="{Binding PageSize, Mode=TwoWay}" Minimum="10" Maximum="100"/>
|
||||
<NumericUpDown Value="{Binding Page, Mode=TwoWay}" Minimum="1"/>
|
||||
<u:IconButton Icon="{StaticResource SemiIconSearch}"
|
||||
Command="{Binding DownloadServerLogCommand}"/>
|
||||
</StackPanel>
|
||||
<ListBox ItemsSource="{Binding Logs, Mode=TwoWay}">
|
||||
<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Logs, Mode=TwoWay}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid RowDefinitions="Auto, *" ColumnDefinitions="Auto,*,Auto">
|
||||
<Label Grid.Row="0" Grid.Column="0" FontSize="16" Content="{Binding Level}"/>
|
||||
<Label Grid.Row="0" Grid.Column="2" FontSize="16" Content="{Binding Time}"/>
|
||||
<Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding Message}"/>
|
||||
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding Message}"/>
|
||||
<Label Grid.Row="1" Grid.Column="0" FontSize="10" Content="{Binding Level}"/>
|
||||
<Label Grid.Row="1" Grid.Column="2" FontSize="10" Content="{Binding Time}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
namespace Flawless.Communication.Request;
|
||||
|
||||
public record UserInfoModifyResponse
|
||||
public struct UserInfoModifyResponse
|
||||
{
|
||||
public string? NickName { get; set; }
|
||||
|
||||
public UserSex? Gender { get; set; }
|
||||
public int Gender { get; set; }
|
||||
|
||||
public string? Bio { get; set; }
|
||||
|
||||
|
||||
@ -2,4 +2,4 @@ using Flawless.Communication.Shared;
|
||||
|
||||
namespace Flawless.Communication.Request;
|
||||
|
||||
public record WebhookCreateRequest(string TargetUrl, WebhookEventType EventType, string Secret);
|
||||
public record WebhookCreateRequest(string TargetUrl, int EventType, string Secret);
|
||||
@ -4,7 +4,7 @@ namespace Flawless.Communication.Response;
|
||||
|
||||
public struct WebhookResponse
|
||||
{
|
||||
public WebhookResponse(int id, string targetUrl, WebhookEventType eventType, bool isActive, DateTime createdAt)
|
||||
public WebhookResponse(int id, string targetUrl, int eventType, bool isActive, DateTime createdAt)
|
||||
{
|
||||
Id = id;
|
||||
TargetUrl = targetUrl;
|
||||
@ -17,7 +17,7 @@ public struct WebhookResponse
|
||||
|
||||
public string TargetUrl { get; set; }
|
||||
|
||||
public WebhookEventType EventType { get; set; }
|
||||
public int EventType { get; set; }
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
namespace Flawless.Communication.Shared;
|
||||
|
||||
public record IssueInfo(
|
||||
ulong Id, string Author, string Title, DateTime CreateAt, DateTime LastUpdate, bool closed, string? Tag);
|
||||
int Id, string Author, string Title, DateTime CreateAt, DateTime LastUpdate, bool closed, string? Tag);
|
||||
|
||||
public record IssueDetailInfo(
|
||||
ulong Id, string Author, string Title, string Description, DateTime CreateAt, DateTime LastUpdate, bool closed, string? Tag);
|
||||
int Id, string Author, string Title, string Description, DateTime CreateAt, DateTime LastUpdate, bool closed, string? Tag);
|
||||
|
||||
public record IssueCommentInfo(
|
||||
ulong Id, string Author, string Content, DateTime CreateAt, DateTime LastUpdate, ulong? ReplyTo);
|
||||
int Id, string Author, string Content, DateTime CreateAt, DateTime LastUpdate, ulong? ReplyTo);
|
||||
@ -32,13 +32,14 @@ public class AdminController(
|
||||
UserName = request.Username,
|
||||
Email = request.Email,
|
||||
EmailConfirmed = true,
|
||||
CreatedOn = DateTime.UtcNow,
|
||||
CreatedOn = DateTime.UtcNow
|
||||
};
|
||||
|
||||
user.RenewSecurityStamp();
|
||||
var result = await userManager.CreateAsync(user, request.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await userManager.SetLockoutEnabledAsync(user, false);
|
||||
logger.LogInformation("User '{0}' created (SUPERUSER REGISTER)", user.UserName);
|
||||
return Ok();
|
||||
}
|
||||
@ -204,7 +205,7 @@ public class AdminController(
|
||||
public async Task<ActionResult<IEnumerable<LogEntryResponse>>> GetSystemLogsAsync(
|
||||
[FromQuery] DateTime startTime,
|
||||
[FromQuery] DateTime endTime,
|
||||
[FromQuery] LogLevel level,
|
||||
[FromQuery] int level,
|
||||
[FromQuery] int page,
|
||||
[FromQuery] int pageSize)
|
||||
{
|
||||
@ -212,11 +213,11 @@ public class AdminController(
|
||||
if (t != null) return t;
|
||||
|
||||
var query = dbContext.SystemLogs.Where(x =>
|
||||
x.Timestamp >= startTime && x.Timestamp <= endTime && x.LogLevel >= level
|
||||
x.Timestamp >= startTime && x.Timestamp <= endTime && (int) x.LogLevel >= level
|
||||
).AsQueryable();
|
||||
|
||||
// 分页处理
|
||||
var totalCount = await query.CountAsync();
|
||||
// var totalCount = await query.CountAsync();
|
||||
var results = await query
|
||||
.OrderByDescending(l => l.Timestamp)
|
||||
.Skip((page - 1) * pageSize)
|
||||
@ -228,6 +229,6 @@ public class AdminController(
|
||||
l.Exception))
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(new PaginatedResponse<LogEntryResponse>(results, totalCount, page, pageSize));
|
||||
return Ok(results);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Flawless.Communication.Request;
|
||||
using Flawless.Communication.Response;
|
||||
using Flawless.Communication.Shared;
|
||||
@ -48,7 +49,8 @@ public class AuthenticationController(
|
||||
Email = r.AdminEmail,
|
||||
EmailConfirmed = true,
|
||||
CreatedOn = DateTime.UtcNow,
|
||||
Admin = true
|
||||
Admin = true,
|
||||
LockoutEnabled = false
|
||||
};
|
||||
|
||||
user.RenewSecurityStamp();
|
||||
@ -74,19 +76,20 @@ public class AuthenticationController(
|
||||
UserName = request.Username,
|
||||
Email = request.Email,
|
||||
EmailConfirmed = true,
|
||||
CreatedOn = DateTime.UtcNow,
|
||||
CreatedOn = DateTime.UtcNow
|
||||
};
|
||||
|
||||
user.RenewSecurityStamp();
|
||||
var result = await userManager.CreateAsync(user, request.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await userManager.SetLockoutEnabledAsync(user, false);
|
||||
logger.LogInformation("User '{0}' created (PUBLIC REGISTER)", user.UserName);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
logger.LogInformation("User '{0}' NOT created (PUBLIC REGISTER) : {1}", user.UserName, result.Errors);
|
||||
return BadRequest(new FailedResponse(result.Errors));
|
||||
return BadRequest(new FailedResponse(new StringBuilder().AppendJoin(", ", result.Errors).ToString()));
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
@ -95,6 +98,7 @@ public class AuthenticationController(
|
||||
var user = await userManager.FindByNameAsync(r.Username);
|
||||
if (user == null) return BadRequest(new FailedResponse("Invalid username or password."));
|
||||
|
||||
if (user.LockoutEnabled) return BadRequest(new FailedResponse("Account is locked out."));
|
||||
var result = await signInManager.CheckPasswordSignInAsync(user, r.Password, false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
@ -132,6 +136,7 @@ public class AuthenticationController(
|
||||
var principal = tokenService.GetPrincipalFromExpiredToken(r.Token);
|
||||
var user = await userManager.GetUserAsync(principal);
|
||||
if (user == null) return BadRequest(new FailedResponse("Token is ban. Please login again."));
|
||||
if (user.LockoutEnabled) return BadRequest(new FailedResponse("Account is locked out."));
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@ -51,7 +51,7 @@ public class IssueController(
|
||||
public async Task<IActionResult> AddCommentAsync(
|
||||
string userName,
|
||||
string repositoryName,
|
||||
ulong issueId,
|
||||
int issueId,
|
||||
[FromBody] AddCommentRequest request)
|
||||
{
|
||||
var user = (await userManager.GetUserAsync(HttpContext.User))!;
|
||||
@ -122,7 +122,7 @@ public class IssueController(
|
||||
public async Task<ActionResult<IssueDetailInfo>> GetIssueDetailsAsync(
|
||||
string userName,
|
||||
string repositoryName,
|
||||
ulong issueId)
|
||||
int issueId)
|
||||
{
|
||||
var user = (await userManager.GetUserAsync(HttpContext.User))!;
|
||||
var grantIssue = await ValidateRepositoryAsync(userName, repositoryName, user, RepositoryRole.Reporter);
|
||||
@ -152,7 +152,7 @@ public class IssueController(
|
||||
public async Task<IActionResult> UpdateIssueAsync(
|
||||
string userName,
|
||||
string repositoryName,
|
||||
ulong issueId,
|
||||
int issueId,
|
||||
[FromBody] UpdateIssueRequest request)
|
||||
{
|
||||
var user = (await userManager.GetUserAsync(HttpContext.User))!;
|
||||
@ -198,7 +198,7 @@ public class IssueController(
|
||||
public async Task<ActionResult<ListingResponse<CommentResponse>>> GetIssueCommentsAsync(
|
||||
string userName,
|
||||
string repositoryName,
|
||||
ulong issueId)
|
||||
int issueId)
|
||||
{
|
||||
var user = (await userManager.GetUserAsync(HttpContext.User))!;
|
||||
var grantIssue = await ValidateRepositoryAsync(userName, repositoryName, user, RepositoryRole.Reporter);
|
||||
|
||||
@ -180,10 +180,15 @@ public class RepositoryInnieController(
|
||||
{
|
||||
var user = (await userManager.GetUserAsync(HttpContext.User))!;
|
||||
var grantIssue = await ValidateRepositoryAsync(userName, repositoryName, user, RepositoryRole.Owner);
|
||||
if (grantIssue is not Repository rp) return (ActionResult) grantIssue;
|
||||
|
||||
if (grantIssue is not Repository _) return (ActionResult) grantIssue;
|
||||
|
||||
var response = new RepoStatisticResponse();
|
||||
var rp = await dbContext.Repositories
|
||||
.Include(r => r.Members)
|
||||
.ThenInclude(m => m.User)
|
||||
.Include(r => r.Owner).Include(repository => repository.Depots).Include(repository => repository.Commits)
|
||||
.ThenInclude(repositoryCommit => repositoryCommit.Author)
|
||||
.FirstAsync(r => r.Owner.UserName == userName && r.Name == repositoryName);
|
||||
|
||||
// 获取Depot大小统计
|
||||
response.Depots = rp.Depots
|
||||
@ -204,7 +209,7 @@ public class RepositoryInnieController(
|
||||
|
||||
// 获取每日提交数量统计
|
||||
response.CommitByDay = rp.Commits
|
||||
.GroupBy(c => c.CommittedOn)
|
||||
.GroupBy(c => c.CommittedOn.Date)
|
||||
.Select(g => new RepoStatisticResponse.CommitByDayDetail
|
||||
{
|
||||
Day = g.Key,
|
||||
@ -224,7 +229,7 @@ public class RepositoryInnieController(
|
||||
var grantIssue = await ValidateRepositoryAsync(userName, repositoryName, user, RepositoryRole.Owner);
|
||||
if (grantIssue is not Repository rp) return (IActionResult) grantIssue;
|
||||
|
||||
await webhookService.AddWebhookAsync(rp, request.TargetUrl, request.EventType, request.Secret);
|
||||
await webhookService.AddWebhookAsync(rp, request.TargetUrl, (WebhookEventType) request.EventType, request.Secret);
|
||||
return Created();
|
||||
}
|
||||
|
||||
@ -236,7 +241,7 @@ public class RepositoryInnieController(
|
||||
if (grantIssue is not Repository rp) return (ActionResult) grantIssue;
|
||||
|
||||
return Ok((await webhookService.GetWebhooksAsync(rp)).Select(x => new WebhookResponse(
|
||||
x.Id, x.TargetUrl, x.EventType, x.IsActive, x.CreatedAt)));
|
||||
x.Id, x.TargetUrl, (int) x.EventType, x.IsActive, x.CreatedAt)));
|
||||
}
|
||||
|
||||
[HttpPost("webhooks/{webhookId}/toggle")]
|
||||
|
||||
@ -24,31 +24,30 @@ public class UserController(
|
||||
// Modify content
|
||||
var u = (await userManager.GetUserAsync(HttpContext.User))!;
|
||||
|
||||
if (r.NickName != null)
|
||||
if (r.NickName != u.NickName)
|
||||
{
|
||||
update = true;
|
||||
u.NickName = r.NickName;
|
||||
}
|
||||
|
||||
if (r.Bio != null)
|
||||
if (r.Bio != u.Bio)
|
||||
{
|
||||
update = true;
|
||||
u.Bio = r.Bio;
|
||||
}
|
||||
|
||||
if (r.Gender != null)
|
||||
if (r.Gender != (int) u.Gender)
|
||||
{
|
||||
update = true;
|
||||
u.Gender = r.Gender ?? UserSex.Unset;
|
||||
u.Gender = (UserSex) r.Gender;
|
||||
}
|
||||
|
||||
if (r.PublicEmail != null)
|
||||
if (r.PublicEmail != u.PublicEmail)
|
||||
{
|
||||
update = true;
|
||||
u.PublicEmail = r.PublicEmail ?? false;
|
||||
}
|
||||
|
||||
|
||||
if (renew) u.RenewSecurityStamp();
|
||||
if (update || renew) await userManager.UpdateAsync(u);
|
||||
return Ok();
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Flawless.Server.Models;
|
||||
|
||||
public class RepositoryIssue
|
||||
{
|
||||
[Key, Required]
|
||||
public ulong Id { get; set; }
|
||||
[Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Required]
|
||||
public required Repository Repository { get; set; }
|
||||
|
||||
@ -202,7 +202,7 @@ public static class Program
|
||||
if (u == null) throw new SecurityTokenExpiredException("User is not existed.");
|
||||
|
||||
if (u.SecurityStamp != stamp) throw new SecurityTokenExpiredException("SecurityStamp is mismatched.");
|
||||
// if (u.LockoutEnabled) throw new SecurityTokenExpiredException("User has been locked."); //todo Fix lockout prob
|
||||
if (u.LockoutEnabled) throw new SecurityTokenExpiredException("User has been locked.");
|
||||
}
|
||||
|
||||
// Extract user info into HttpContext
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user