From d99786799e8028b8df86d68864d9a17bfbc5c352 Mon Sep 17 00:00:00 2001 From: GZTime Date: Sun, 13 Aug 2023 23:53:51 +0800 Subject: [PATCH] fix(code style): csharp naming convention --- src/GZCTF/Controllers/AccountController.cs | 180 ++++++++-------- src/GZCTF/Controllers/AdminController.cs | 168 +++++++-------- src/GZCTF/Controllers/AssetsController.cs | 39 ++-- src/GZCTF/Controllers/EditController.cs | 188 ++++++++-------- src/GZCTF/Controllers/GameController.cs | 204 +++++++++--------- src/GZCTF/Controllers/InfoController.cs | 34 +-- src/GZCTF/Controllers/TeamController.cs | 136 ++++++------ src/GZCTF/Extensions/RecaptchaExtension.cs | 16 +- src/GZCTF/Extensions/SignalRSinkExtension.cs | 13 +- src/GZCTF/Hubs/AdminHub.cs | 7 - .../Middlewares/PrivilegeAuthentication.cs | 8 +- src/GZCTF/Pages/Error.cshtml.cs | 7 - .../Providers/EntityConfigurationProvider.cs | 44 ++-- .../Providers/EntityConfigurationSource.cs | 6 +- src/GZCTF/Repositories/ChallengeRepository.cs | 38 ++-- src/GZCTF/Repositories/CheatInfoRepository.cs | 14 +- src/GZCTF/Repositories/ContainerRepository.cs | 14 +- src/GZCTF/Repositories/FileRepository.cs | 40 ++-- src/GZCTF/Repositories/GameEventRepository.cs | 14 +- .../Repositories/GameNoticeRepository.cs | 38 ++-- src/GZCTF/Repositories/GameRepository.cs | 77 +++---- src/GZCTF/Repositories/InstanceRepository.cs | 94 ++++---- src/GZCTF/Repositories/LogRepository.cs | 4 +- .../Repositories/ParticipationRepository.cs | 36 ++-- src/GZCTF/Repositories/PostRepository.cs | 34 +-- src/GZCTF/Repositories/RepositoryBase.cs | 19 +- .../Repositories/SubmissionRepository.cs | 20 +- src/GZCTF/Repositories/TeamRepository.cs | 22 +- src/GZCTF/Services/CacheMaker.cs | 72 +++---- src/GZCTF/Services/ConfigService.cs | 32 +-- src/GZCTF/Services/CronJobService.cs | 26 +-- src/GZCTF/Services/DockerService.cs | 100 ++++----- src/GZCTF/Services/FlagChecker.cs | 62 +++--- src/GZCTF/Services/K8sService.cs | 114 +++++----- src/GZCTF/Services/MailSender.cs | 30 +-- src/GZCTF/Utils/LogHelper.cs | 32 +-- 36 files changed, 983 insertions(+), 999 deletions(-) diff --git a/src/GZCTF/Controllers/AccountController.cs b/src/GZCTF/Controllers/AccountController.cs index 69bf8e889..0ed9fc64a 100644 --- a/src/GZCTF/Controllers/AccountController.cs +++ b/src/GZCTF/Controllers/AccountController.cs @@ -21,33 +21,33 @@ namespace GZCTF.Controllers; [Produces(MediaTypeNames.Application.Json)] public class AccountController : ControllerBase { - private readonly ILogger logger; - private readonly IMailSender mailSender; - private readonly UserManager userManager; - private readonly SignInManager signInManager; - private readonly IFileRepository fileService; - private readonly IRecaptchaExtension recaptcha; - private readonly IHostEnvironment environment; - private readonly IOptionsSnapshot accountPolicy; + private readonly ILogger _logger; + private readonly IMailSender _mailSender; + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly IFileRepository _fileService; + private readonly IRecaptchaExtension _recaptcha; + private readonly IHostEnvironment _environment; + private readonly IOptionsSnapshot _accountPolicy; public AccountController( - IMailSender _mailSender, - IFileRepository _FileService, - IHostEnvironment _environment, - IRecaptchaExtension _recaptcha, - IOptionsSnapshot _accountPolicy, - UserManager _userManager, - SignInManager _signInManager, - ILogger _logger) + IMailSender mailSender, + IFileRepository fileService, + IHostEnvironment environment, + IRecaptchaExtension recaptcha, + IOptionsSnapshot accountPolicy, + UserManager userManager, + SignInManager signInManager, + ILogger logger) { - recaptcha = _recaptcha; - mailSender = _mailSender; - environment = _environment; - userManager = _userManager; - signInManager = _signInManager; - fileService = _FileService; - accountPolicy = _accountPolicy; - logger = _logger; + _recaptcha = recaptcha; + _mailSender = mailSender; + _environment = environment; + _userManager = userManager; + _signInManager = signInManager; + _fileService = fileService; + _accountPolicy = accountPolicy; + _logger = logger; } /// @@ -65,19 +65,19 @@ public AccountController( [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task Register([FromBody] RegisterModel model) { - if (!accountPolicy.Value.AllowRegister) + if (!_accountPolicy.Value.AllowRegister) return BadRequest(new RequestResponse("注册功能已禁用")); - if (accountPolicy.Value.UseGoogleRecaptcha && ( + if (_accountPolicy.Value.UseGoogleRecaptcha && ( model.GToken is null || HttpContext.Connection.RemoteIpAddress is null || - !await recaptcha.VerifyAsync(model.GToken, HttpContext.Connection.RemoteIpAddress.ToString()) + !await _recaptcha.VerifyAsync(model.GToken, HttpContext.Connection.RemoteIpAddress.ToString()) )) return BadRequest(new RequestResponse("Google reCAPTCHA 校验失败")); var mailDomain = model.Email!.Split('@')[1]; - if (!string.IsNullOrWhiteSpace(accountPolicy.Value.EmailDomainList) && - accountPolicy.Value.EmailDomainList.Split(',').All(d => d != mailDomain)) - return BadRequest(new RequestResponse($"可用邮箱后缀:{accountPolicy.Value.EmailDomainList}")); + if (!string.IsNullOrWhiteSpace(_accountPolicy.Value.EmailDomainList) && + _accountPolicy.Value.EmailDomainList.Split(',').All(d => d != mailDomain)) + return BadRequest(new RequestResponse($"可用邮箱后缀:{_accountPolicy.Value.EmailDomainList}")); var user = new UserInfo { @@ -88,48 +88,48 @@ model.GToken is null || HttpContext.Connection.RemoteIpAddress is null || user.UpdateByHttpContext(HttpContext); - var result = await userManager.CreateAsync(user, model.Password); + var result = await _userManager.CreateAsync(user, model.Password); if (!result.Succeeded) { - var current = await userManager.FindByEmailAsync(model.Email); + var current = await _userManager.FindByEmailAsync(model.Email); if (current is null) return BadRequest(new RequestResponse(result.Errors.FirstOrDefault()?.Description ?? "未知错误")); - if (await userManager.IsEmailConfirmedAsync(current)) + if (await _userManager.IsEmailConfirmedAsync(current)) return BadRequest(new RequestResponse("此账户已存在")); user = current; } - if (accountPolicy.Value.ActiveOnRegister) + if (_accountPolicy.Value.ActiveOnRegister) { user.EmailConfirmed = true; - await userManager.UpdateAsync(user); - await signInManager.SignInAsync(user, true); + await _userManager.UpdateAsync(user); + await _signInManager.SignInAsync(user, true); - logger.Log("用户成功注册", user, TaskStatus.Success); + _logger.Log("用户成功注册", user, TaskStatus.Success); return Ok(new RequestResponse("注册成功", RegisterStatus.LoggedIn, 200)); } - if (!accountPolicy.Value.EmailConfirmationRequired) + if (!_accountPolicy.Value.EmailConfirmationRequired) { - logger.Log("用户成功注册,待审核", user, TaskStatus.Success); + _logger.Log("用户成功注册,待审核", user, TaskStatus.Success); return Ok(new RequestResponse("注册成功,等待管理员审核", RegisterStatus.AdminConfirmationRequired, 200)); } - logger.Log("发送用户邮箱验证邮件", user, TaskStatus.Pending); + _logger.Log("发送用户邮箱验证邮件", user, TaskStatus.Pending); - var token = Codec.Base64.Encode(await userManager.GenerateEmailConfirmationTokenAsync(user)); - if (environment.IsDevelopment()) + var token = Codec.Base64.Encode(await _userManager.GenerateEmailConfirmationTokenAsync(user)); + if (_environment.IsDevelopment()) { - logger.Log($"http://{HttpContext.Request.Host}/account/verify?token={token}&email={Codec.Base64.Encode(model.Email)}", user, TaskStatus.Pending, LogLevel.Debug); + _logger.Log($"http://{HttpContext.Request.Host}/account/verify?token={token}&email={Codec.Base64.Encode(model.Email)}", user, TaskStatus.Pending, LogLevel.Debug); } else { - if (!mailSender.SendConfirmEmailUrl(user.UserName, user.Email, + if (!_mailSender.SendConfirmEmailUrl(user.UserName, user.Email, $"https://{HttpContext.Request.Host}/account/verify?token={token}&email={Codec.Base64.Encode(model.Email)}")) return BadRequest(new RequestResponse("邮件无法发送,请联系管理员")); } @@ -155,33 +155,33 @@ model.GToken is null || HttpContext.Connection.RemoteIpAddress is null || [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task Recovery([FromBody] RecoveryModel model) { - if (accountPolicy.Value.UseGoogleRecaptcha && ( + if (_accountPolicy.Value.UseGoogleRecaptcha && ( model.GToken is null || HttpContext.Connection.RemoteIpAddress is null || - !await recaptcha.VerifyAsync(model.GToken, HttpContext.Connection.RemoteIpAddress.ToString()) + !await _recaptcha.VerifyAsync(model.GToken, HttpContext.Connection.RemoteIpAddress.ToString()) )) return BadRequest(new RequestResponse("Google reCAPTCHA 校验失败")); - var user = await userManager.FindByEmailAsync(model.Email!); + var user = await _userManager.FindByEmailAsync(model.Email!); if (user is null) return NotFound(new RequestResponse("用户不存在", 404)); if (!user.EmailConfirmed) return NotFound(new RequestResponse("账户未激活,请重新注册", 404)); - if (!accountPolicy.Value.EmailConfirmationRequired) + if (!_accountPolicy.Value.EmailConfirmationRequired) return BadRequest(new RequestResponse("请联系管理员重置密码")); - logger.Log("发送用户密码重置邮件", HttpContext, TaskStatus.Pending); + _logger.Log("发送用户密码重置邮件", HttpContext, TaskStatus.Pending); - var token = Codec.Base64.Encode(await userManager.GeneratePasswordResetTokenAsync(user)); + var token = Codec.Base64.Encode(await _userManager.GeneratePasswordResetTokenAsync(user)); - if (environment.IsDevelopment()) + if (_environment.IsDevelopment()) { - logger.Log($"http://{HttpContext.Request.Host}/account/reset?token={token}&email={Codec.Base64.Encode(model.Email)}", user, TaskStatus.Pending, LogLevel.Debug); + _logger.Log($"http://{HttpContext.Request.Host}/account/reset?token={token}&email={Codec.Base64.Encode(model.Email)}", user, TaskStatus.Pending, LogLevel.Debug); } else { - if (!mailSender.SendResetPasswordUrl(user.UserName, user.Email, + if (!_mailSender.SendResetPasswordUrl(user.UserName, user.Email, $"https://{HttpContext.Request.Host}/account/reset?token={token}&email={Codec.Base64.Encode(model.Email)}")) return BadRequest(new RequestResponse("邮件无法发送,请联系管理员")); } @@ -204,18 +204,18 @@ model.GToken is null || HttpContext.Connection.RemoteIpAddress is null || [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task PasswordReset([FromBody] PasswordResetModel model) { - var user = await userManager.FindByEmailAsync(Codec.Base64.Decode(model.Email)); + var user = await _userManager.FindByEmailAsync(Codec.Base64.Decode(model.Email)); if (user is null) return BadRequest(new RequestResponse("无效的邮件地址")); user.UpdateByHttpContext(HttpContext); - var result = await userManager.ResetPasswordAsync(user, Codec.Base64.Decode(model.RToken), model.Password); + var result = await _userManager.ResetPasswordAsync(user, Codec.Base64.Decode(model.RToken), model.Password); if (!result.Succeeded) return BadRequest(new RequestResponse(result.Errors.FirstOrDefault()?.Description ?? "未知错误")); - logger.Log("用户成功重置密码", user, TaskStatus.Success); + _logger.Log("用户成功重置密码", user, TaskStatus.Success); return Ok(); } @@ -236,24 +236,24 @@ public async Task PasswordReset([FromBody] PasswordResetModel mod [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status401Unauthorized)] public async Task Verify([FromBody] AccountVerifyModel model) { - var user = await userManager.FindByEmailAsync(Codec.Base64.Decode(model.Email)); + var user = await _userManager.FindByEmailAsync(Codec.Base64.Decode(model.Email)); if (user is null || user.EmailConfirmed) return BadRequest(new RequestResponse("无效的邮件地址")); - var result = await userManager.ConfirmEmailAsync(user, Codec.Base64.Decode(model.Token)); + var result = await _userManager.ConfirmEmailAsync(user, Codec.Base64.Decode(model.Token)); if (!result.Succeeded) return Unauthorized(new RequestResponse("邮箱验证失败", 401)); - logger.Log("通过邮箱验证", user, TaskStatus.Success); - await signInManager.SignInAsync(user, true); + _logger.Log("通过邮箱验证", user, TaskStatus.Success); + await _signInManager.SignInAsync(user, true); user.LastSignedInUTC = DateTimeOffset.UtcNow; user.LastVisitedUTC = DateTimeOffset.UtcNow; user.RegisterTimeUTC = DateTimeOffset.UtcNow; - result = await userManager.UpdateAsync(user); + result = await _userManager.UpdateAsync(user); if (!result.Succeeded) return BadRequest(new RequestResponse(result.Errors.FirstOrDefault()?.Description ?? "未知错误")); @@ -277,8 +277,8 @@ public async Task Verify([FromBody] AccountVerifyModel model) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task LogIn([FromBody] LoginModel model) { - var user = await userManager.FindByNameAsync(model.UserName); - user ??= await userManager.FindByEmailAsync(model.UserName); + var user = await _userManager.FindByNameAsync(model.UserName); + user ??= await _userManager.FindByEmailAsync(model.UserName); if (user is null) return Unauthorized(new RequestResponse("用户名或密码错误", 401)); @@ -289,14 +289,14 @@ public async Task LogIn([FromBody] LoginModel model) user.LastSignedInUTC = DateTimeOffset.UtcNow; user.UpdateByHttpContext(HttpContext); - await signInManager.SignOutAsync(); + await _signInManager.SignOutAsync(); - var result = await signInManager.PasswordSignInAsync(user, model.Password, true, false); + var result = await _signInManager.PasswordSignInAsync(user, model.Password, true, false); if (!result.Succeeded) return Unauthorized(new RequestResponse("用户名或密码错误", 401)); - logger.Log("用户成功登录", user, TaskStatus.Success); + _logger.Log("用户成功登录", user, TaskStatus.Success); return Ok(); } @@ -314,7 +314,7 @@ public async Task LogIn([FromBody] LoginModel model) [ProducesResponseType(StatusCodes.Status200OK)] public async Task LogOut() { - await signInManager.SignOutAsync(); + await _signInManager.SignOutAsync(); return Ok(); } @@ -335,17 +335,17 @@ public async Task LogOut() [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task Update([FromBody] ProfileUpdateModel model) { - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); var oname = user!.UserName; user.UpdateUserInfo(model); - var result = await userManager.UpdateAsync(user); + var result = await _userManager.UpdateAsync(user); if (!result.Succeeded) return BadRequest(new RequestResponse(result.Errors.FirstOrDefault()?.Description ?? "未知错误")); if (oname != user.UserName) - logger.Log($"用户更新:{oname} => {model.UserName}", user, TaskStatus.Success); + _logger.Log($"用户更新:{oname} => {model.UserName}", user, TaskStatus.Success); return Ok(); } @@ -366,13 +366,13 @@ public async Task Update([FromBody] ProfileUpdateModel model) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status401Unauthorized)] public async Task ChangePassword([FromBody] PasswordChangeModel model) { - var user = await userManager.GetUserAsync(User); - var result = await userManager.ChangePasswordAsync(user!, model.Old, model.New); + var user = await _userManager.GetUserAsync(User); + var result = await _userManager.ChangePasswordAsync(user!, model.Old, model.New); if (!result.Succeeded) return BadRequest(new RequestResponse(result.Errors.FirstOrDefault()?.Description ?? "未知错误")); - logger.Log("用户更新密码", user, TaskStatus.Success); + _logger.Log("用户更新密码", user, TaskStatus.Success); return Ok(); } @@ -395,25 +395,25 @@ public async Task ChangePassword([FromBody] PasswordChangeModel m [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status401Unauthorized)] public async Task ChangeEmail([FromBody] MailChangeModel model) { - if (await userManager.FindByEmailAsync(model.NewMail) is not null) + if (await _userManager.FindByEmailAsync(model.NewMail) is not null) return BadRequest(new RequestResponse("邮箱已经被占用")); - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); - if (!accountPolicy.Value.EmailConfirmationRequired) + if (!_accountPolicy.Value.EmailConfirmationRequired) return BadRequest(new RequestResponse("请联系管理员修改邮箱", false)); - logger.Log("发送用户邮箱更改邮件", user, TaskStatus.Pending); + _logger.Log("发送用户邮箱更改邮件", user, TaskStatus.Pending); - var token = Codec.Base64.Encode(await userManager.GenerateChangeEmailTokenAsync(user!, model.NewMail)); + var token = Codec.Base64.Encode(await _userManager.GenerateChangeEmailTokenAsync(user!, model.NewMail)); - if (environment.IsDevelopment()) + if (_environment.IsDevelopment()) { - logger.Log($"http://{HttpContext.Request.Host}/account/confirm?token={token}&email={Codec.Base64.Encode(model.NewMail)}", user, TaskStatus.Pending, LogLevel.Debug); + _logger.Log($"http://{HttpContext.Request.Host}/account/confirm?token={token}&email={Codec.Base64.Encode(model.NewMail)}", user, TaskStatus.Pending, LogLevel.Debug); } else { - if (!mailSender.SendConfirmEmailUrl(user!.UserName, user.Email, + if (!_mailSender.SendConfirmEmailUrl(user!.UserName, user.Email, $"https://{HttpContext.Request.Host}/account/confirm?token={token}&email={Codec.Base64.Encode(model.NewMail)}")) return BadRequest(new RequestResponse("邮件无法发送,请联系管理员")); } @@ -439,13 +439,13 @@ public async Task ChangeEmail([FromBody] MailChangeModel model) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status401Unauthorized)] public async Task MailChangeConfirm([FromBody] AccountVerifyModel model) { - var user = await userManager.GetUserAsync(User); - var result = await userManager.ChangeEmailAsync(user!, Codec.Base64.Decode(model.Email), Codec.Base64.Decode(model.Token)); + var user = await _userManager.GetUserAsync(User); + var result = await _userManager.ChangeEmailAsync(user!, Codec.Base64.Decode(model.Email), Codec.Base64.Decode(model.Token)); if (!result.Succeeded) return BadRequest(new RequestResponse("无效邮箱")); - logger.Log("更改邮箱成功", user, TaskStatus.Success); + _logger.Log("更改邮箱成功", user, TaskStatus.Success); return Ok(); } @@ -465,7 +465,7 @@ public async Task MailChangeConfirm([FromBody] AccountVerifyModel [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task Profile() { - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); return Ok(ProfileUserInfoModel.FromUserInfo(user!)); } @@ -492,23 +492,23 @@ public async Task Avatar(IFormFile file, CancellationToken token) if (file.Length > 3 * 1024 * 1024) return BadRequest(new RequestResponse("文件过大")); - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); if (user!.AvatarHash is not null) - await fileService.DeleteFileByHash(user.AvatarHash, token); + await _fileService.DeleteFileByHash(user.AvatarHash, token); - var avatar = await fileService.CreateOrUpdateImage(file, "avatar", token); + var avatar = await _fileService.CreateOrUpdateImage(file, "avatar", token); if (avatar is null) return BadRequest(new RequestResponse("用户头像更新失败")); user.AvatarHash = avatar.Hash; - var result = await userManager.UpdateAsync(user); + var result = await _userManager.UpdateAsync(user); if (result != IdentityResult.Success) return BadRequest(new RequestResponse("用户更新失败")); - logger.Log($"更改新头像:[{avatar.Hash[..8]}]", user, TaskStatus.Success); + _logger.Log($"更改新头像:[{avatar.Hash[..8]}]", user, TaskStatus.Success); return Ok(avatar.Url()); } diff --git a/src/GZCTF/Controllers/AdminController.cs b/src/GZCTF/Controllers/AdminController.cs index 84c964879..7139b5663 100644 --- a/src/GZCTF/Controllers/AdminController.cs +++ b/src/GZCTF/Controllers/AdminController.cs @@ -26,44 +26,44 @@ namespace GZCTF.Controllers; [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public class AdminController : ControllerBase { - private readonly ILogger logger; - private readonly UserManager userManager; - private readonly ILogRepository logRepository; - private readonly IFileRepository fileService; - private readonly IConfigService configService; - private readonly IGameRepository gameRepository; - private readonly ITeamRepository teamRepository; - private readonly IServiceProvider serviceProvider; - private readonly IContainerRepository containerRepository; - private readonly IInstanceRepository instanceRepository; - private readonly IParticipationRepository participationRepository; - private readonly string basepath; - - public AdminController(UserManager _userManager, - ILogger _logger, - IFileRepository _FileService, - ILogRepository _logRepository, - IConfigService _configService, - IGameRepository _gameRepository, - ITeamRepository _teamRepository, - IInstanceRepository _instanceRepository, - IContainerRepository _containerRepository, - IServiceProvider _serviceProvider, - IConfiguration _configuration, - IParticipationRepository _participationRepository) + private readonly ILogger _logger; + private readonly UserManager _userManager; + private readonly ILogRepository _logRepository; + private readonly IFileRepository _fileService; + private readonly IConfigService _configService; + private readonly IGameRepository _gameRepository; + private readonly ITeamRepository _teamRepository; + private readonly IServiceProvider _serviceProvider; + private readonly IContainerRepository _containerRepository; + private readonly IInstanceRepository _instanceRepository; + private readonly IParticipationRepository _participationRepository; + private readonly string _basepath; + + public AdminController(UserManager userManager, + ILogger logger, + IFileRepository fileService, + ILogRepository logRepository, + IConfigService configService, + IGameRepository gameRepository, + ITeamRepository teamRepository, + IInstanceRepository instanceRepository, + IContainerRepository containerRepository, + IServiceProvider serviceProvider, + IConfiguration configuration, + IParticipationRepository participationRepository) { - logger = _logger; - userManager = _userManager; - fileService = _FileService; - configService = _configService; - logRepository = _logRepository; - teamRepository = _teamRepository; - gameRepository = _gameRepository; - instanceRepository = _instanceRepository; - containerRepository = _containerRepository; - serviceProvider = _serviceProvider; - participationRepository = _participationRepository; - basepath = _configuration.GetSection("UploadFolder").Value ?? "uploads"; + _logger = logger; + _userManager = userManager; + _fileService = fileService; + _configService = configService; + _logRepository = logRepository; + _teamRepository = teamRepository; + _gameRepository = gameRepository; + _instanceRepository = instanceRepository; + _containerRepository = containerRepository; + _serviceProvider = serviceProvider; + _participationRepository = participationRepository; + _basepath = configuration.GetSection("UploadFolder").Value ?? "uploads"; } /// @@ -80,13 +80,13 @@ public AdminController(UserManager _userManager, public IActionResult GetConfigs() { // always reload, ensure latest - configService.ReloadConfig(); + _configService.ReloadConfig(); ConfigEditModel config = new() { - AccountPolicy = serviceProvider.GetRequiredService>().Value, - GlobalConfig = serviceProvider.GetRequiredService>().Value, - GamePolicy = serviceProvider.GetRequiredService>().Value + AccountPolicy = _serviceProvider.GetRequiredService>().Value, + GlobalConfig = _serviceProvider.GetRequiredService>().Value, + GamePolicy = _serviceProvider.GetRequiredService>().Value }; return Ok(config); @@ -109,7 +109,7 @@ public async Task UpdateConfigs([FromBody] ConfigEditModel model, { var value = prop.GetValue(model); if (value is not null) - await configService.SaveConfig(prop.PropertyType, value, token); + await _configService.SaveConfig(prop.PropertyType, value, token); } return Ok(); @@ -128,9 +128,9 @@ public async Task UpdateConfigs([FromBody] ConfigEditModel model, [ProducesResponseType(typeof(ArrayResponse), StatusCodes.Status200OK)] public async Task Users([FromQuery] int count = 100, [FromQuery] int skip = 0, CancellationToken token = default) => Ok((await ( - from user in userManager.Users.OrderBy(e => e.Id).Skip(skip).Take(count) + from user in _userManager.Users.OrderBy(e => e.Id).Skip(skip).Take(count) select UserInfoModel.FromUserInfo(user) - ).ToArrayAsync(token)).ToResponse(await userManager.Users.CountAsync(token))); + ).ToArrayAsync(token)).ToResponse(await _userManager.Users.CountAsync(token))); /// /// 批量添加用户 @@ -147,8 +147,8 @@ select UserInfoModel.FromUserInfo(user) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task AddUsers([FromBody] UserCreateModel[] model, CancellationToken token = default) { - var currentUser = await userManager.GetUserAsync(User); - var trans = await teamRepository.BeginTransactionAsync(token); + var currentUser = await _userManager.GetUserAsync(User); + var trans = await _teamRepository.BeginTransactionAsync(token); try { @@ -156,17 +156,17 @@ public async Task AddUsers([FromBody] UserCreateModel[] model, Ca foreach (var user in model) { var userInfo = user.ToUserInfo(); - var result = await userManager.CreateAsync(userInfo, user.Password); + var result = await _userManager.CreateAsync(userInfo, user.Password); if (!result.Succeeded) { switch (result.Errors.FirstOrDefault()?.Code) { case "DuplicateEmail": - userInfo = await userManager.FindByEmailAsync(user.Email); + userInfo = await _userManager.FindByEmailAsync(user.Email); break; case "DuplicateUserName": - userInfo = await userManager.FindByNameAsync(user.UserName); + userInfo = await _userManager.FindByNameAsync(user.UserName); break; default: await trans.RollbackAsync(token); @@ -176,8 +176,8 @@ public async Task AddUsers([FromBody] UserCreateModel[] model, Ca if (userInfo is not null) { userInfo.UpdateUserInfo(user); - var code = await userManager.GeneratePasswordResetTokenAsync(userInfo); - result = await userManager.ResetPasswordAsync(userInfo, code, user.Password); + var code = await _userManager.GeneratePasswordResetTokenAsync(userInfo); + result = await _userManager.ResetPasswordAsync(userInfo, code, user.Password); } if (!result.Succeeded || userInfo is null) @@ -199,7 +199,7 @@ public async Task AddUsers([FromBody] UserCreateModel[] model, Ca var team = teams.Find(team => team.Name == teamName); if (team is null) { - team = await teamRepository.CreateTeam(new(teamName), user, token); + team = await _teamRepository.CreateTeam(new(teamName), user, token); teams.Add(team!); } else @@ -208,10 +208,10 @@ public async Task AddUsers([FromBody] UserCreateModel[] model, Ca } } - await teamRepository.SaveAsync(token); + await _teamRepository.SaveAsync(token); await trans.CommitAsync(token); - logger.Log($"成功批量添加 {users.Count} 个用户", currentUser, TaskStatus.Success); + _logger.Log($"成功批量添加 {users.Count} 个用户", currentUser, TaskStatus.Success); return Ok(); } @@ -235,7 +235,7 @@ public async Task AddUsers([FromBody] UserCreateModel[] model, Ca [ProducesResponseType(typeof(ArrayResponse), StatusCodes.Status200OK)] public async Task SearchUsers([FromQuery] string hint, CancellationToken token = default) => Ok((await ( - from user in userManager.Users + from user in _userManager.Users .Where(item => EF.Functions.Like(item.UserName!, $"%{hint}%") || EF.Functions.Like(item.StdNumber, $"%{hint}%") || @@ -259,9 +259,9 @@ select UserInfoModel.FromUserInfo(user) [HttpGet("Teams")] [ProducesResponseType(typeof(ArrayResponse), StatusCodes.Status200OK)] public async Task Teams([FromQuery] int count = 100, [FromQuery] int skip = 0, CancellationToken token = default) - => Ok((await teamRepository.GetTeams(count, skip, token)) + => Ok((await _teamRepository.GetTeams(count, skip, token)) .Select(team => TeamInfoModel.FromTeam(team)) - .ToResponse(await teamRepository.CountAsync(token))); + .ToResponse(await _teamRepository.CountAsync(token))); /// /// 搜索队伍 @@ -275,7 +275,7 @@ public async Task Teams([FromQuery] int count = 100, [FromQuery] [HttpPost("Teams/Search")] [ProducesResponseType(typeof(ArrayResponse), StatusCodes.Status200OK)] public async Task SearchTeams([FromQuery] string hint, CancellationToken token = default) - => Ok((await teamRepository.SearchTeams(hint, token)) + => Ok((await _teamRepository.SearchTeams(hint, token)) .Select(team => TeamInfoModel.FromTeam(team)) .ToResponse()); @@ -294,13 +294,13 @@ public async Task SearchTeams([FromQuery] string hint, Cancellati [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UpdateTeam([FromRoute] int id, [FromBody] AdminTeamModel model, CancellationToken token = default) { - var team = await teamRepository.GetTeamById(id, token); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); team.UpdateInfo(model); - await teamRepository.SaveAsync(token); + await _teamRepository.SaveAsync(token); return Ok(); } @@ -320,13 +320,13 @@ public async Task UpdateTeam([FromRoute] int id, [FromBody] Admin [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UpdateUserInfo(string userid, [FromBody] AdminUserInfoModel model) { - var user = await userManager.FindByIdAsync(userid); + var user = await _userManager.FindByIdAsync(userid); if (user is null) return NotFound(new RequestResponse("用户未找到", 404)); user.UpdateUserInfo(model); - await userManager.UpdateAsync(user); + await _userManager.UpdateAsync(user); return Ok(); } @@ -346,14 +346,14 @@ public async Task UpdateUserInfo(string userid, [FromBody] AdminU [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task ResetPassword(string userid, CancellationToken token = default) { - var user = await userManager.FindByIdAsync(userid); + var user = await _userManager.FindByIdAsync(userid); if (user is null) return NotFound(new RequestResponse("用户未找到", 404)); var pwd = Codec.RandomPassword(16); - var code = await userManager.GeneratePasswordResetTokenAsync(user); - await userManager.ResetPasswordAsync(user, code, pwd); + var code = await _userManager.GeneratePasswordResetTokenAsync(user); + await _userManager.ResetPasswordAsync(user, code, pwd); return Ok(pwd); } @@ -373,20 +373,20 @@ public async Task ResetPassword(string userid, CancellationToken [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DeleteUser(string userid, CancellationToken token = default) { - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); if (user!.Id == userid) return BadRequest(new RequestResponse("不可以删除自己")); - user = await userManager.FindByIdAsync(userid); + user = await _userManager.FindByIdAsync(userid); if (user is null) return NotFound(new RequestResponse("用户未找到", 404)); - if (await teamRepository.CheckIsCaptain(user, token)) + if (await _teamRepository.CheckIsCaptain(user, token)) return BadRequest(new RequestResponse("不可以删除队长")); - await userManager.DeleteAsync(user); + await _userManager.DeleteAsync(user); return Ok(); } @@ -406,12 +406,12 @@ public async Task DeleteUser(string userid, CancellationToken tok [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DeleteTeam(int id, CancellationToken token = default) { - var team = await teamRepository.GetTeamById(id, token); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return NotFound(new RequestResponse("队伍未找到", 404)); - await teamRepository.DeleteTeam(team, token); + await _teamRepository.DeleteTeam(team, token); return Ok(); } @@ -430,7 +430,7 @@ public async Task DeleteTeam(int id, CancellationToken token = de [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UserInfo(string userid) { - var user = await userManager.FindByIdAsync(userid); + var user = await _userManager.FindByIdAsync(userid); if (user is null) return NotFound(new RequestResponse("用户未找到", 404)); @@ -450,7 +450,7 @@ public async Task UserInfo(string userid) [HttpGet("Logs")] [ProducesResponseType(typeof(LogMessageModel[]), StatusCodes.Status200OK)] public async Task Logs([FromQuery] string? level = "All", [FromQuery] int count = 50, [FromQuery] int skip = 0, CancellationToken token = default) - => Ok(await logRepository.GetLogs(skip, count, level, token)); + => Ok(await _logRepository.GetLogs(skip, count, level, token)); /// /// 更新参与状态 @@ -467,12 +467,12 @@ public async Task Logs([FromQuery] string? level = "All", [FromQu [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task Participation(int id, ParticipationStatus status, CancellationToken token = default) { - var participation = await participationRepository.GetParticipationById(id, token); + var participation = await _participationRepository.GetParticipationById(id, token); if (participation is null) return NotFound(new RequestResponse("参与状态未找到", 404)); - await participationRepository.UpdateParticipationStatus(participation, status, token); + await _participationRepository.UpdateParticipationStatus(participation, status, token); return Ok(); } @@ -492,12 +492,12 @@ public async Task Participation(int id, ParticipationStatus statu [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task Writeups(int id, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - return Ok(await participationRepository.GetWriteups(game, token)); + return Ok(await _participationRepository.GetWriteups(game, token)); } /// @@ -515,14 +515,14 @@ public async Task Writeups(int id, CancellationToken token = defa [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DownloadAllWriteups(int id, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var wps = await participationRepository.GetWriteups(game, token); + var wps = await _participationRepository.GetWriteups(game, token); var filename = $"Writeups-{game.Title}-{DateTimeOffset.UtcNow:yyyyMMdd-HH.mm.ssZ}"; - var stream = await Codec.ZipFilesAsync(wps.Select(p => p.File), basepath, filename, token); + var stream = await Codec.ZipFilesAsync(wps.Select(p => p.File), _basepath, filename, token); stream.Seek(0, SeekOrigin.Begin); return File(stream, "application/zip", $"{filename}.zip"); @@ -540,7 +540,7 @@ public async Task DownloadAllWriteups(int id, CancellationToken t [HttpGet("Instances")] [ProducesResponseType(typeof(ArrayResponse), StatusCodes.Status200OK)] public async Task Instances(CancellationToken token = default) - => Ok(new ArrayResponse(await containerRepository.GetContainerInstances(token))); + => Ok(new ArrayResponse(await _containerRepository.GetContainerInstances(token))); /// /// 删除容器实例 @@ -559,12 +559,12 @@ public async Task Instances(CancellationToken token = default) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DestroyInstance(string id, CancellationToken token = default) { - var container = await containerRepository.GetContainerById(id, token); + var container = await _containerRepository.GetContainerById(id, token); if (container is null) return NotFound(new RequestResponse("容器实例未找到", 404)); - if (await instanceRepository.DestroyContainer(container, token)) + if (await _instanceRepository.DestroyContainer(container, token)) return Ok(); else return BadRequest(new RequestResponse("容器实例销毁失败", 404)); @@ -582,5 +582,5 @@ public async Task DestroyInstance(string id, CancellationToken to [HttpGet("Files")] [ProducesResponseType(typeof(ArrayResponse), StatusCodes.Status200OK)] public async Task Files([FromQuery] int count = 50, [FromQuery] int skip = 0, CancellationToken token = default) - => Ok(new ArrayResponse(await fileService.GetFiles(count, skip, token))); + => Ok(new ArrayResponse(await _fileService.GetFiles(count, skip, token))); } diff --git a/src/GZCTF/Controllers/AssetsController.cs b/src/GZCTF/Controllers/AssetsController.cs index dd8b98631..0d43b7a32 100644 --- a/src/GZCTF/Controllers/AssetsController.cs +++ b/src/GZCTF/Controllers/AssetsController.cs @@ -16,20 +16,19 @@ namespace GZCTF.Controllers; [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public class AssetsController : ControllerBase { - private readonly ILogger logger; - private readonly IFileRepository fileRepository; - private readonly IConfiguration configuration; - private readonly string basepath; - private readonly FileExtensionContentTypeProvider extProvider = new(); + private readonly ILogger _logger; + private readonly IFileRepository _fileRepository; + private readonly FileExtensionContentTypeProvider _extProvider = new(); - public AssetsController(IFileRepository _fileeService, - IConfiguration _configuration, - ILogger _logger) + private readonly string _basepath; + + public AssetsController(IFileRepository fileeService, + IConfiguration configuration, + ILogger logger) { - fileRepository = _fileeService; - configuration = _configuration; - logger = _logger; - basepath = configuration.GetSection("UploadFolder").Value ?? "uploads"; + _fileRepository = fileeService; + _logger = logger; + _basepath = configuration.GetSection("UploadFolder").Value ?? "uploads"; } /// @@ -49,15 +48,15 @@ public AssetsController(IFileRepository _fileeService, public IActionResult GetFile([RegularExpression("[0-9a-f]{64}")] string hash, string filename) { var path = $"{hash[..2]}/{hash[2..4]}/{hash}"; - path = Path.GetFullPath(Path.Combine(basepath, path)); + path = Path.GetFullPath(Path.Combine(_basepath, path)); if (!System.IO.File.Exists(path)) { - logger.Log($"尝试获取不存在的文件 [{hash[..8]}] {filename}", HttpContext.Connection?.RemoteIpAddress?.ToString() ?? "0.0.0.0", TaskStatus.NotFound, LogLevel.Warning); + _logger.Log($"尝试获取不存在的文件 [{hash[..8]}] {filename}", HttpContext.Connection?.RemoteIpAddress?.ToString() ?? "0.0.0.0", TaskStatus.NotFound, LogLevel.Warning); return NotFound(new RequestResponse("文件不存在", 404)); } - if (!extProvider.TryGetContentType(filename, out string? contentType)) + if (!_extProvider.TryGetContentType(filename, out string? contentType)) contentType = MediaTypeNames.Application.Octet; return new PhysicalFileResult(path, contentType) @@ -92,8 +91,8 @@ public async Task Upload(List files, [FromQuery] strin { if (file.Length > 0) { - var res = await fileRepository.CreateOrUpdateFile(file, filename, token); - logger.SystemLog($"更新文件 [{res.Hash[..8]}] {filename ?? file.FileName} @ {file.Length} bytes", TaskStatus.Success, LogLevel.Debug); + var res = await _fileRepository.CreateOrUpdateFile(file, filename, token); + _logger.SystemLog($"更新文件 [{res.Hash[..8]}] {filename ?? file.FileName} @ {file.Length} bytes", TaskStatus.Success, LogLevel.Debug); results.Add(res); } } @@ -101,7 +100,7 @@ public async Task Upload(List files, [FromQuery] strin } catch (Exception ex) { - logger.LogError(ex, ex.Message); + _logger.LogError(ex, ex.Message); return BadRequest(new RequestResponse("遇到IO错误")); } } @@ -125,9 +124,9 @@ public async Task Upload(List files, [FromQuery] strin [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task Delete(string hash, CancellationToken token) { - var result = await fileRepository.DeleteFileByHash(hash, token); + var result = await _fileRepository.DeleteFileByHash(hash, token); - logger.SystemLog($"删除文件 [{hash[..8]}]...", result, LogLevel.Information); + _logger.SystemLog($"删除文件 [{hash[..8]}]...", result, LogLevel.Information); return result switch { diff --git a/src/GZCTF/Controllers/EditController.cs b/src/GZCTF/Controllers/EditController.cs index 4a9c620f2..c075e76a1 100644 --- a/src/GZCTF/Controllers/EditController.cs +++ b/src/GZCTF/Controllers/EditController.cs @@ -23,35 +23,35 @@ namespace GZCTF.Controllers; [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public class EditController : Controller { - private readonly ILogger logger; - private readonly UserManager userManager; - private readonly IPostRepository postRepository; - private readonly IGameNoticeRepository gameNoticeRepository; - private readonly IGameRepository gameRepository; - private readonly IChallengeRepository challengeRepository; - private readonly IFileRepository fileService; - private readonly IContainerService containerService; - private readonly IContainerRepository containerRepository; - - public EditController(UserManager _userManager, - ILogger _logger, - IPostRepository _postRepository, - IContainerRepository _containerRepository, - IChallengeRepository _challengeRepository, - IGameNoticeRepository _gameNoticeRepository, - IGameRepository _gameRepository, - IContainerService _containerService, - IFileRepository _fileService) + private readonly ILogger _logger; + private readonly UserManager _userManager; + private readonly IPostRepository _postRepository; + private readonly IGameNoticeRepository _gameNoticeRepository; + private readonly IGameRepository _gameRepository; + private readonly IChallengeRepository _challengeRepository; + private readonly IFileRepository _fileService; + private readonly IContainerService _containerService; + private readonly IContainerRepository _containerRepository; + + public EditController(UserManager userManager, + ILogger logger, + IPostRepository postRepository, + IContainerRepository containerRepository, + IChallengeRepository challengeRepository, + IGameNoticeRepository gameNoticeRepository, + IGameRepository gameRepository, + IContainerService containerService, + IFileRepository fileService) { - logger = _logger; - fileService = _fileService; - userManager = _userManager; - gameRepository = _gameRepository; - postRepository = _postRepository; - containerService = _containerService; - challengeRepository = _challengeRepository; - containerRepository = _containerRepository; - gameNoticeRepository = _gameNoticeRepository; + _logger = logger; + _fileService = fileService; + _userManager = userManager; + _gameRepository = gameRepository; + _postRepository = postRepository; + _containerService = containerService; + _challengeRepository = challengeRepository; + _containerRepository = containerRepository; + _gameNoticeRepository = gameNoticeRepository; } /// @@ -67,8 +67,8 @@ public EditController(UserManager _userManager, [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] public async Task AddPost([FromBody] PostEditModel model, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var res = await postRepository.CreatePost(new Post().Update(model, user!), token); + var user = await _userManager.GetUserAsync(User); + var res = await _postRepository.CreatePost(new Post().Update(model, user!), token); return Ok(res.Id); } @@ -88,14 +88,14 @@ public async Task AddPost([FromBody] PostEditModel model, Cancell [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UpdatePost(string id, [FromBody] PostEditModel model, CancellationToken token) { - var post = await postRepository.GetPostById(id, token); + var post = await _postRepository.GetPostById(id, token); if (post is null) return NotFound(new RequestResponse("文章未找到", 404)); - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); - await postRepository.UpdatePost(post.Update(model, user!), token); + await _postRepository.UpdatePost(post.Update(model, user!), token); return Ok(PostDetailModel.FromPost(post)); } @@ -115,12 +115,12 @@ public async Task UpdatePost(string id, [FromBody] PostEditModel [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DeletePost(string id, CancellationToken token) { - var post = await postRepository.GetPostById(id, token); + var post = await _postRepository.GetPostById(id, token); if (post is null) return NotFound(new RequestResponse("文章未找到", 404)); - await postRepository.RemovePost(post, token); + await _postRepository.RemovePost(post, token); return Ok(); } @@ -139,12 +139,12 @@ public async Task DeletePost(string id, CancellationToken token) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task AddGame([FromBody] GameInfoModel model, CancellationToken token) { - var game = await gameRepository.CreateGame(new Game().Update(model), token); + var game = await _gameRepository.CreateGame(new Game().Update(model), token); if (game is null) return BadRequest(new RequestResponse("比赛创建失败", 400)); - gameRepository.FlushGameInfoCache(); + _gameRepository.FlushGameInfoCache(); return Ok(GameInfoModel.FromGame(game)); } @@ -162,9 +162,9 @@ public async Task AddGame([FromBody] GameInfoModel model, Cancell [HttpGet("Games")] [ProducesResponseType(typeof(ArrayResponse), StatusCodes.Status200OK)] public async Task GetGames([FromQuery] int count, [FromQuery] int skip, CancellationToken token) - => Ok((await gameRepository.GetGames(count, skip, token)) + => Ok((await _gameRepository.GetGames(count, skip, token)) .Select(GameInfoModel.FromGame) - .ToResponse(await gameRepository.CountAsync(token))); + .ToResponse(await _gameRepository.CountAsync(token))); /// /// 获取比赛 @@ -180,7 +180,7 @@ public async Task GetGames([FromQuery] int count, [FromQuery] int [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task GetGame([FromRoute] int id, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); @@ -202,7 +202,7 @@ public async Task GetGame([FromRoute] int id, CancellationToken t [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task GetTeamHashSalt([FromRoute] int id, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); @@ -227,15 +227,15 @@ public async Task GetTeamHashSalt([FromRoute] int id, Cancellatio [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UpdateGame([FromRoute] int id, [FromBody] GameInfoModel model, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); game.Update(model); - await gameRepository.SaveAsync(token); - gameRepository.FlushGameInfoCache(); - await gameRepository.FlushScoreboardCache(game.Id, token); + await _gameRepository.SaveAsync(token); + _gameRepository.FlushGameInfoCache(); + await _gameRepository.FlushScoreboardCache(game.Id, token); return Ok(GameInfoModel.FromGame(game)); } @@ -254,12 +254,12 @@ public async Task UpdateGame([FromRoute] int id, [FromBody] GameI [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DeleteGame([FromRoute] int id, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - await gameRepository.DeleteGame(game, token); + await _gameRepository.DeleteGame(game, token); return Ok(); } @@ -285,19 +285,19 @@ public async Task UpdateGamePoster([FromRoute] int id, IFormFile if (file.Length > 3 * 1024 * 1024) return BadRequest(new RequestResponse("文件过大")); - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var poster = await fileService.CreateOrUpdateImage(file, "poster", token, 0); + var poster = await _fileService.CreateOrUpdateImage(file, "poster", token, 0); if (poster is null) return BadRequest(new RequestResponse("文件创建失败")); game.PosterHash = poster.Hash; - await gameRepository.SaveAsync(token); - gameRepository.FlushGameInfoCache(); + await _gameRepository.SaveAsync(token); + _gameRepository.FlushGameInfoCache(); return Ok(poster.Url()); } @@ -317,12 +317,12 @@ public async Task UpdateGamePoster([FromRoute] int id, IFormFile [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task AddGameNotice([FromRoute] int id, [FromBody] GameNoticeModel model, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var res = await gameNoticeRepository.AddNotice(new() + var res = await _gameNoticeRepository.AddNotice(new() { Content = model.Content, GameId = game.Id, @@ -347,12 +347,12 @@ public async Task AddGameNotice([FromRoute] int id, [FromBody] Ga [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task GetGameNotices([FromRoute] int id, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - return Ok(await gameNoticeRepository.GetNormalNotices(id, token)); + return Ok(await _gameNoticeRepository.GetNormalNotices(id, token)); } /// @@ -371,7 +371,7 @@ public async Task GetGameNotices([FromRoute] int id, Cancellation [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UpdateGameNotice([FromRoute] int id, [FromRoute] int noticeId, [FromBody] GameNoticeModel model, CancellationToken token = default) { - var notice = await gameNoticeRepository.GetNoticeById(id, noticeId, token); + var notice = await _gameNoticeRepository.GetNoticeById(id, noticeId, token); if (notice is null) return NotFound(new RequestResponse("通知未找到", 404)); @@ -380,7 +380,7 @@ public async Task UpdateGameNotice([FromRoute] int id, [FromRoute return BadRequest(new RequestResponse("不能更改系统通知")); notice.Content = model.Content; - return Ok(await gameNoticeRepository.UpdateNotice(notice, token)); + return Ok(await _gameNoticeRepository.UpdateNotice(notice, token)); } /// @@ -399,7 +399,7 @@ public async Task UpdateGameNotice([FromRoute] int id, [FromRoute [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DeleteGameNotice([FromRoute] int id, [FromRoute] int noticeId, CancellationToken token) { - var notice = await gameNoticeRepository.GetNoticeById(id, noticeId, token); + var notice = await _gameNoticeRepository.GetNoticeById(id, noticeId, token); if (notice is null) return NotFound(new RequestResponse("通知未找到", 404)); @@ -407,7 +407,7 @@ public async Task DeleteGameNotice([FromRoute] int id, [FromRoute if (notice.Type != NoticeType.Normal) return BadRequest(new RequestResponse("不能删除系统通知")); - await gameNoticeRepository.RemoveNotice(notice, token); + await _gameNoticeRepository.RemoveNotice(notice, token); return Ok(); } @@ -427,12 +427,12 @@ public async Task DeleteGameNotice([FromRoute] int id, [FromRoute [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task AddGameChallenge([FromRoute] int id, [FromBody] ChallengeInfoModel model, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var res = await challengeRepository.CreateChallenge(game, new Challenge() + var res = await _challengeRepository.CreateChallenge(game, new Challenge() { Title = model.Title, Type = model.Type, @@ -454,7 +454,7 @@ public async Task AddGameChallenge([FromRoute] int id, [FromBody] [HttpGet("Games/{id}/Challenges")] [ProducesResponseType(typeof(ChallengeInfoModel[]), StatusCodes.Status200OK)] public async Task GetGameChallenges([FromRoute] int id, CancellationToken token) - => Ok((await challengeRepository.GetChallenges(id, token)).Select(ChallengeInfoModel.FromChallenge)); + => Ok((await _challengeRepository.GetChallenges(id, token)).Select(ChallengeInfoModel.FromChallenge)); /// /// 获取比赛题目 @@ -471,12 +471,12 @@ public async Task GetGameChallenges([FromRoute] int id, Cancellat [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task GetGameChallenge([FromRoute] int id, [FromRoute] int cId, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var res = await challengeRepository.GetChallenge(id, cId, true, token); + var res = await _challengeRepository.GetChallenge(id, cId, true, token); if (res is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -500,12 +500,12 @@ public async Task GetGameChallenge([FromRoute] int id, [FromRoute [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UpdateGameChallenge([FromRoute] int id, [FromRoute] int cId, [FromBody] ChallengeUpdateModel model, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var res = await challengeRepository.GetChallenge(id, cId, true, token); + var res = await _challengeRepository.GetChallenge(id, cId, true, token); if (res is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -527,11 +527,11 @@ public async Task UpdateGameChallenge([FromRoute] int id, [FromRo if (model.IsEnabled == true) { // will also update IsEnabled - await challengeRepository.EnsureInstances(res, game, token); + await _challengeRepository.EnsureInstances(res, game, token); if (game.IsActive) { - await gameNoticeRepository.AddNotice(new() + await _gameNoticeRepository.AddNotice(new() { Game = game, Type = NoticeType.NewChallenge, @@ -540,11 +540,11 @@ await gameNoticeRepository.AddNotice(new() } } else - await challengeRepository.SaveAsync(token); + await _challengeRepository.SaveAsync(token); if (game.IsActive && res.IsEnabled && hintUpdated) { - await gameNoticeRepository.AddNotice(new() + await _gameNoticeRepository.AddNotice(new() { Game = game, Type = NoticeType.NewHint, @@ -553,7 +553,7 @@ await gameNoticeRepository.AddNotice(new() } // always flush scoreboard - await gameRepository.FlushScoreboardCache(game.Id, token); + await _gameRepository.FlushScoreboardCache(game.Id, token); return Ok(ChallengeEditDetailModel.FromChallenge(res)); } @@ -573,12 +573,12 @@ await gameNoticeRepository.AddNotice(new() [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task CreateTestContainer([FromRoute] int id, [FromRoute] int cId, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var challenge = await challengeRepository.GetChallenge(id, cId, true, token); + var challenge = await _challengeRepository.GetChallenge(id, cId, true, token); if (challenge is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -589,9 +589,9 @@ public async Task CreateTestContainer([FromRoute] int id, [FromRo if (challenge.ContainerImage is null || challenge.ContainerExposePort is null) return BadRequest(new RequestResponse("容器配置错误")); - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); - var container = await containerService.CreateContainerAsync(new() + var container = await _containerService.CreateContainerAsync(new() { TeamId = "admin", UserId = user!.Id, @@ -607,9 +607,9 @@ public async Task CreateTestContainer([FromRoute] int id, [FromRo return BadRequest(new RequestResponse("容器创建失败")); challenge.TestContainer = container; - await challengeRepository.SaveAsync(token); + await _challengeRepository.SaveAsync(token); - logger.Log($"成功创建测试容器 {container.ContainerId}", user, TaskStatus.Success); + _logger.Log($"成功创建测试容器 {container.ContainerId}", user, TaskStatus.Success); return Ok(ContainerInfoModel.FromContainer(container)); } @@ -629,12 +629,12 @@ public async Task CreateTestContainer([FromRoute] int id, [FromRo [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task DestroyTestContainer([FromRoute] int id, [FromRoute] int cId, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var challenge = await challengeRepository.GetChallenge(id, cId, true, token); + var challenge = await _challengeRepository.GetChallenge(id, cId, true, token); if (challenge is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -642,8 +642,8 @@ public async Task DestroyTestContainer([FromRoute] int id, [FromR if (challenge.TestContainer is null) return Ok(); - await containerService.DestroyContainerAsync(challenge.TestContainer, token); - await containerRepository.RemoveContainer(challenge.TestContainer, token); + await _containerService.DestroyContainerAsync(challenge.TestContainer, token); + await _containerRepository.RemoveContainer(challenge.TestContainer, token); return Ok(); } @@ -663,20 +663,20 @@ public async Task DestroyTestContainer([FromRoute] int id, [FromR [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task RemoveGameChallenge([FromRoute] int id, [FromRoute] int cId, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var res = await challengeRepository.GetChallenge(id, cId, true, token); + var res = await _challengeRepository.GetChallenge(id, cId, true, token); if (res is null) return NotFound(new RequestResponse("题目未找到", 404)); - await challengeRepository.RemoveChallenge(res, token); + await _challengeRepository.RemoveChallenge(res, token); // always flush scoreboard - await gameRepository.FlushScoreboardCache(game.Id, token); + await _gameRepository.FlushScoreboardCache(game.Id, token); return Ok(); } @@ -697,12 +697,12 @@ public async Task RemoveGameChallenge([FromRoute] int id, [FromRo [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task UpdateAttachment([FromRoute] int id, [FromRoute] int cId, [FromBody] AttachmentCreateModel model, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var challenge = await challengeRepository.GetChallenge(id, cId, true, token); + var challenge = await _challengeRepository.GetChallenge(id, cId, true, token); if (challenge is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -710,7 +710,7 @@ public async Task UpdateAttachment([FromRoute] int id, [FromRoute if (challenge.Type == ChallengeType.DynamicAttachment) return BadRequest(new RequestResponse("动态附件题目请使用 assets API 上传附件")); - await challengeRepository.UpdateAttachment(challenge, model, token); + await _challengeRepository.UpdateAttachment(challenge, model, token); return Ok(); } @@ -731,17 +731,17 @@ public async Task UpdateAttachment([FromRoute] int id, [FromRoute [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task AddFlags([FromRoute] int id, [FromRoute] int cId, [FromBody] FlagCreateModel[] models, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var challenge = await challengeRepository.GetChallenge(id, cId, true, token); + var challenge = await _challengeRepository.GetChallenge(id, cId, true, token); if (challenge is null) return NotFound(new RequestResponse("题目未找到", 404)); - await challengeRepository.AddFlags(challenge, models, token); + await _challengeRepository.AddFlags(challenge, models, token); return Ok(); } @@ -762,16 +762,16 @@ public async Task AddFlags([FromRoute] int id, [FromRoute] int cI [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task RemoveFlag([FromRoute] int id, [FromRoute] int cId, [FromRoute] int fId, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var challenge = await challengeRepository.GetChallenge(id, cId, true, token); + var challenge = await _challengeRepository.GetChallenge(id, cId, true, token); if (challenge is null) return NotFound(new RequestResponse("题目未找到", 404)); - return Ok(await challengeRepository.RemoveFlag(challenge, fId, token)); + return Ok(await _challengeRepository.RemoveFlag(challenge, fId, token)); } } diff --git a/src/GZCTF/Controllers/GameController.cs b/src/GZCTF/Controllers/GameController.cs index 3fe8547c4..1df3bec6f 100644 --- a/src/GZCTF/Controllers/GameController.cs +++ b/src/GZCTF/Controllers/GameController.cs @@ -25,54 +25,54 @@ namespace GZCTF.Controllers; [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public class GameController : ControllerBase { - private readonly ILogger logger; - private readonly UserManager userManager; - private readonly ChannelWriter checkerChannelWriter; - private readonly IFileRepository fileService; - private readonly IGameRepository gameRepository; - private readonly ITeamRepository teamRepository; - private readonly IGameEventRepository eventRepository; - private readonly IInstanceRepository instanceRepository; - private readonly IGameNoticeRepository noticeRepository; - private readonly IGameEventRepository gameEventRepository; - private readonly IContainerRepository containerRepository; - private readonly ICheatInfoRepository cheatInfoRepository; - private readonly IChallengeRepository challengeRepository; - private readonly ISubmissionRepository submissionRepository; - private readonly IParticipationRepository participationRepository; + private readonly ILogger _logger; + private readonly UserManager _userManager; + private readonly ChannelWriter _checkerChannelWriter; + private readonly IFileRepository _fileService; + private readonly IGameRepository _gameRepository; + private readonly ITeamRepository _teamRepository; + private readonly IGameEventRepository _eventRepository; + private readonly IInstanceRepository _instanceRepository; + private readonly IGameNoticeRepository _noticeRepository; + private readonly IGameEventRepository _gameEventRepository; + private readonly IContainerRepository _containerRepository; + private readonly ICheatInfoRepository _cheatInfoRepository; + private readonly IChallengeRepository _challengeRepository; + private readonly ISubmissionRepository _submissionRepository; + private readonly IParticipationRepository _participationRepository; public GameController( - ILogger _logger, - UserManager _userManager, - ChannelWriter _channelWriter, - IFileRepository _fileService, - IGameRepository _gameRepository, - ITeamRepository _teamRepository, - IGameEventRepository _eventRepository, - IGameNoticeRepository _noticeRepository, - IInstanceRepository _instanceRepository, - ICheatInfoRepository _cheatInfoRepository, - IChallengeRepository _challengeRepository, - IContainerRepository _containerRepository, - IGameEventRepository _gameEventRepository, - ISubmissionRepository _submissionRepository, - IParticipationRepository _participationRepository) + ILogger logger, + UserManager userManager, + ChannelWriter channelWriter, + IFileRepository fileService, + IGameRepository gameRepository, + ITeamRepository teamRepository, + IGameEventRepository eventRepository, + IGameNoticeRepository noticeRepository, + IInstanceRepository instanceRepository, + ICheatInfoRepository cheatInfoRepository, + IChallengeRepository challengeRepository, + IContainerRepository containerRepository, + IGameEventRepository gameEventRepository, + ISubmissionRepository submissionRepository, + IParticipationRepository participationRepository) { - logger = _logger; - userManager = _userManager; - checkerChannelWriter = _channelWriter; - fileService = _fileService; - gameRepository = _gameRepository; - teamRepository = _teamRepository; - eventRepository = _eventRepository; - noticeRepository = _noticeRepository; - instanceRepository = _instanceRepository; - challengeRepository = _challengeRepository; - containerRepository = _containerRepository; - gameEventRepository = _gameEventRepository; - cheatInfoRepository = _cheatInfoRepository; - submissionRepository = _submissionRepository; - participationRepository = _participationRepository; + _logger = logger; + _userManager = userManager; + _checkerChannelWriter = channelWriter; + _fileService = fileService; + _gameRepository = gameRepository; + _teamRepository = teamRepository; + _eventRepository = eventRepository; + _noticeRepository = noticeRepository; + _instanceRepository = instanceRepository; + _challengeRepository = challengeRepository; + _containerRepository = containerRepository; + _gameEventRepository = gameEventRepository; + _cheatInfoRepository = cheatInfoRepository; + _submissionRepository = submissionRepository; + _participationRepository = participationRepository; } /// @@ -86,7 +86,7 @@ public GameController( [HttpGet] [ProducesResponseType(typeof(BasicGameInfoModel[]), StatusCodes.Status200OK)] public async Task Games(CancellationToken token) - => Ok(await gameRepository.GetBasicGameInfo(10, 0, token)); + => Ok(await _gameRepository.GetBasicGameInfo(10, 0, token)); /// /// 获取比赛详细信息 @@ -108,7 +108,7 @@ public async Task Games(int id, CancellationToken token) if (context.Game is null) return NotFound(new RequestResponse("比赛未找到")); - var count = await participationRepository.GetParticipationCount(context.Game, token); + var count = await _participationRepository.GetParticipationCount(context.Game, token); return Ok(DetailedGameInfoModel.FromGame(context.Game, count) .WithParticipation(context.Participation)); @@ -133,7 +133,7 @@ public async Task Games(int id, CancellationToken token) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task JoinGame(int id, [FromBody] GameJoinModel model, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); @@ -147,8 +147,8 @@ public async Task JoinGame(int id, [FromBody] GameJoinModel model if (game.Organizations is { Count: > 0 } && game.Organizations.All(o => o != model.Organization)) return BadRequest(new RequestResponse("无效的参赛单位")); - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(model.TeamId, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(model.TeamId, token); if (team is null) return NotFound(new RequestResponse("队伍未找到", 404)); @@ -157,14 +157,14 @@ public async Task JoinGame(int id, [FromBody] GameJoinModel model return BadRequest(new RequestResponse("您不是此队伍的队员")); // 如果已经报名(非拒绝状态) - if (await participationRepository.CheckRepeatParticipation(user!, game, token)) + if (await _participationRepository.CheckRepeatParticipation(user!, game, token)) return BadRequest(new RequestResponse("您已经在其他队伍报名参赛")); // 移除所有的已经存在的报名 - await participationRepository.RemoveUserParticipations(user!, game, token); + await _participationRepository.RemoveUserParticipations(user!, game, token); // 根据队伍获取报名信息 - var part = await participationRepository.GetParticipation(team, game, token); + var part = await _participationRepository.GetParticipation(team, game, token); // 如果队伍未报名 if (part is null) @@ -175,10 +175,10 @@ public async Task JoinGame(int id, [FromBody] GameJoinModel model Game = game, Team = team, Organization = model.Organization, - Token = gameRepository.GetToken(game, team) + Token = _gameRepository.GetToken(game, team) }; - participationRepository.Add(part); + _participationRepository.Add(part); } if (game.TeamMemberCountLimit > 0 && part.Members.Count >= game.TeamMemberCountLimit) @@ -192,12 +192,12 @@ public async Task JoinGame(int id, [FromBody] GameJoinModel model if (part.Status == ParticipationStatus.Rejected) part.Status = ParticipationStatus.Pending; - await participationRepository.SaveAsync(token); + await _participationRepository.SaveAsync(token); if (game.AcceptWithoutReview) - await participationRepository.UpdateParticipationStatus(part, ParticipationStatus.Accepted, token); + await _participationRepository.UpdateParticipationStatus(part, ParticipationStatus.Accepted, token); - logger.Log($"[{team!.Name}] 成功报名了比赛 [{game.Title}]", user, TaskStatus.Success); + _logger.Log($"[{team!.Name}] 成功报名了比赛 [{game.Title}]", user, TaskStatus.Success); return Ok(); } @@ -220,14 +220,14 @@ public async Task JoinGame(int id, [FromBody] GameJoinModel model [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task LeaveGame(int id, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到", 404)); - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); - var part = await participationRepository.GetParticipation(user!, game, token); + var part = await _participationRepository.GetParticipation(user!, game, token); if (part is null || part.Members.All(u => u.UserId != user!.Id)) return BadRequest(new RequestResponse("无法退出未报名的比赛")); @@ -240,9 +240,9 @@ public async Task LeaveGame(int id, CancellationToken token) part.Members.RemoveWhere(u => u.UserId == user!.Id); if (part.Members.Count == 0) - await participationRepository.RemoveParticipation(part, token); + await _participationRepository.RemoveParticipation(part, token); else - await participationRepository.SaveAsync(token); + await _participationRepository.SaveAsync(token); return Ok(); } @@ -262,7 +262,7 @@ public async Task LeaveGame(int id, CancellationToken token) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task Scoreboard([FromRoute] int id, CancellationToken token) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到")); @@ -270,7 +270,7 @@ public async Task Scoreboard([FromRoute] int id, CancellationToke if (DateTimeOffset.UtcNow < game.StartTimeUTC) return BadRequest(new RequestResponse("比赛未开始")); - return Ok(await gameRepository.GetScoreboard(game, token)); + return Ok(await _gameRepository.GetScoreboard(game, token)); } /// @@ -290,7 +290,7 @@ public async Task Scoreboard([FromRoute] int id, CancellationToke [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task Notices([FromRoute] int id, [FromQuery] int count = 100, [FromQuery] int skip = 0, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到")); @@ -298,7 +298,7 @@ public async Task Notices([FromRoute] int id, [FromQuery] int cou if (DateTimeOffset.UtcNow < game.StartTimeUTC) return BadRequest(new RequestResponse("比赛未开始")); - return Ok(await noticeRepository.GetNotices(game.Id, count, skip, token)); + return Ok(await _noticeRepository.GetNotices(game.Id, count, skip, token)); } /// @@ -320,7 +320,7 @@ public async Task Notices([FromRoute] int id, [FromQuery] int cou [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task Events([FromRoute] int id, [FromQuery] bool hideContainer = false, [FromQuery] int count = 100, [FromQuery] int skip = 0, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到")); @@ -328,7 +328,7 @@ public async Task Events([FromRoute] int id, [FromQuery] bool hid if (DateTimeOffset.UtcNow < game.StartTimeUTC) return BadRequest(new RequestResponse("比赛未开始")); - return Ok(await eventRepository.GetEvents(game.Id, hideContainer, count, skip, token)); + return Ok(await _eventRepository.GetEvents(game.Id, hideContainer, count, skip, token)); } /// @@ -350,7 +350,7 @@ public async Task Events([FromRoute] int id, [FromQuery] bool hid [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task Submissions([FromRoute] int id, [FromQuery] AnswerResult? type = null, [FromQuery] int count = 100, [FromQuery] int skip = 0, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到")); @@ -358,7 +358,7 @@ public async Task Submissions([FromRoute] int id, [FromQuery] Ans if (DateTimeOffset.UtcNow < game.StartTimeUTC) return BadRequest(new RequestResponse("比赛未开始")); - return Ok(await submissionRepository.GetSubmissions(game, type, count, skip, token)); + return Ok(await _submissionRepository.GetSubmissions(game, type, count, skip, token)); } /// @@ -377,7 +377,7 @@ public async Task Submissions([FromRoute] int id, [FromQuery] Ans [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task CheatInfo([FromRoute] int id, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到")); @@ -385,7 +385,7 @@ public async Task CheatInfo([FromRoute] int id, CancellationToken if (DateTimeOffset.UtcNow < game.StartTimeUTC) return BadRequest(new RequestResponse("比赛未开始")); - return Ok((await cheatInfoRepository.GetCheatInfoByGameId(game.Id, token)) + return Ok((await _cheatInfoRepository.GetCheatInfoByGameId(game.Id, token)) .Select(CheatInfoModel.FromCheatInfo)); } @@ -412,7 +412,7 @@ public async Task ChallengesWithTeamInfo([FromRoute] int id, Canc if (context.Result is not null) return context.Result; - var scoreboard = await gameRepository.GetScoreboard(context.Game!, token); + var scoreboard = await _gameRepository.GetScoreboard(context.Game!, token); var boarditem = scoreboard.Items.FirstOrDefault(i => i.Id == context.Participation!.TeamId); @@ -458,7 +458,7 @@ public async Task Participations([FromRoute] int id, Cancellation if (context.Game is null) return NotFound(new RequestResponse("比赛未找到")); - return Ok((await participationRepository.GetParticipations(context.Game!, token)) + return Ok((await _participationRepository.GetParticipations(context.Game!, token)) .Select(ParticipationInfoModel.FromParticipation)); } @@ -480,7 +480,7 @@ public async Task Participations([FromRoute] int id, Cancellation [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task ScoreboardSheet([FromRoute] int id, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到")); @@ -490,7 +490,7 @@ public async Task ScoreboardSheet([FromRoute] int id, Cancellatio try { - var scoreboard = await gameRepository.GetScoreboardWithMembers(game, token); + var scoreboard = await _gameRepository.GetScoreboardWithMembers(game, token); var stream = ExcelHelper.GetScoreboardExcel(scoreboard, game); stream.Seek(0, SeekOrigin.Begin); @@ -500,8 +500,8 @@ public async Task ScoreboardSheet([FromRoute] int id, Cancellatio } catch (Exception ex) { - logger.SystemLog("下载积分榜遇到错误", TaskStatus.Failed, LogLevel.Error); - logger.LogError(ex, ex.Message); + _logger.SystemLog("下载积分榜遇到错误", TaskStatus.Failed, LogLevel.Error); + _logger.LogError(ex, ex.Message); return BadRequest(new RequestResponse("遇到问题,请重试")); } } @@ -524,7 +524,7 @@ public async Task ScoreboardSheet([FromRoute] int id, Cancellatio [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task SubmissionSheet([FromRoute] int id, CancellationToken token = default) { - var game = await gameRepository.GetGameById(id, token); + var game = await _gameRepository.GetGameById(id, token); if (game is null) return NotFound(new RequestResponse("比赛未找到")); @@ -532,7 +532,7 @@ public async Task SubmissionSheet([FromRoute] int id, Cancellatio if (DateTimeOffset.UtcNow < game.StartTimeUTC) return BadRequest(new RequestResponse("比赛未开始")); - var submissions = await submissionRepository.GetSubmissions(game, count: 0, token: token); + var submissions = await _submissionRepository.GetSubmissions(game, count: 0, token: token); var stream = ExcelHelper.GetSubmissionExcel(submissions); stream.Seek(0, SeekOrigin.Begin); @@ -569,7 +569,7 @@ public async Task GetChallenge([FromRoute] int id, [FromRoute] in if (context.Result is not null) return context.Result; - var instance = await instanceRepository.GetInstance(context.Participation!, challengeId, token); + var instance = await _instanceRepository.GetInstance(context.Participation!, challengeId, token); if (instance is null) return NotFound(new RequestResponse("题目未找到或动态附件分配失败", 404)); @@ -615,10 +615,10 @@ public async Task Submit([FromRoute] int id, [FromRoute] int chal SubmitTimeUTC = DateTimeOffset.UtcNow, }; - submission = await submissionRepository.AddSubmission(submission, token); + submission = await _submissionRepository.AddSubmission(submission, token); // send to flag checker service - await checkerChannelWriter.WriteAsync(submission, token); + await _checkerChannelWriter.WriteAsync(submission, token); return Ok(submission.Id); } @@ -643,7 +643,7 @@ public async Task Status([FromRoute] int id, [FromRoute] int chal { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); - var submission = await submissionRepository.GetSubmission(id, challengeId, userId!, submitId, token); + var submission = await _submissionRepository.GetSubmission(id, challengeId, userId!, submitId, token); if (submission is null) return NotFound(new RequestResponse("提交未找到", 404)); @@ -724,18 +724,18 @@ public async Task SubmitWriteup([FromRoute] int id, IFormFile fil var wp = context.Participation!.Writeup; if (wp is not null) - await fileService.DeleteFile(wp, token); + await _fileService.DeleteFile(wp, token); - wp = await fileService.CreateOrUpdateFile(file, $"Writeup-{game.Id}-{team.Id}-{DateTimeOffset.Now:yyyyMMdd-HH.mm.ssZ}.pdf", token); + wp = await _fileService.CreateOrUpdateFile(file, $"Writeup-{game.Id}-{team.Id}-{DateTimeOffset.Now:yyyyMMdd-HH.mm.ssZ}.pdf", token); if (wp is null) return BadRequest(new RequestResponse("保存文件失败")); part.Writeup = wp; - await participationRepository.SaveAsync(token); + await _participationRepository.SaveAsync(token); - logger.Log($"{team.Name} 成功提交 {game.Title} 的 Writeup", context.User!, TaskStatus.Success); + _logger.Log($"{team.Name} 成功提交 {game.Title} 的 Writeup", context.User!, TaskStatus.Success); return Ok(); } @@ -766,7 +766,7 @@ public async Task CreateContainer([FromRoute] int id, [FromRoute] if (context.Result is not null) return context.Result; - var instance = await instanceRepository.GetInstance(context.Participation!, challengeId, token); + var instance = await _instanceRepository.GetInstance(context.Participation!, challengeId, token); if (instance is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -785,10 +785,10 @@ public async Task CreateContainer([FromRoute] int id, [FromRoute] if (instance.Container.Status == ContainerStatus.Running) return BadRequest(new RequestResponse("题目已经创建容器")); - await containerRepository.RemoveContainer(instance.Container, token); + await _containerRepository.RemoveContainer(instance.Container, token); } - return await instanceRepository.CreateContainer(instance, context.Participation!.Team, context.User!, context.Game!.ContainerCountLimit, token) switch + return await _instanceRepository.CreateContainer(instance, context.Participation!.Team, context.User!, context.Game!.ContainerCountLimit, token) switch { null or (TaskStatus.Failed, null) => BadRequest(new RequestResponse("题目创建容器失败")), (TaskStatus.Denied, null) => BadRequest(new RequestResponse($"队伍容器数目不能超过 {context.Game.ContainerCountLimit}")), @@ -822,7 +822,7 @@ public async Task ProlongContainer([FromRoute] int id, [FromRoute if (context.Result is not null) return context.Result; - var instance = await instanceRepository.GetInstance(context.Participation!, challengeId, token); + var instance = await _instanceRepository.GetInstance(context.Participation!, challengeId, token); if (instance is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -836,7 +836,7 @@ public async Task ProlongContainer([FromRoute] int id, [FromRoute if (instance.Container.ExpectStopAt - DateTimeOffset.UtcNow > TimeSpan.FromMinutes(10)) return BadRequest(new RequestResponse("容器时间尚不可延长")); - await instanceRepository.ProlongContainer(instance.Container, TimeSpan.FromHours(2), token); + await _instanceRepository.ProlongContainer(instance.Container, TimeSpan.FromHours(2), token); return Ok(ContainerInfoModel.FromContainer(instance.Container)); } @@ -867,7 +867,7 @@ public async Task DeleteContainer([FromRoute] int id, [FromRoute] if (context.Result is not null) return context.Result; - var instance = await instanceRepository.GetInstance(context.Participation!, challengeId, token); + var instance = await _instanceRepository.GetInstance(context.Participation!, challengeId, token); if (instance is null) return NotFound(new RequestResponse("题目未找到", 404)); @@ -886,12 +886,12 @@ public async Task DeleteContainer([FromRoute] int id, [FromRoute] var destroyId = instance.Container.ContainerId; - if (!await instanceRepository.DestroyContainer(instance.Container, token)) + if (!await _instanceRepository.DestroyContainer(instance.Container, token)) return BadRequest(new RequestResponse("题目删除容器失败")); instance.LastContainerOperation = DateTimeOffset.UtcNow; - await gameEventRepository.AddEvent(new() + await _gameEventRepository.AddEvent(new() { Type = EventType.ContainerDestroy, GameId = context.Game!.Id, @@ -900,7 +900,7 @@ await gameEventRepository.AddEvent(new() Content = $"{instance.Challenge.Title}#{instance.Challenge.Id} 销毁容器实例" }, token); - logger.Log($"{context.Participation!.Team.Name} 销毁题目 {instance.Challenge.Title} 的容器实例 [{destroyId}]", context.User, TaskStatus.Success); + _logger.Log($"{context.Participation!.Team.Name} 销毁题目 {instance.Challenge.Title} 的容器实例 [{destroyId}]", context.User, TaskStatus.Success); return Ok(); } @@ -924,14 +924,14 @@ private async Task GetContextInfo(int id, int challengeId = 0, bool { ContextInfo res = new() { - User = await userManager.GetUserAsync(User), - Game = await gameRepository.GetGameById(id, token) + User = await _userManager.GetUserAsync(User), + Game = await _gameRepository.GetGameById(id, token) }; if (res.Game is null) return res.WithResult(NotFound(new RequestResponse("比赛未找到", 404))); - var part = await participationRepository.GetParticipation(res.User!, res.Game, token); + var part = await _participationRepository.GetParticipation(res.User!, res.Game, token); if (part is null) return res.WithResult(BadRequest(new RequestResponse("您尚未参赛"))); @@ -949,7 +949,7 @@ private async Task GetContextInfo(int id, int challengeId = 0, bool if (challengeId > 0) { - var challenge = await challengeRepository.GetChallenge(id, challengeId, withFlag, token); + var challenge = await _challengeRepository.GetChallenge(id, challengeId, withFlag, token); if (challenge is null) return res.WithResult(NotFound(new RequestResponse("题目未找到", 404))); diff --git a/src/GZCTF/Controllers/InfoController.cs b/src/GZCTF/Controllers/InfoController.cs index 48d808521..0cc446df9 100644 --- a/src/GZCTF/Controllers/InfoController.cs +++ b/src/GZCTF/Controllers/InfoController.cs @@ -15,20 +15,20 @@ namespace GZCTF.Controllers; [ApiController] public class InfoController : ControllerBase { - private readonly IOptionsSnapshot accountPolicy; - private readonly IOptionsSnapshot globalConfig; - private readonly IPostRepository postRepository; - private readonly IRecaptchaExtension recaptchaExtension; + private readonly IOptionsSnapshot _accountPolicy; + private readonly IOptionsSnapshot _globalConfig; + private readonly IPostRepository _postRepository; + private readonly IRecaptchaExtension _recaptchaExtension; - public InfoController(IPostRepository _postRepository, - IRecaptchaExtension _recaptchaExtension, - IOptionsSnapshot _globalConfig, - IOptionsSnapshot _accountPolicy) + public InfoController(IPostRepository postRepository, + IRecaptchaExtension recaptchaExtension, + IOptionsSnapshot globalConfig, + IOptionsSnapshot accountPolicy) { - globalConfig = _globalConfig; - accountPolicy = _accountPolicy; - postRepository = _postRepository; - recaptchaExtension = _recaptchaExtension; + _globalConfig = globalConfig; + _accountPolicy = accountPolicy; + _postRepository = postRepository; + _recaptchaExtension = recaptchaExtension; } /// @@ -42,7 +42,7 @@ public InfoController(IPostRepository _postRepository, [HttpGet("Posts/Latest")] [ProducesResponseType(typeof(PostInfoModel[]), StatusCodes.Status200OK)] public async Task GetLatestPosts(CancellationToken token) - => Ok((await postRepository.GetPosts(token)).Take(20).Select(PostInfoModel.FromPost)); + => Ok((await _postRepository.GetPosts(token)).Take(20).Select(PostInfoModel.FromPost)); /// /// 获取全部文章 @@ -55,7 +55,7 @@ public async Task GetLatestPosts(CancellationToken token) [HttpGet("Posts")] [ProducesResponseType(typeof(PostInfoModel[]), StatusCodes.Status200OK)] public async Task GetPosts(CancellationToken token) - => Ok((await postRepository.GetPosts(token)).Select(PostInfoModel.FromPost)); + => Ok((await _postRepository.GetPosts(token)).Select(PostInfoModel.FromPost)); /// /// 获取文章详情 @@ -71,7 +71,7 @@ public async Task GetPosts(CancellationToken token) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status404NotFound)] public async Task GetPost(string id, CancellationToken token) { - var post = await postRepository.GetPostByIdFromCache(id, token); + var post = await _postRepository.GetPostByIdFromCache(id, token); if (post is null) return NotFound(new RequestResponse("文章未找到", 404)); @@ -88,7 +88,7 @@ public async Task GetPost(string id, CancellationToken token) /// 成功获取配置信息 [HttpGet("Config")] [ProducesResponseType(typeof(GlobalConfig), StatusCodes.Status200OK)] - public IActionResult GetGlobalConfig() => Ok(globalConfig.Value); + public IActionResult GetGlobalConfig() => Ok(_globalConfig.Value); /// /// 获取 Recaptcha SiteKey @@ -100,5 +100,5 @@ public async Task GetPost(string id, CancellationToken token) [HttpGet("SiteKey")] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] public IActionResult GetRecaptchaSiteKey() - => Ok(accountPolicy.Value.UseGoogleRecaptcha ? recaptchaExtension.SiteKey() : "NOTOKEN"); + => Ok(_accountPolicy.Value.UseGoogleRecaptcha ? _recaptchaExtension.SiteKey() : "NOTOKEN"); } diff --git a/src/GZCTF/Controllers/TeamController.cs b/src/GZCTF/Controllers/TeamController.cs index c8a15a115..d3eec85f3 100644 --- a/src/GZCTF/Controllers/TeamController.cs +++ b/src/GZCTF/Controllers/TeamController.cs @@ -19,23 +19,23 @@ namespace GZCTF.Controllers; [Produces(MediaTypeNames.Application.Json)] public class TeamController : ControllerBase { - private readonly UserManager userManager; - private readonly IFileRepository FileService; - private readonly ITeamRepository teamRepository; - private readonly IParticipationRepository participationRepository; - private readonly ILogger logger; - - public TeamController(UserManager _userManager, - IFileRepository _FileService, - ILogger _logger, - ITeamRepository _teamRepository, - IParticipationRepository _participationRepository) + private readonly UserManager _userManager; + private readonly IFileRepository _fileService; + private readonly ITeamRepository _teamRepository; + private readonly IParticipationRepository _participationRepository; + private readonly ILogger _logger; + + public TeamController(UserManager userManager, + IFileRepository fileService, + ILogger logger, + ITeamRepository teamRepository, + IParticipationRepository participationRepository) { - logger = _logger; - userManager = _userManager; - FileService = _FileService; - teamRepository = _teamRepository; - participationRepository = _participationRepository; + _logger = logger; + _userManager = userManager; + _fileService = fileService; + _teamRepository = teamRepository; + _participationRepository = participationRepository; } /// @@ -53,7 +53,7 @@ public TeamController(UserManager _userManager, [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task GetBasicInfo(int id, CancellationToken token) { - var team = await teamRepository.GetTeamById(id, token); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return NotFound(new RequestResponse("队伍不存在", 404)); @@ -76,9 +76,9 @@ public async Task GetBasicInfo(int id, CancellationToken token) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status400BadRequest)] public async Task GetTeamsInfo(CancellationToken token) { - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); - return Ok((await teamRepository.GetUserTeams(user!, token)).Select(t => TeamInfoModel.FromTeam(t))); + return Ok((await _teamRepository.GetUserTeams(user!, token)).Select(t => TeamInfoModel.FromTeam(t))); } /// @@ -100,9 +100,9 @@ public async Task GetTeamsInfo(CancellationToken token) [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task CreateTeam([FromBody] TeamUpdateModel model, CancellationToken token) { - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); - var teams = await teamRepository.GetUserTeams(user!, token); + var teams = await _teamRepository.GetUserTeams(user!, token); if (teams.Length > 1 && teams.Any(t => t.CaptainId == user!.Id)) return BadRequest(new RequestResponse("不允许创建多个队伍")); @@ -110,14 +110,14 @@ public async Task CreateTeam([FromBody] TeamUpdateModel model, Ca if (string.IsNullOrEmpty(model.Name)) return BadRequest(new RequestResponse("队伍名不能为空")); - var team = await teamRepository.CreateTeam(model, user!, token); + var team = await _teamRepository.CreateTeam(model, user!, token); if (team is null) return BadRequest(new RequestResponse("队伍创建失败")); - await userManager.UpdateAsync(user!); + await _userManager.UpdateAsync(user!); - logger.Log($"创建队伍 {team.Name}", user, TaskStatus.Success); + _logger.Log($"创建队伍 {team.Name}", user, TaskStatus.Success); return Ok(TeamInfoModel.FromTeam(team)); } @@ -143,8 +143,8 @@ public async Task CreateTeam([FromBody] TeamUpdateModel model, Ca [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task UpdateTeam([FromRoute] int id, [FromBody] TeamUpdateModel model, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(id, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); @@ -154,7 +154,7 @@ public async Task UpdateTeam([FromRoute] int id, [FromBody] TeamU team.UpdateInfo(model); - await teamRepository.SaveAsync(token); + await _teamRepository.SaveAsync(token); return Ok(TeamInfoModel.FromTeam(team)); } @@ -180,8 +180,8 @@ public async Task UpdateTeam([FromRoute] int id, [FromBody] TeamU [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task Transfer([FromRoute] int id, [FromBody] TeamTransferModel model, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(id, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); @@ -189,20 +189,20 @@ public async Task Transfer([FromRoute] int id, [FromBody] TeamTra if (team.CaptainId != user!.Id) return new JsonResult(new RequestResponse("无权访问", 403)) { StatusCode = 403 }; - if (team.Locked && await teamRepository.AnyActiveGame(team, token)) + if (team.Locked && await _teamRepository.AnyActiveGame(team, token)) return BadRequest(new RequestResponse("队伍已锁定")); - var newCaptain = await userManager.Users.SingleOrDefaultAsync(u => u.Id == model.NewCaptainId); + var newCaptain = await _userManager.Users.SingleOrDefaultAsync(u => u.Id == model.NewCaptainId); if (newCaptain is null) return BadRequest(new RequestResponse("移交的用户不存在")); - var newCaptainTeams = await teamRepository.GetUserTeams(newCaptain, token); + var newCaptainTeams = await _teamRepository.GetUserTeams(newCaptain, token); if (newCaptainTeams.Count(t => t.CaptainId == newCaptain.Id) >= 3) return BadRequest(new RequestResponse("被移交者所管理的队伍过多")); - await teamRepository.Transfer(team, newCaptain, token); + await _teamRepository.Transfer(team, newCaptain, token); return Ok(TeamInfoModel.FromTeam(team)); } @@ -227,8 +227,8 @@ public async Task Transfer([FromRoute] int id, [FromBody] TeamTra [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task InviteCode([FromRoute] int id, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(id, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); @@ -259,8 +259,8 @@ public async Task InviteCode([FromRoute] int id, CancellationToke [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task UpdateInviteToken([FromRoute] int id, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(id, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); @@ -270,7 +270,7 @@ public async Task UpdateInviteToken([FromRoute] int id, Cancellat team.UpdateInviteToken(); - await teamRepository.SaveAsync(token); + await _teamRepository.SaveAsync(token); return Ok(team.InviteCode); } @@ -296,8 +296,8 @@ public async Task UpdateInviteToken([FromRoute] int id, Cancellat [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task KickUser([FromRoute] int id, [FromRoute] string userid, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(id, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); @@ -305,11 +305,11 @@ public async Task KickUser([FromRoute] int id, [FromRoute] string if (team.CaptainId != user!.Id) return new JsonResult(new RequestResponse("无权访问", 403)) { StatusCode = 403 }; - var trans = await teamRepository.BeginTransactionAsync(token); + var trans = await _teamRepository.BeginTransactionAsync(token); try { - if (team.Locked && await teamRepository.AnyActiveGame(team, token)) + if (team.Locked && await _teamRepository.AnyActiveGame(team, token)) return BadRequest(new RequestResponse("队伍已锁定")); var kickUser = team.Members.SingleOrDefault(m => m.Id == userid); @@ -317,12 +317,12 @@ public async Task KickUser([FromRoute] int id, [FromRoute] string return BadRequest(new RequestResponse("用户不在队伍中")); team.Members.Remove(kickUser); - await participationRepository.RemoveUserParticipations(user, team, token); + await _participationRepository.RemoveUserParticipations(user, team, token); - await teamRepository.SaveAsync(token); + await _teamRepository.SaveAsync(token); await trans.CommitAsync(token); - logger.Log($"从队伍 {team.Name} 踢除 {kickUser.UserName}", user, TaskStatus.Success); + _logger.Log($"从队伍 {team.Name} 踢除 {kickUser.UserName}", user, TaskStatus.Success); return Ok(TeamInfoModel.FromTeam(team)); } catch @@ -364,11 +364,11 @@ public async Task Accept([FromBody] string code, CancellationToke return BadRequest(new RequestResponse($"队伍 Id 转换错误:{preCode[(lastColon + 1)..]}")); var teamName = preCode[..lastColon]; - var trans = await teamRepository.BeginTransactionAsync(cancelToken); + var trans = await _teamRepository.BeginTransactionAsync(cancelToken); try { - var team = await teamRepository.GetTeamById(teamId, cancelToken); + var team = await _teamRepository.GetTeamById(teamId, cancelToken); if (team is null) return BadRequest(new RequestResponse($"{teamName} 队伍未找到")); @@ -376,20 +376,20 @@ public async Task Accept([FromBody] string code, CancellationToke if (team.InviteCode != code) return BadRequest(new RequestResponse($"{teamName} 邀请无效")); - if (team.Locked && await teamRepository.AnyActiveGame(team, cancelToken)) + if (team.Locked && await _teamRepository.AnyActiveGame(team, cancelToken)) return BadRequest(new RequestResponse($"{teamName} 队伍已锁定")); - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); if (team.Members.Any(m => m.Id == user!.Id)) return BadRequest(new RequestResponse("你已经加入此队伍,无需重复加入")); team.Members.Add(user!); - await teamRepository.SaveAsync(cancelToken); + await _teamRepository.SaveAsync(cancelToken); await trans.CommitAsync(cancelToken); - logger.Log($"加入队伍 {team.Name}", user, TaskStatus.Success); + _logger.Log($"加入队伍 {team.Name}", user, TaskStatus.Success); return Ok(); } catch @@ -419,29 +419,29 @@ public async Task Accept([FromBody] string code, CancellationToke [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task Leave([FromRoute] int id, CancellationToken token) { - var trans = await teamRepository.BeginTransactionAsync(token); + var trans = await _teamRepository.BeginTransactionAsync(token); try { - var team = await teamRepository.GetTeamById(id, token); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); - var user = await userManager.GetUserAsync(User); + var user = await _userManager.GetUserAsync(User); if (team.Members.All(m => m.Id != user!.Id)) return BadRequest(new RequestResponse("你不在此队伍中,无法离队")); - if (team.Locked && await teamRepository.AnyActiveGame(team, token)) + if (team.Locked && await _teamRepository.AnyActiveGame(team, token)) return BadRequest(new RequestResponse("队伍已锁定")); team.Members.Remove(user!); - await teamRepository.SaveAsync(token); + await _teamRepository.SaveAsync(token); await trans.CommitAsync(token); - logger.Log($"离开队伍 {team.Name}", user, TaskStatus.Success); + _logger.Log($"离开队伍 {team.Name}", user, TaskStatus.Success); return Ok(); } catch @@ -468,8 +468,8 @@ public async Task Leave([FromRoute] int id, CancellationToken tok [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task Avatar([FromRoute] int id, IFormFile file, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(id, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); @@ -484,17 +484,17 @@ public async Task Avatar([FromRoute] int id, IFormFile file, Canc return BadRequest(new RequestResponse("文件过大")); if (team.AvatarHash is not null) - _ = await FileService.DeleteFileByHash(team.AvatarHash, token); + _ = await _fileService.DeleteFileByHash(team.AvatarHash, token); - var avatar = await FileService.CreateOrUpdateImage(file, "avatar", token); + var avatar = await _fileService.CreateOrUpdateImage(file, "avatar", token); if (avatar is null) return BadRequest(new RequestResponse("队伍头像更新失败")); team.AvatarHash = avatar.Hash; - await teamRepository.SaveAsync(token); + await _teamRepository.SaveAsync(token); - logger.Log($"队伍 {team.Name} 更改新头像:[{avatar.Hash[..8]}]", user, TaskStatus.Success); + _logger.Log($"队伍 {team.Name} 更改新头像:[{avatar.Hash[..8]}]", user, TaskStatus.Success); return Ok(avatar.Url()); } @@ -517,8 +517,8 @@ public async Task Avatar([FromRoute] int id, IFormFile file, Canc [ProducesResponseType(typeof(RequestResponse), StatusCodes.Status403Forbidden)] public async Task DeleteTeam(int id, CancellationToken token) { - var user = await userManager.GetUserAsync(User); - var team = await teamRepository.GetTeamById(id, token); + var user = await _userManager.GetUserAsync(User); + var team = await _teamRepository.GetTeamById(id, token); if (team is null) return BadRequest(new RequestResponse("队伍未找到")); @@ -526,12 +526,12 @@ public async Task DeleteTeam(int id, CancellationToken token) if (team.CaptainId != user!.Id) return new JsonResult(new RequestResponse("无权访问", 403)) { StatusCode = 403 }; - if (team.Locked && await teamRepository.AnyActiveGame(team, token)) + if (team.Locked && await _teamRepository.AnyActiveGame(team, token)) return BadRequest(new RequestResponse("队伍已锁定")); - await teamRepository.DeleteTeam(team!, token); + await _teamRepository.DeleteTeam(team!, token); - logger.Log($"删除队伍 {team!.Name}", user, TaskStatus.Success); + _logger.Log($"删除队伍 {team!.Name}", user, TaskStatus.Success); return Ok(); } diff --git a/src/GZCTF/Extensions/RecaptchaExtension.cs b/src/GZCTF/Extensions/RecaptchaExtension.cs index 45126f5ea..76e418b7e 100644 --- a/src/GZCTF/Extensions/RecaptchaExtension.cs +++ b/src/GZCTF/Extensions/RecaptchaExtension.cs @@ -23,30 +23,30 @@ public interface IRecaptchaExtension public class RecaptchaExtension : IRecaptchaExtension { - private readonly RecaptchaConfig? options; - private readonly HttpClient httpClient; + private readonly RecaptchaConfig? _options; + private readonly HttpClient _httpClient; public RecaptchaExtension(IOptions options) { - this.options = options.Value; - httpClient = new(); + _options = options.Value; + _httpClient = new(); } public async Task VerifyAsync(string token, string ip) { - if (options is null) + if (_options is null) return true; if (string.IsNullOrEmpty(token)) return false; - var response = await httpClient.GetStreamAsync($"{options.VerifyAPIAddress}?secret={options.Secretkey}&response={token}&remoteip={ip}"); + var response = await _httpClient.GetStreamAsync($"{_options.VerifyAPIAddress}?secret={_options.Secretkey}&response={token}&remoteip={ip}"); var tokenResponse = await JsonSerializer.DeserializeAsync(response); - if (tokenResponse is null || !tokenResponse.Success || tokenResponse.Score < options.RecaptchaThreshold) + if (tokenResponse is null || !tokenResponse.Success || tokenResponse.Score < _options.RecaptchaThreshold) return false; return true; } - public string SiteKey() => options?.SiteKey ?? "NOTOKEN"; + public string SiteKey() => _options?.SiteKey ?? "NOTOKEN"; } diff --git a/src/GZCTF/Extensions/SignalRSinkExtension.cs b/src/GZCTF/Extensions/SignalRSinkExtension.cs index 9ca6b9f2a..405338cb2 100644 --- a/src/GZCTF/Extensions/SignalRSinkExtension.cs +++ b/src/GZCTF/Extensions/SignalRSinkExtension.cs @@ -17,24 +17,23 @@ public static LoggerConfiguration SignalR(this LoggerSinkConfiguration loggerCon public class SignalRSink : ILogEventSink { - private readonly IServiceProvider serviceProvider; - private IHubContext? hubContext; + private readonly IServiceProvider _serviceProvider; + private IHubContext? _hubContext; - public SignalRSink(IServiceProvider _serviceProvider) + public SignalRSink(IServiceProvider serviceProvider) { - serviceProvider = _serviceProvider; + _serviceProvider = serviceProvider; } public void Emit(LogEvent logEvent) { - if (hubContext is null) - hubContext = serviceProvider.GetRequiredService>(); + _hubContext ??= _serviceProvider.GetRequiredService>(); if (logEvent.Level >= LogEventLevel.Information) { try { - hubContext.Clients.All.ReceivedLog( + _hubContext.Clients.All.ReceivedLog( new LogMessageModel { Time = logEvent.Timestamp, diff --git a/src/GZCTF/Hubs/AdminHub.cs b/src/GZCTF/Hubs/AdminHub.cs index db55f8eba..90aeadffc 100644 --- a/src/GZCTF/Hubs/AdminHub.cs +++ b/src/GZCTF/Hubs/AdminHub.cs @@ -6,13 +6,6 @@ namespace GZCTF.Hubs; public class AdminHub : Hub { - private readonly ILogger logger; - - public AdminHub(ILogger _logger) - { - logger = _logger; - } - public override async Task OnConnectedAsync() { if (!await HubHelper.HasAdmin(Context.GetHttpContext()!)) diff --git a/src/GZCTF/Middlewares/PrivilegeAuthentication.cs b/src/GZCTF/Middlewares/PrivilegeAuthentication.cs index 14a8f490f..3b864ed91 100644 --- a/src/GZCTF/Middlewares/PrivilegeAuthentication.cs +++ b/src/GZCTF/Middlewares/PrivilegeAuthentication.cs @@ -16,10 +16,10 @@ public class RequirePrivilegeAttribute : Attribute, IAsyncAuthorizationFilter /// /// 所需权限 /// - private readonly Role RequiredPrivilege; + private readonly Role _requiredPrivilege; public RequirePrivilegeAttribute(Role privilege) - => RequiredPrivilege = privilege; + => _requiredPrivilege = privilege; public static IActionResult GetResult(string msg, int code) => new JsonResult(new RequestResponse(msg, code)) { StatusCode = code }; @@ -50,9 +50,9 @@ public async Task OnAuthorizationAsync(AuthorizationFilterContext context) await dbcontext.SaveChangesAsync(); // avoid to update ConcurrencyStamp } - if (user.Role < RequiredPrivilege) + if (user.Role < _requiredPrivilege) { - if (RequiredPrivilege > Role.User) + if (_requiredPrivilege > Role.User) logger.Log($"未经授权的访问:{context.HttpContext.Request.Path}", user, TaskStatus.Denied); context.Result = ForbiddenResult; diff --git a/src/GZCTF/Pages/Error.cshtml.cs b/src/GZCTF/Pages/Error.cshtml.cs index 0979c41c2..b641ee50a 100644 --- a/src/GZCTF/Pages/Error.cshtml.cs +++ b/src/GZCTF/Pages/Error.cshtml.cs @@ -7,13 +7,6 @@ namespace GZCTF.Pages; [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public class ErrorModel : PageModel { - private readonly ILogger _logger; - - public ErrorModel(ILogger logger) - { - _logger = logger; - } - public string RequestId { get; set; } = default!; public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); diff --git a/src/GZCTF/Providers/EntityConfigurationProvider.cs b/src/GZCTF/Providers/EntityConfigurationProvider.cs index 3d314f998..032b39197 100644 --- a/src/GZCTF/Providers/EntityConfigurationProvider.cs +++ b/src/GZCTF/Providers/EntityConfigurationProvider.cs @@ -10,17 +10,17 @@ namespace GZCTF.Providers; public class EntityConfigurationProvider : ConfigurationProvider, IDisposable { - private readonly EntityConfigurationSource source; - private readonly CancellationTokenSource cancellationTokenSource; - private Task? databaseWatcher; - private byte[] lastHash; - private bool disposed = false; + private readonly EntityConfigurationSource _source; + private readonly CancellationTokenSource _cancellationTokenSource; + private Task? _databaseWatcher; + private byte[] _lastHash; + private bool _disposed = false; - public EntityConfigurationProvider(EntityConfigurationSource _source) + public EntityConfigurationProvider(EntityConfigurationSource source) { - source = _source; - lastHash = Array.Empty(); - cancellationTokenSource = new(); + _source = source; + _lastHash = Array.Empty(); + _cancellationTokenSource = new(); } private static HashSet DefaultConfigs() @@ -40,16 +40,16 @@ private async Task WatchDatabase(CancellationToken token) { try { - await Task.Delay(source.PollingInterval, token); + await Task.Delay(_source.PollingInterval, token); IDictionary actualData = await GetDataAsync(token); byte[] computedHash = ConfigHash(actualData); - if (!computedHash.SequenceEqual(lastHash)) + if (!computedHash.SequenceEqual(_lastHash)) { Data = actualData; OnReload(); } - lastHash = computedHash; + _lastHash = computedHash; } catch (Exception ex) { @@ -61,7 +61,7 @@ private async Task WatchDatabase(CancellationToken token) private AppDbContext CreateAppDbContext() { var builder = new DbContextOptionsBuilder(); - source.OptionsAction(builder); + _source.OptionsAction(builder); return new AppDbContext(builder.Options); } @@ -78,13 +78,13 @@ private static byte[] ConfigHash(IDictionary configs) public override void Load() { - if (databaseWatcher is not null) + if (_databaseWatcher is not null) { var task = GetDataAsync(); task.Wait(); Data = task.Result; - lastHash = ConfigHash(Data); + _lastHash = ConfigHash(Data); return; } @@ -114,20 +114,20 @@ public override void Load() Data = context.Configs.ToDictionary(c => c.ConfigKey, c => c.Value, StringComparer.OrdinalIgnoreCase); } - lastHash = ConfigHash(Data); + _lastHash = ConfigHash(Data); - var cancellationToken = cancellationTokenSource.Token; - databaseWatcher = Task.Run(() => WatchDatabase(cancellationToken), cancellationToken); + var cancellationToken = _cancellationTokenSource.Token; + _databaseWatcher = Task.Run(() => WatchDatabase(cancellationToken), cancellationToken); } public void Dispose() { - if (disposed) + if (_disposed) return; - cancellationTokenSource.Cancel(); - cancellationTokenSource.Dispose(); - disposed = true; + _cancellationTokenSource.Cancel(); + _cancellationTokenSource.Dispose(); + _disposed = true; GC.SuppressFinalize(this); } } diff --git a/src/GZCTF/Providers/EntityConfigurationSource.cs b/src/GZCTF/Providers/EntityConfigurationSource.cs index 836a4d29f..1b7f573d1 100644 --- a/src/GZCTF/Providers/EntityConfigurationSource.cs +++ b/src/GZCTF/Providers/EntityConfigurationSource.cs @@ -7,10 +7,10 @@ public class EntityConfigurationSource : IConfigurationSource public Action OptionsAction { get; set; } public int PollingInterval { get; private set; } - public EntityConfigurationSource(Action _optionsAction, int _pollingInterval = 180000) + public EntityConfigurationSource(Action optionsAction, int pollingInterval = 180000) { - OptionsAction = _optionsAction; - PollingInterval = _pollingInterval; // default to 3min + OptionsAction = optionsAction; + PollingInterval = pollingInterval; // default to 3min } public IConfigurationProvider Build(IConfigurationBuilder builder) diff --git a/src/GZCTF/Repositories/ChallengeRepository.cs b/src/GZCTF/Repositories/ChallengeRepository.cs index 86c082d60..e9cefec36 100644 --- a/src/GZCTF/Repositories/ChallengeRepository.cs +++ b/src/GZCTF/Repositories/ChallengeRepository.cs @@ -7,11 +7,11 @@ namespace GZCTF.Repositories; public class ChallengeRepository : RepositoryBase, IChallengeRepository { - private readonly IFileRepository fileRepository; + private readonly IFileRepository _fileRepository; - public ChallengeRepository(AppDbContext _context, IFileRepository _fileRepository) : base(_context) + public ChallengeRepository(AppDbContext context, IFileRepository fileRepository) : base(context) { - fileRepository = _fileRepository; + _fileRepository = fileRepository; } public async Task AddFlags(Challenge challenge, FlagCreateModel[] models, CancellationToken token = default) @@ -21,7 +21,7 @@ public async Task AddFlags(Challenge challenge, FlagCreateModel[] models, Cancel Attachment? attachment = model.AttachmentType == FileType.None ? null : new() { Type = model.AttachmentType, - LocalFile = await fileRepository.GetFileByHash(model.FileHash, token), + LocalFile = await _fileRepository.GetFileByHash(model.FileHash, token), RemoteUrl = model.RemoteUrl }; @@ -38,7 +38,7 @@ public async Task AddFlags(Challenge challenge, FlagCreateModel[] models, Cancel public async Task CreateChallenge(Game game, Challenge challenge, CancellationToken token = default) { - await context.AddAsync(challenge, token); + await _context.AddAsync(challenge, token); game.Challenges.Add(challenge); await SaveAsync(token); return challenge; @@ -46,8 +46,8 @@ public async Task CreateChallenge(Game game, Challenge challenge, Can public async Task EnsureInstances(Challenge challenge, Game game, CancellationToken token = default) { - await context.Entry(challenge).Collection(c => c.Teams).LoadAsync(token); - await context.Entry(game).Collection(g => g.Participations).LoadAsync(token); + await _context.Entry(challenge).Collection(c => c.Teams).LoadAsync(token); + await _context.Entry(game).Collection(g => g.Participations).LoadAsync(token); bool update = false; @@ -61,7 +61,7 @@ public async Task EnsureInstances(Challenge challenge, Game game, Cancella public Task GetChallenge(int gameId, int id, bool withFlag = false, CancellationToken token = default) { - var challenges = context.Challenges + var challenges = _context.Challenges .Where(c => c.Id == id && c.GameId == gameId); if (withFlag) @@ -71,7 +71,7 @@ public async Task EnsureInstances(Challenge challenge, Game game, Cancella } public Task GetChallenges(int gameId, CancellationToken token = default) - => context.Challenges.Where(c => c.GameId == gameId).OrderBy(c => c.Id).ToArrayAsync(token); + => _context.Challenges.Where(c => c.GameId == gameId).OrderBy(c => c.Id).ToArrayAsync(token); public async Task RemoveChallenge(Challenge challenge, CancellationToken token = default) { @@ -83,7 +83,7 @@ public async Task RemoveChallenge(Challenge challenge, CancellationToken token = flag.Attachment.Type == FileType.Local && flag.Attachment.LocalFile is not null) { - await fileRepository.DeleteFileByHash( + await _fileRepository.DeleteFileByHash( flag.Attachment.LocalFile.Hash, token); } } @@ -92,11 +92,11 @@ await fileRepository.DeleteFileByHash( challenge.Attachment.Type == FileType.Local && challenge.Attachment.LocalFile is not null) { - await fileRepository.DeleteFileByHash( + await _fileRepository.DeleteFileByHash( challenge.Attachment.LocalFile.Hash, token); } - context.Remove(challenge); + _context.Remove(challenge); await SaveAsync(token); } @@ -111,11 +111,11 @@ public async Task RemoveFlag(Challenge challenge, int flagId, Cancel flag.Attachment.Type == FileType.Local && flag.Attachment.LocalFile is not null) { - await fileRepository.DeleteFileByHash( + await _fileRepository.DeleteFileByHash( flag.Attachment.LocalFile.Hash, token); } - context.Remove(flag); + _context.Remove(flag); if (challenge.Flags.Count == 0) challenge.IsEnabled = false; @@ -130,7 +130,7 @@ public async Task UpdateAttachment(Challenge challenge, AttachmentCreateModel mo Attachment? attachment = model.AttachmentType == FileType.None ? null : new() { Type = model.AttachmentType, - LocalFile = await fileRepository.GetFileByHash(model.FileHash, token), + LocalFile = await _fileRepository.GetFileByHash(model.FileHash, token), RemoteUrl = model.RemoteUrl }; @@ -139,15 +139,15 @@ public async Task UpdateAttachment(Challenge challenge, AttachmentCreateModel mo if (challenge.Attachment.Type == FileType.Local && challenge.Attachment.LocalFile is not null) { - await fileRepository.DeleteFileByHash( + await _fileRepository.DeleteFileByHash( challenge.Attachment.LocalFile.Hash, token); } - context.Remove(challenge.Attachment); + _context.Remove(challenge.Attachment); } if (attachment is not null) - await context.AddAsync(attachment, token); + await _context.AddAsync(attachment, token); challenge.Attachment = attachment; @@ -155,5 +155,5 @@ await fileRepository.DeleteFileByHash( } public Task VerifyStaticAnswer(Challenge challenge, string flag, CancellationToken token = default) - => context.Entry(challenge).Collection(e => e.Flags).Query().AnyAsync(f => f.Flag == flag, token); + => _context.Entry(challenge).Collection(e => e.Flags).Query().AnyAsync(f => f.Flag == flag, token); } diff --git a/src/GZCTF/Repositories/CheatInfoRepository.cs b/src/GZCTF/Repositories/CheatInfoRepository.cs index 3b87c35b1..6da32a16b 100644 --- a/src/GZCTF/Repositories/CheatInfoRepository.cs +++ b/src/GZCTF/Repositories/CheatInfoRepository.cs @@ -6,17 +6,17 @@ namespace GZCTF.Repositories; public class CheatInfoRepository : RepositoryBase, ICheatInfoRepository { - private readonly IParticipationRepository participationRepository; + private readonly IParticipationRepository _participationRepository; - public CheatInfoRepository(AppDbContext _context, - IParticipationRepository _participationRepository) : base(_context) + public CheatInfoRepository(AppDbContext context, + IParticipationRepository participationRepository) : base(context) { - participationRepository = _participationRepository; + _participationRepository = participationRepository; } public async Task CreateCheatInfo(Submission submission, Instance source, CancellationToken token = default) { - var submit = await participationRepository.GetParticipation(submission.Team, submission.Game, token); + var submit = await _participationRepository.GetParticipation(submission.Team, submission.Game, token); if (submit is null) throw new NullReferenceException(nameof(submit)); @@ -29,13 +29,13 @@ public async Task CreateCheatInfo(Submission submission, Instance sou SourceTeam = source.Participation }; - await context.AddAsync(info, token); + await _context.AddAsync(info, token); return info; } public Task GetCheatInfoByGameId(int gameId, CancellationToken token = default) - => context.CheatInfo.IgnoreAutoIncludes().Where(i => i.GameId == gameId) + => _context.CheatInfo.IgnoreAutoIncludes().Where(i => i.GameId == gameId) .Include(i => i.SourceTeam).ThenInclude(t => t.Team) .Include(i => i.SubmitTeam).ThenInclude(t => t.Team) .Include(i => i.Submission).ThenInclude(s => s.User) diff --git a/src/GZCTF/Repositories/ContainerRepository.cs b/src/GZCTF/Repositories/ContainerRepository.cs index 6d456c6a9..5338881f2 100644 --- a/src/GZCTF/Repositories/ContainerRepository.cs +++ b/src/GZCTF/Repositories/ContainerRepository.cs @@ -6,20 +6,20 @@ namespace GZCTF.Repositories; public class ContainerRepository : RepositoryBase, IContainerRepository { - public ContainerRepository(AppDbContext _context) : base(_context) + public ContainerRepository(AppDbContext context) : base(context) { } - public override Task CountAsync(CancellationToken token = default) => context.Containers.CountAsync(token); + public override Task CountAsync(CancellationToken token = default) => _context.Containers.CountAsync(token); public Task GetContainerById(string guid, CancellationToken token = default) - => context.Containers.FirstOrDefaultAsync(i => i.Id == guid, token); + => _context.Containers.FirstOrDefaultAsync(i => i.Id == guid, token); public Task> GetContainers(CancellationToken token = default) - => context.Containers.ToListAsync(token); + => _context.Containers.ToListAsync(token); public async Task GetContainerInstances(CancellationToken token = default) - => (await context.Containers + => (await _context.Containers .Where(c => c.Instance != null) .Include(c => c.Instance).ThenInclude(i => i!.Participation) .OrderBy(c => c.StartedAt).ToArrayAsync(token)) @@ -29,7 +29,7 @@ public async Task GetContainerInstances(CancellationTo public Task> GetDyingContainers(CancellationToken token = default) { var now = DateTimeOffset.UtcNow; - return context.Containers.Where(c => c.ExpectStopAt < now).ToListAsync(token); + return _context.Containers.Where(c => c.ExpectStopAt < now).ToListAsync(token); } public Task RemoveContainer(Container container, CancellationToken token = default) @@ -38,7 +38,7 @@ public Task RemoveContainer(Container container, CancellationToken token = defau if (container.Status != ContainerStatus.Destroyed) return Task.FromResult(-1); - context.Containers.Remove(container); + _context.Containers.Remove(container); return SaveAsync(token); } } diff --git a/src/GZCTF/Repositories/FileRepository.cs b/src/GZCTF/Repositories/FileRepository.cs index 59780edf6..f4556abe6 100644 --- a/src/GZCTF/Repositories/FileRepository.cs +++ b/src/GZCTF/Repositories/FileRepository.cs @@ -8,17 +8,17 @@ namespace GZCTF.Repositories; public class FileRepository : RepositoryBase, IFileRepository { - private readonly ILogger logger; - private readonly string uploadPath; + private readonly ILogger _logger; + private readonly string _uploadPath; - public FileRepository(AppDbContext context, IConfiguration _configuration, - ILogger _logger) : base(context) + public FileRepository(AppDbContext context, IConfiguration configuration, + ILogger logger) : base(context) { - logger = _logger; - uploadPath = _configuration.GetSection("UploadFolder")?.Value ?? "uploads"; + _logger = logger; + _uploadPath = configuration.GetSection("UploadFolder")?.Value ?? "uploads"; } - public override Task CountAsync(CancellationToken token = default) => context.Files.CountAsync(token); + public override Task CountAsync(CancellationToken token = default) => _context.Files.CountAsync(token); private static Stream GetStream(long bufferSize) => bufferSize <= 16 * 1024 * 1024 ? new MemoryStream() : File.Create(Path.GetTempFileName(), 4096, FileOptions.DeleteOnClose); @@ -38,16 +38,16 @@ private async Task StoreLocalFile(string fileName, Stream contentStre localFile.UploadTimeUTC = DateTimeOffset.UtcNow; // update upload time localFile.ReferenceCount++; // same hash, add ref count - logger.SystemLog($"文件引用计数 [{localFile.Hash[..8]}] {localFile.Name} => {localFile.ReferenceCount}", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog($"文件引用计数 [{localFile.Hash[..8]}] {localFile.Name} => {localFile.ReferenceCount}", TaskStatus.Success, LogLevel.Debug); - context.Update(localFile); + _context.Update(localFile); } else { localFile = new() { Hash = fileHash, Name = fileName, FileSize = contentStream.Length }; - await context.AddAsync(localFile, token); + await _context.AddAsync(localFile, token); - var path = Path.Combine(uploadPath, localFile.Location); + var path = Path.Combine(_uploadPath, localFile.Location); if (!Directory.Exists(path)) Directory.CreateDirectory(path); @@ -66,7 +66,7 @@ public async Task CreateOrUpdateFile(IFormFile file, string? fileName { using var tmp = GetStream(file.Length); - logger.SystemLog($"缓存位置:{tmp.GetType()}", TaskStatus.Pending, LogLevel.Trace); + _logger.SystemLog($"缓存位置:{tmp.GetType()}", TaskStatus.Pending, LogLevel.Trace); await file.CopyToAsync(tmp, token); return await StoreLocalFile(fileName ?? file.FileName, tmp, token); @@ -101,38 +101,38 @@ public async Task CreateOrUpdateFile(IFormFile file, string? fileName } catch { - logger.SystemLog($"无法存储图像文件:{file.Name}", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"无法存储图像文件:{file.Name}", TaskStatus.Failed, LogLevel.Warning); return null; } } public async Task DeleteFile(LocalFile file, CancellationToken token = default) { - var path = Path.Combine(uploadPath, file.Location, file.Hash); + var path = Path.Combine(_uploadPath, file.Location, file.Hash); if (file.ReferenceCount > 1) { file.ReferenceCount--; // other ref exists, decrease ref count - logger.SystemLog($"文件引用计数 [{file.Hash[..8]}] {file.Name} => {file.ReferenceCount}", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog($"文件引用计数 [{file.Hash[..8]}] {file.Name} => {file.ReferenceCount}", TaskStatus.Success, LogLevel.Debug); await SaveAsync(token); return TaskStatus.Success; } - logger.SystemLog($"删除文件 [{file.Hash[..8]}] {file.Name}", TaskStatus.Pending, LogLevel.Information); + _logger.SystemLog($"删除文件 [{file.Hash[..8]}] {file.Name}", TaskStatus.Pending, LogLevel.Information); if (File.Exists(path)) { File.Delete(path); - context.Files.Remove(file); + _context.Files.Remove(file); await SaveAsync(token); return TaskStatus.Success; } - context.Files.Remove(file); + _context.Files.Remove(file); await SaveAsync(token); return TaskStatus.NotFound; @@ -149,8 +149,8 @@ public async Task DeleteFileByHash(string fileHash, CancellationToke } public Task GetFileByHash(string? fileHash, CancellationToken token = default) - => context.Files.SingleOrDefaultAsync(f => f.Hash == fileHash, token); + => _context.Files.SingleOrDefaultAsync(f => f.Hash == fileHash, token); public Task GetFiles(int count, int skip, CancellationToken token = default) - => context.Files.OrderBy(e => e.Name).Skip(skip).Take(count).ToArrayAsync(token); + => _context.Files.OrderBy(e => e.Name).Skip(skip).Take(count).ToArrayAsync(token); } diff --git a/src/GZCTF/Repositories/GameEventRepository.cs b/src/GZCTF/Repositories/GameEventRepository.cs index 9e5dc195e..89f824e14 100644 --- a/src/GZCTF/Repositories/GameEventRepository.cs +++ b/src/GZCTF/Repositories/GameEventRepository.cs @@ -8,23 +8,23 @@ namespace GZCTF.Repositories; public class GameEventRepository : RepositoryBase, IGameEventRepository { - private readonly IHubContext hubContext; + private readonly IHubContext _hubContext; public GameEventRepository( IHubContext hub, - AppDbContext _context) : base(_context) + AppDbContext context) : base(context) { - hubContext = hub; + _hubContext = hub; } public async Task AddEvent(GameEvent gameEvent, CancellationToken token = default) { - await context.AddAsync(gameEvent); + await _context.AddAsync(gameEvent, token); await SaveAsync(token); - gameEvent = await context.GameEvents.SingleAsync(s => s.Id == gameEvent.Id, token); + gameEvent = await _context.GameEvents.SingleAsync(s => s.Id == gameEvent.Id, token); - await hubContext.Clients.Group($"Game_{gameEvent.GameId}") + await _hubContext.Clients.Group($"Game_{gameEvent.GameId}") .ReceivedGameEvent(gameEvent); return gameEvent; @@ -32,7 +32,7 @@ await hubContext.Clients.Group($"Game_{gameEvent.GameId}") public Task GetEvents(int gameId, bool hideContainer = false, int count = 50, int skip = 0, CancellationToken token = default) { - var data = context.GameEvents.Where(e => e.GameId == gameId); + var data = _context.GameEvents.Where(e => e.GameId == gameId); if (hideContainer) data = data.Where(e => e.Type != EventType.ContainerStart && e.Type != EventType.ContainerDestroy); diff --git a/src/GZCTF/Repositories/GameNoticeRepository.cs b/src/GZCTF/Repositories/GameNoticeRepository.cs index d5c20419e..a9da81d13 100644 --- a/src/GZCTF/Repositories/GameNoticeRepository.cs +++ b/src/GZCTF/Repositories/GameNoticeRepository.cs @@ -10,54 +10,54 @@ namespace GZCTF.Repositories; public class GameNoticeRepository : RepositoryBase, IGameNoticeRepository { - private readonly IDistributedCache cache; - private readonly ILogger logger; - private readonly IHubContext hubContext; + private readonly IDistributedCache _cache; + private readonly ILogger _logger; + private readonly IHubContext _hubContext; - public GameNoticeRepository(IDistributedCache _cache, - ILogger _logger, + public GameNoticeRepository(IDistributedCache cache, + ILogger logger, IHubContext hub, - AppDbContext _context) : base(_context) + AppDbContext context) : base(context) { - cache = _cache; - logger = _logger; - hubContext = hub; + _cache = cache; + _logger = logger; + _hubContext = hub; } public async Task AddNotice(GameNotice notice, CancellationToken token = default) { - await context.AddAsync(notice, token); + await _context.AddAsync(notice, token); await SaveAsync(token); - cache.Remove(CacheKey.GameNotice(notice.GameId)); + _cache.Remove(CacheKey.GameNotice(notice.GameId)); - await hubContext.Clients.Group($"Game_{notice.GameId}") + await _hubContext.Clients.Group($"Game_{notice.GameId}") .ReceivedGameNotice(notice); return notice; } public Task GetNormalNotices(int gameId, CancellationToken token = default) - => context.GameNotices + => _context.GameNotices .Where(n => n.GameId == gameId && n.Type == NoticeType.Normal) .ToArrayAsync(token); public Task GetNoticeById(int gameId, int noticeId, CancellationToken token = default) - => context.GameNotices.FirstOrDefaultAsync(e => e.Id == noticeId && e.GameId == gameId, token); + => _context.GameNotices.FirstOrDefaultAsync(e => e.Id == noticeId && e.GameId == gameId, token); public Task GetNotices(int gameId, int count = 100, int skip = 0, CancellationToken token = default) - => cache.GetOrCreateAsync(logger, CacheKey.GameNotice(gameId), (entry) => + => _cache.GetOrCreateAsync(_logger, CacheKey.GameNotice(gameId), (entry) => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30); - return context.GameNotices.Where(e => e.GameId == gameId) + return _context.GameNotices.Where(e => e.GameId == gameId) .OrderByDescending(e => e.Type == NoticeType.Normal ? DateTimeOffset.UtcNow : e.PublishTimeUTC) .Skip(skip).Take(count).ToArrayAsync(token); }, token); public Task RemoveNotice(GameNotice notice, CancellationToken token = default) { - context.Remove(notice); - cache.Remove(CacheKey.GameNotice(notice.GameId)); + _context.Remove(notice); + _cache.Remove(CacheKey.GameNotice(notice.GameId)); return SaveAsync(token); } @@ -67,7 +67,7 @@ public async Task UpdateNotice(GameNotice notice, CancellationToken notice.PublishTimeUTC = DateTimeOffset.UtcNow; await SaveAsync(token); - cache.Remove(CacheKey.GameNotice(notice.GameId)); + _cache.Remove(CacheKey.GameNotice(notice.GameId)); return notice; } diff --git a/src/GZCTF/Repositories/GameRepository.cs b/src/GZCTF/Repositories/GameRepository.cs index cb877cde0..56b610d0e 100644 --- a/src/GZCTF/Repositories/GameRepository.cs +++ b/src/GZCTF/Repositories/GameRepository.cs @@ -12,63 +12,64 @@ namespace GZCTF.Repositories; public class GameRepository : RepositoryBase, IGameRepository { - private readonly IDistributedCache cache; - private readonly ITeamRepository teamRepository; - private readonly byte[]? xorkey; - private readonly ILogger logger; - private readonly ChannelWriter cacheRequestChannelWriter; - - public GameRepository(IDistributedCache _cache, - ITeamRepository _teamRepository, - IConfiguration _configuration, - ILogger _logger, - ChannelWriter _cacheRequestChannelWriter, - AppDbContext _context) : base(_context) + private readonly IDistributedCache _cache; + private readonly ITeamRepository _teamRepository; + private readonly byte[]? _xorkey; + private readonly ILogger _logger; + private readonly ChannelWriter _cacheRequestChannelWriter; + + public GameRepository(IDistributedCache cache, + ITeamRepository teamRepository, + IConfiguration configuration, + ILogger logger, + ChannelWriter cacheRequestChannelWriter, + AppDbContext context) : base(context) { - cache = _cache; - logger = _logger; - teamRepository = _teamRepository; - cacheRequestChannelWriter = _cacheRequestChannelWriter; - var xorkeyStr = _configuration["XorKey"]; - xorkey = string.IsNullOrEmpty(xorkeyStr) ? null : Encoding.UTF8.GetBytes(xorkeyStr); + _cache = cache; + _logger = logger; + _teamRepository = teamRepository; + _cacheRequestChannelWriter = cacheRequestChannelWriter; + + var xorkeyStr = configuration["XorKey"]; + _xorkey = string.IsNullOrEmpty(xorkeyStr) ? null : Encoding.UTF8.GetBytes(xorkeyStr); } - public override Task CountAsync(CancellationToken token = default) => context.Games.CountAsync(token); + public override Task CountAsync(CancellationToken token = default) => _context.Games.CountAsync(token); public async Task CreateGame(Game game, CancellationToken token = default) { - game.GenerateKeyPair(xorkey); + game.GenerateKeyPair(_xorkey); - if (xorkey is null) - logger.SystemLog("配置文件中的异或密钥未设置,比赛私钥将会被明文存储至数据库。", TaskStatus.Pending, LogLevel.Warning); + if (_xorkey is null) + _logger.SystemLog("配置文件中的异或密钥未设置,比赛私钥将会被明文存储至数据库。", TaskStatus.Pending, LogLevel.Warning); - await context.AddAsync(game, token); + await _context.AddAsync(game, token); await SaveAsync(token); return game; } public string GetToken(Game game, Team team) - => $"{team.Id}:{game.Sign($"GZCTF_TEAM_{team.Id}", xorkey)}"; + => $"{team.Id}:{game.Sign($"GZCTF_TEAM_{team.Id}", _xorkey)}"; public Task GetGameById(int id, CancellationToken token = default) - => context.Games.FirstOrDefaultAsync(x => x.Id == id, token); + => _context.Games.FirstOrDefaultAsync(x => x.Id == id, token); public Task GetUpcomingGames(CancellationToken token = default) - => context.Games.Where(g => g.StartTimeUTC > DateTime.UtcNow + => _context.Games.Where(g => g.StartTimeUTC > DateTime.UtcNow && g.StartTimeUTC - DateTime.UtcNow < TimeSpan.FromMinutes(5)) .OrderBy(g => g.StartTimeUTC).Select(g => g.Id).ToArrayAsync(token); public async Task GetBasicGameInfo(int count = 10, int skip = 0, CancellationToken token = default) - => await cache.GetOrCreateAsync(logger, CacheKey.BasicGameInfo, entry => + => await _cache.GetOrCreateAsync(_logger, CacheKey.BasicGameInfo, entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(2); - return context.Games.Where(g => !g.Hidden) + return _context.Games.Where(g => !g.Hidden) .OrderByDescending(g => g.StartTimeUTC).Skip(skip).Take(count) .Select(g => BasicGameInfoModel.FromGame(g)).ToArrayAsync(token); }, token); public Task GetScoreboard(Game game, CancellationToken token = default) - => cache.GetOrCreateAsync(logger, CacheKey.ScoreBoard(game.Id), entry => + => _cache.GetOrCreateAsync(_logger, CacheKey.ScoreBoard(game.Id), entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(7); return GenScoreboard(game, token); @@ -81,7 +82,7 @@ public async Task GetScoreboardWithMembers(Game game, Cancellat foreach (var item in scoreboard.Items) { - item.TeamInfo = await teamRepository.GetTeamById(item.Id, token) ?? + item.TeamInfo = await _teamRepository.GetTeamById(item.Id, token) ?? throw new ArgumentNullException("team", "Team not found"); } @@ -91,21 +92,21 @@ public async Task GetScoreboardWithMembers(Game game, Cancellat public async Task DeleteGame(Game game, CancellationToken token = default) { - context.Remove(game); - cache.Remove(CacheKey.BasicGameInfo); - cache.Remove(CacheKey.ScoreBoard(game.Id)); + _context.Remove(game); + _cache.Remove(CacheKey.BasicGameInfo); + _cache.Remove(CacheKey.ScoreBoard(game.Id)); await SaveAsync(token); } public Task GetGames(int count, int skip, CancellationToken token) - => context.Games.OrderByDescending(g => g.Id).Skip(skip).Take(count).ToArrayAsync(token); + => _context.Games.OrderByDescending(g => g.Id).Skip(skip).Take(count).ToArrayAsync(token); public void FlushGameInfoCache() - => cache.Remove(CacheKey.BasicGameInfo); + => _cache.Remove(CacheKey.BasicGameInfo); public async Task FlushScoreboardCache(int gameId, CancellationToken token) - => await cacheRequestChannelWriter.WriteAsync(ScoreboardCacheHandler.MakeCacheRequest(gameId), token); + => await _cacheRequestChannelWriter.WriteAsync(ScoreboardCacheHandler.MakeCacheRequest(gameId), token); #region Generate Scoreboard @@ -127,14 +128,14 @@ public async Task GenScoreboard(Game game, CancellationToken to } private Task FetchData(Game game, CancellationToken token = default) - => context.Instances + => _context.Instances .Include(i => i.Challenge) .Where(i => i.Challenge.Game == game && i.Challenge.IsEnabled && i.Participation.Status == ParticipationStatus.Accepted) .Include(i => i.Participation).ThenInclude(p => p.Team).ThenInclude(t => t.Members) .GroupJoin( - context.Submissions.Where(s => s.Status == AnswerResult.Accepted + _context.Submissions.Where(s => s.Status == AnswerResult.Accepted && s.SubmitTimeUTC < game.EndTimeUTC), i => new { i.ChallengeId, i.ParticipationId }, s => new { s.ChallengeId, s.ParticipationId }, diff --git a/src/GZCTF/Repositories/InstanceRepository.cs b/src/GZCTF/Repositories/InstanceRepository.cs index 36cbaa872..64ee00c39 100644 --- a/src/GZCTF/Repositories/InstanceRepository.cs +++ b/src/GZCTF/Repositories/InstanceRepository.cs @@ -9,41 +9,41 @@ namespace GZCTF.Repositories; public class InstanceRepository : RepositoryBase, IInstanceRepository { - private readonly IContainerService service; - private readonly ICheatInfoRepository cheatInfoRepository; - private readonly IContainerRepository containerRepository; - private readonly IGameEventRepository gameEventRepository; - private readonly ILogger logger; - private readonly IOptionsSnapshot gamePolicy; - - public InstanceRepository(AppDbContext _context, - IContainerService _service, - ICheatInfoRepository _cheatInfoRepository, - IContainerRepository _containerRepository, - IGameEventRepository _gameEventRepository, - IOptionsSnapshot _gamePolicy, - ILogger _logger) : base(_context) + private readonly IContainerService _service; + private readonly ICheatInfoRepository _cheatInfoRepository; + private readonly IContainerRepository _containerRepository; + private readonly IGameEventRepository _gameEventRepository; + private readonly ILogger _logger; + private readonly IOptionsSnapshot _gamePolicy; + + public InstanceRepository(AppDbContext context, + IContainerService service, + ICheatInfoRepository cheatInfoRepository, + IContainerRepository containerRepository, + IGameEventRepository gameEventRepository, + IOptionsSnapshot gamePolicy, + ILogger logger) : base(context) { - logger = _logger; - service = _service; - gamePolicy = _gamePolicy; - cheatInfoRepository = _cheatInfoRepository; - gameEventRepository = _gameEventRepository; - containerRepository = _containerRepository; + _logger = logger; + _service = service; + _gamePolicy = gamePolicy; + _cheatInfoRepository = cheatInfoRepository; + _gameEventRepository = gameEventRepository; + _containerRepository = containerRepository; } public async Task GetInstance(Participation part, int challengeId, CancellationToken token = default) { - using var transaction = await context.Database.BeginTransactionAsync(token); + using var transaction = await _context.Database.BeginTransactionAsync(token); - var instance = await context.Instances + var instance = await _context.Instances .Include(i => i.FlagContext) .Where(e => e.ChallengeId == challengeId && e.Participation == part) .SingleOrDefaultAsync(token); if (instance is null) { - logger.SystemLog($"队伍对应参与对象为空,这可能是非预期的情况 [{part.Id}, {challengeId}]", TaskStatus.NotFound, LogLevel.Warning); + _logger.SystemLog($"队伍对应参与对象为空,这可能是非预期的情况 [{part.Id}, {challengeId}]", TaskStatus.NotFound, LogLevel.Warning); return null; } @@ -77,13 +77,13 @@ public InstanceRepository(AppDbContext _context, }; break; case ChallengeType.DynamicAttachment: - var flags = await context.FlagContexts + var flags = await _context.FlagContexts .Where(e => e.Challenge == challenge && !e.IsOccupied) .ToListAsync(token); if (flags.Count == 0) { - logger.SystemLog($"题目 {challenge.Title}#{challenge.Id} 请求分配的动态附件数量不足", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"题目 {challenge.Title}#{challenge.Id} 请求分配的动态附件数量不足", TaskStatus.Failed, LogLevel.Warning); return null; } @@ -105,7 +105,7 @@ public InstanceRepository(AppDbContext _context, } catch { - logger.SystemLog($"为队伍 {part.Team.Name} 获取题目 {challenge.Title}#{challenge.Id} 的实例时遇到问题(可能由于并发错误),回滚中", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"为队伍 {part.Team.Name} 获取题目 {challenge.Title}#{challenge.Id} 的实例时遇到问题(可能由于并发错误),回滚中", TaskStatus.Failed, LogLevel.Warning); await transaction.RollbackAsync(token); return null; } @@ -117,13 +117,13 @@ public async Task DestroyContainer(Container container, CancellationToken { try { - await service.DestroyContainerAsync(container, token); - await containerRepository.RemoveContainer(container, token); + await _service.DestroyContainerAsync(container, token); + await _containerRepository.RemoveContainer(container, token); return true; } catch (Exception ex) { - logger.SystemLog($"销毁容器 [{container.ContainerId[..12]}] ({container.Image.Split("/").LastOrDefault()}): {ex.Message}", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"销毁容器 [{container.ContainerId[..12]}] ({container.Image.Split("/").LastOrDefault()}): {ex.Message}", TaskStatus.Failed, LogLevel.Warning); return false; } } @@ -132,29 +132,29 @@ public async Task> CreateContainer(Instance instance, Team { if (string.IsNullOrEmpty(instance.Challenge.ContainerImage) || instance.Challenge.ContainerExposePort is null) { - logger.SystemLog($"无法为题目 {instance.Challenge.Title} 启动容器实例", TaskStatus.Denied, LogLevel.Warning); + _logger.SystemLog($"无法为题目 {instance.Challenge.Title} 启动容器实例", TaskStatus.Denied, LogLevel.Warning); return new TaskResult(TaskStatus.Failed); } // containerLimit == 0 means unlimit if (containerLimit > 0) { - if (gamePolicy.Value.AutoDestroyOnLimitReached) + if (_gamePolicy.Value.AutoDestroyOnLimitReached) { - var running = await context.Instances + var running = await _context.Instances .Where(i => i.Participation == instance.Participation && i.Container != null) .OrderBy(i => i.Container!.StartedAt).ToListAsync(token); var first = running.FirstOrDefault(); if (running.Count >= containerLimit && first is not null) { - logger.Log($"{team.Name} 自动销毁题目 {first.Challenge.Title} 的容器实例 [{first.Container!.ContainerId}]", user, TaskStatus.Success); + _logger.Log($"{team.Name} 自动销毁题目 {first.Challenge.Title} 的容器实例 [{first.Container!.ContainerId}]", user, TaskStatus.Success); await DestroyContainer(running.First().Container!, token); } } else { - var count = await context.Instances.CountAsync( + var count = await _context.Instances.CountAsync( i => i.Participation == instance.Participation && i.Container != null, token); @@ -165,8 +165,8 @@ public async Task> CreateContainer(Instance instance, Team if (instance.Container is null) { - await context.Entry(instance).Reference(e => e.FlagContext).LoadAsync(token); - var container = await service.CreateContainerAsync(new ContainerConfig() + await _context.Entry(instance).Reference(e => e.FlagContext).LoadAsync(token); + var container = await _service.CreateContainerAsync(new ContainerConfig() { TeamId = team.Id.ToString(), UserId = user.Id, @@ -181,17 +181,17 @@ public async Task> CreateContainer(Instance instance, Team if (container is null) { - logger.SystemLog($"为题目 {instance.Challenge.Title} 启动容器实例失败", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"为题目 {instance.Challenge.Title} 启动容器实例失败", TaskStatus.Failed, LogLevel.Warning); return new TaskResult(TaskStatus.Failed); } instance.Container = container; instance.LastContainerOperation = DateTimeOffset.UtcNow; - logger.Log($"{team.Name} 启动题目 {instance.Challenge.Title} 的容器实例 [{container.ContainerId}]", user, TaskStatus.Success); + _logger.Log($"{team.Name} 启动题目 {instance.Challenge.Title} 的容器实例 [{container.ContainerId}]", user, TaskStatus.Success); // will save instance together - await gameEventRepository.AddEvent(new() + await _gameEventRepository.AddEvent(new() { Type = EventType.ContainerStart, GameId = instance.Challenge.GameId, @@ -211,14 +211,14 @@ public async Task ProlongContainer(Container container, TimeSpan time, Cancellat } public Task GetInstances(Challenge challenge, CancellationToken token = default) - => context.Instances.Where(i => i.Challenge == challenge).OrderBy(i => i.ParticipationId) + => _context.Instances.Where(i => i.Challenge == challenge).OrderBy(i => i.ParticipationId) .Include(i => i.Participation).ThenInclude(i => i.Team).ToArrayAsync(token); public async Task CheckCheat(Submission submission, CancellationToken token = default) { CheatCheckInfo checkInfo = new(); - var instances = await context.Instances.Where(i => i.ChallengeId == submission.ChallengeId && + var instances = await _context.Instances.Where(i => i.ChallengeId == submission.ChallengeId && i.ParticipationId != submission.ParticipationId) .Include(i => i.FlagContext).Include(i => i.Participation) .ThenInclude(i => i.Team).ToArrayAsync(token); @@ -227,9 +227,9 @@ public async Task CheckCheat(Submission submission, Cancellation { if (instance.FlagContext?.Flag == submission.Answer) { - var updateSub = await context.Submissions.Where(s => s.Id == submission.Id).SingleAsync(token); + var updateSub = await _context.Submissions.Where(s => s.Id == submission.Id).SingleAsync(token); - var cheatInfo = await cheatInfoRepository.CreateCheatInfo(updateSub, instance, token); + var cheatInfo = await _cheatInfoRepository.CreateCheatInfo(updateSub, instance, token); checkInfo = CheatCheckInfo.FromCheatInfo(cheatInfo); if (updateSub is not null) @@ -246,12 +246,12 @@ public async Task CheckCheat(Submission submission, Cancellation public async Task VerifyAnswer(Submission submission, CancellationToken token = default) { - var trans = await context.Database.BeginTransactionAsync(token); + var trans = await _context.Database.BeginTransactionAsync(token); try { - var instance = await context.Instances + var instance = await _context.Instances .IgnoreAutoIncludes() .Include(i => i.FlagContext) .SingleOrDefaultAsync(i => i.ChallengeId == submission.ChallengeId && @@ -259,7 +259,7 @@ public async Task VerifyAnswer(Submission submission, Cancellation // submission is from the queue, do not modify it directly // we need to requery the entity to ensure it is being tracked correctly - var updateSub = await context.Submissions.SingleAsync(s => s.Id == submission.Id, token); + var updateSub = await _context.Submissions.SingleAsync(s => s.Id == submission.Id, token); var ret = SubmissionType.Unaccepted; @@ -271,7 +271,7 @@ public async Task VerifyAnswer(Submission submission, Cancellation if (instance.FlagContext is null && submission.Challenge.Type.IsStatic()) { - updateSub.Status = await context.FlagContexts + updateSub.Status = await _context.FlagContexts .AsNoTracking() .AnyAsync( f => f.ChallengeId == submission.ChallengeId && f.Flag == submission.Answer, diff --git a/src/GZCTF/Repositories/LogRepository.cs b/src/GZCTF/Repositories/LogRepository.cs index 52d3bc7ca..1ecb968d2 100644 --- a/src/GZCTF/Repositories/LogRepository.cs +++ b/src/GZCTF/Repositories/LogRepository.cs @@ -6,13 +6,13 @@ namespace GZCTF.Repositories; public class LogRepository : RepositoryBase, ILogRepository { - public LogRepository(AppDbContext _context) : base(_context) + public LogRepository(AppDbContext context) : base(context) { } public Task GetLogs(int skip, int count, string? level, CancellationToken token) { - IQueryable data = context.Logs; + IQueryable data = _context.Logs; if (level is not null && level != "All") data = data.Where(x => x.Level == level); diff --git a/src/GZCTF/Repositories/ParticipationRepository.cs b/src/GZCTF/Repositories/ParticipationRepository.cs index 1157eff08..634c02c88 100644 --- a/src/GZCTF/Repositories/ParticipationRepository.cs +++ b/src/GZCTF/Repositories/ParticipationRepository.cs @@ -6,21 +6,21 @@ namespace GZCTF.Repositories; public class ParticipationRepository : RepositoryBase, IParticipationRepository { - private readonly IGameRepository gameRepository; + private readonly IGameRepository _gameRepository; public ParticipationRepository( - IGameRepository _gameRepository, - AppDbContext _context) : base(_context) + IGameRepository gameRepository, + AppDbContext context) : base(context) { - gameRepository = _gameRepository; + _gameRepository = gameRepository; } public async Task EnsureInstances(Participation part, Game game, CancellationToken token = default) { - var challenges = await context.Challenges.Where(c => c.Game == game && c.IsEnabled).ToArrayAsync(token); + var challenges = await _context.Challenges.Where(c => c.Game == game && c.IsEnabled).ToArrayAsync(token); // requery instead of Entry - part = await context.Participations.Include(p => p.Challenges).SingleAsync(p => p.Id == part.Id, token); + part = await _context.Participations.Include(p => p.Challenges).SingleAsync(p => p.Id == part.Id, token); bool update = false; @@ -33,31 +33,31 @@ public async Task EnsureInstances(Participation part, Game game, Cancellat } public Task GetParticipationById(int id, CancellationToken token = default) - => context.Participations.FirstOrDefaultAsync(p => p.Id == id, token); + => _context.Participations.FirstOrDefaultAsync(p => p.Id == id, token); public Task GetParticipation(Team team, Game game, CancellationToken token = default) - => context.Participations.FirstOrDefaultAsync(e => e.Team == team && e.Game == game, token); + => _context.Participations.FirstOrDefaultAsync(e => e.Team == team && e.Game == game, token); public Task GetParticipation(UserInfo user, Game game, CancellationToken token = default) - => context.Participations.FirstOrDefaultAsync(p => p.Members.Any(m => m.Game == game && m.User == user), token); + => _context.Participations.FirstOrDefaultAsync(p => p.Members.Any(m => m.Game == game && m.User == user), token); public Task GetParticipationCount(Game game, CancellationToken token = default) - => context.Participations.Where(p => p.GameId == game.Id).CountAsync(token); + => _context.Participations.Where(p => p.GameId == game.Id).CountAsync(token); public Task GetParticipations(Game game, CancellationToken token = default) - => context.Participations.Where(p => p.GameId == game.Id) + => _context.Participations.Where(p => p.GameId == game.Id) .Include(p => p.Team) .ThenInclude(t => t.Members) .OrderBy(p => p.TeamId).ToArrayAsync(token); public Task GetWriteups(Game game, CancellationToken token = default) - => context.Participations.Where(p => p.Game == game && p.Writeup != null) + => _context.Participations.Where(p => p.Game == game && p.Writeup != null) .OrderByDescending(p => p.Writeup!.UploadTimeUTC) .Select(p => WriteupInfoModel.FromParticipation(p)!) .ToArrayAsync(token); public Task CheckRepeatParticipation(UserInfo user, Game game, CancellationToken token = default) - => context.UserParticipations.Include(p => p.Participation) + => _context.UserParticipations.Include(p => p.Participation) .AnyAsync(p => p.User == user && p.Game == game && p.Participation.Status != ParticipationStatus.Rejected, token); @@ -75,7 +75,7 @@ public async Task UpdateParticipationStatus(Participation part, ParticipationSta // also flush scoreboard when a team is re-accepted if (await EnsureInstances(part, part.Game, token) || oldStatus == ParticipationStatus.Suspended) // flush scoreboard when instances are updated - await gameRepository.FlushScoreboardCache(part.Game.Id, token); + await _gameRepository.FlushScoreboardCache(part.Game.Id, token); return; } @@ -85,20 +85,20 @@ public async Task UpdateParticipationStatus(Participation part, ParticipationSta // flush scoreboard when a team is suspended if (status == ParticipationStatus.Suspended && part.Game.IsActive) - await gameRepository.FlushScoreboardCache(part.GameId, token); + await _gameRepository.FlushScoreboardCache(part.GameId, token); } public async Task RemoveUserParticipations(UserInfo user, Game game, CancellationToken token = default) - => context.RemoveRange(await context.UserParticipations + => _context.RemoveRange(await _context.UserParticipations .Where(p => p.User == user && p.Game == game).ToArrayAsync(token)); public async Task RemoveUserParticipations(UserInfo user, Team team, CancellationToken token = default) - => context.RemoveRange(await context.UserParticipations + => _context.RemoveRange(await _context.UserParticipations .Where(p => p.User == user && p.Team == team).ToArrayAsync(token)); public Task RemoveParticipation(Participation part, CancellationToken token = default) { - context.Remove(part); + _context.Remove(part); return SaveAsync(token); } } diff --git a/src/GZCTF/Repositories/PostRepository.cs b/src/GZCTF/Repositories/PostRepository.cs index 6f92c17b1..9ce9c8b3d 100644 --- a/src/GZCTF/Repositories/PostRepository.cs +++ b/src/GZCTF/Repositories/PostRepository.cs @@ -7,57 +7,57 @@ namespace GZCTF.Repositories; public class PostRepository : RepositoryBase, IPostRepository { - private readonly IDistributedCache cache; - private readonly ILogger logger; + private readonly IDistributedCache _cache; + private readonly ILogger _logger; - public PostRepository(IDistributedCache _cache, - ILogger _logger, - AppDbContext _context) : base(_context) + public PostRepository(IDistributedCache cache, + ILogger logger, + AppDbContext context) : base(context) { - cache = _cache; - logger = _logger; + _cache = cache; + _logger = logger; } - public override Task CountAsync(CancellationToken token = default) => context.Posts.CountAsync(token); + public override Task CountAsync(CancellationToken token = default) => _context.Posts.CountAsync(token); public async Task CreatePost(Post post, CancellationToken token = default) { post.UpdateKeyWithHash(); - await context.AddAsync(post, token); + await _context.AddAsync(post, token); await SaveAsync(token); - cache.Remove(CacheKey.Posts); + _cache.Remove(CacheKey.Posts); return post; } public Task GetPostById(string id, CancellationToken token = default) - => context.Posts.FirstOrDefaultAsync(p => p.Id == id, token); + => _context.Posts.FirstOrDefaultAsync(p => p.Id == id, token); public async Task GetPostByIdFromCache(string id, CancellationToken token = default) => (await GetPosts(token)).FirstOrDefault(p => p.Id == id); public Task GetPosts(CancellationToken token = default) - => cache.GetOrCreateAsync(logger, CacheKey.Posts, entry => + => _cache.GetOrCreateAsync(_logger, CacheKey.Posts, entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12); - return context.Posts.AsNoTracking().OrderByDescending(n => n.IsPinned) + return _context.Posts.AsNoTracking().OrderByDescending(n => n.IsPinned) .ThenByDescending(n => n.UpdateTimeUTC).ToArrayAsync(token); }, token); public async Task RemovePost(Post post, CancellationToken token = default) { - context.Remove(post); + _context.Remove(post); await SaveAsync(token); - cache.Remove(CacheKey.Posts); + _cache.Remove(CacheKey.Posts); } public async Task UpdatePost(Post post, CancellationToken token = default) { - context.Update(post); + _context.Update(post); await SaveAsync(token); - cache.Remove(CacheKey.Posts); + _cache.Remove(CacheKey.Posts); } } diff --git a/src/GZCTF/Repositories/RepositoryBase.cs b/src/GZCTF/Repositories/RepositoryBase.cs index 689b37f07..8aafd365e 100644 --- a/src/GZCTF/Repositories/RepositoryBase.cs +++ b/src/GZCTF/Repositories/RepositoryBase.cs @@ -6,15 +6,15 @@ namespace GZCTF.Repositories; public class RepositoryBase : IRepository { - protected readonly AppDbContext context; + protected readonly AppDbContext _context; - public RepositoryBase(AppDbContext _context) - => context = _context; + public RepositoryBase(AppDbContext context) + => _context = context; public Task BeginTransactionAsync(CancellationToken token = default) - => context.Database.BeginTransactionAsync(token); + => _context.Database.BeginTransactionAsync(token); - public string ChangeTrackerView => context.ChangeTracker.DebugView.LongView; + public string ChangeTrackerView => _context.ChangeTracker.DebugView.LongView; public async Task SaveAsync(CancellationToken token = default) { @@ -23,13 +23,12 @@ public async Task SaveAsync(CancellationToken token = default) { try { - await context.SaveChangesAsync(token); + await _context.SaveChangesAsync(token); saved = true; } catch (DbUpdateConcurrencyException ex) { - // TODO: detect change - + // FIXME: detect change foreach (var entry in ex.Entries) entry.Reload(); } @@ -40,9 +39,9 @@ public async Task SaveAsync(CancellationToken token = default) } } - public void Detach(object item) => context.Entry(item).State = EntityState.Detached; + public void Detach(object item) => _context.Entry(item).State = EntityState.Detached; - public void Add(object item) => context.Add(item); + public void Add(object item) => _context.Add(item); public virtual Task CountAsync(CancellationToken token = default) { diff --git a/src/GZCTF/Repositories/SubmissionRepository.cs b/src/GZCTF/Repositories/SubmissionRepository.cs index ad15460dc..78b2c0292 100644 --- a/src/GZCTF/Repositories/SubmissionRepository.cs +++ b/src/GZCTF/Repositories/SubmissionRepository.cs @@ -9,35 +9,35 @@ namespace GZCTF.Repositories; public class SubmissionRepository : RepositoryBase, ISubmissionRepository { - private readonly IHubContext hubContext; + private readonly IHubContext _hubContext; public SubmissionRepository(IHubContext hub, - AppDbContext _context) : base(_context) + AppDbContext context) : base(context) { - hubContext = hub; + _hubContext = hub; } public async Task AddSubmission(Submission submission, CancellationToken token = default) { - await context.AddAsync(submission, token); - await context.SaveChangesAsync(token); + await _context.AddAsync(submission, token); + await _context.SaveChangesAsync(token); return submission; } public Task GetSubmission(int gameId, int challengeId, string userId, int submitId, CancellationToken token = default) - => context.Submissions.Where(s => s.Id == submitId && s.UserId == userId && s.GameId == gameId && s.ChallengeId == challengeId) + => _context.Submissions.Where(s => s.Id == submitId && s.UserId == userId && s.GameId == gameId && s.ChallengeId == challengeId) .SingleOrDefaultAsync(token); public Task GetUncheckedFlags(CancellationToken token = default) - => context.Submissions.Where(s => s.Status == AnswerResult.FlagSubmitted) + => _context.Submissions.Where(s => s.Status == AnswerResult.FlagSubmitted) .AsNoTracking().Include(e => e.Game).ToArrayAsync(token); private IQueryable GetSubmissionsByType(AnswerResult? type = null) { var subs = type is not null - ? context.Submissions.Where(s => s.Status == type.Value) - : context.Submissions; + ? _context.Submissions.Where(s => s.Status == type.Value) + : _context.Submissions; return subs.OrderByDescending(s => s.SubmitTimeUTC); } @@ -52,5 +52,5 @@ public Task GetSubmissions(Participation team, AnswerResult? type => GetSubmissionsByType(type).Where(s => s.TeamId == team.TeamId).TakeAllIfZero(count, skip).ToArrayAsync(token); public Task SendSubmission(Submission submission) - => hubContext.Clients.Group($"Game_{submission.GameId}").ReceivedSubmissions(submission); + => _hubContext.Clients.Group($"Game_{submission.GameId}").ReceivedSubmissions(submission); } diff --git a/src/GZCTF/Repositories/TeamRepository.cs b/src/GZCTF/Repositories/TeamRepository.cs index 3ce347faf..94ffb4e0f 100644 --- a/src/GZCTF/Repositories/TeamRepository.cs +++ b/src/GZCTF/Repositories/TeamRepository.cs @@ -6,14 +6,14 @@ namespace GZCTF.Repositories; public class TeamRepository : RepositoryBase, ITeamRepository { - public TeamRepository(AppDbContext _context) : base(_context) + public TeamRepository(AppDbContext context) : base(context) { } public async Task AnyActiveGame(Team team, CancellationToken token = default) { var current = DateTimeOffset.UtcNow; - var result = await context.Participations + var result = await _context.Participations .Where(p => p.Team == team && p.Game.EndTimeUTC > current) .AnyAsync(token); @@ -26,10 +26,10 @@ public async Task AnyActiveGame(Team team, CancellationToken token = defau return result; } - public override Task CountAsync(CancellationToken token = default) => context.Teams.CountAsync(token); + public override Task CountAsync(CancellationToken token = default) => _context.Teams.CountAsync(token); public Task CheckIsCaptain(UserInfo user, CancellationToken token = default) - => context.Teams.AnyAsync(t => t.Captain == user, token); + => _context.Teams.AnyAsync(t => t.Captain == user, token); public async Task CreateTeam(TeamUpdateModel model, UserInfo user, CancellationToken token = default) { @@ -40,7 +40,7 @@ public Task CheckIsCaptain(UserInfo user, CancellationToken token = defaul team.Members.Add(user); - await context.AddAsync(team, token); + await _context.AddAsync(team, token); await SaveAsync(token); return team; @@ -48,23 +48,23 @@ public Task CheckIsCaptain(UserInfo user, CancellationToken token = defaul public Task DeleteTeam(Team team, CancellationToken token = default) { - context.Remove(team); + _context.Remove(team); return SaveAsync(token); } public Task GetTeamById(int id, CancellationToken token = default) - => context.Teams.Include(e => e.Members).FirstOrDefaultAsync(t => t.Id == id, token); + => _context.Teams.Include(e => e.Members).FirstOrDefaultAsync(t => t.Id == id, token); public Task GetTeams(int count = 100, int skip = 0, CancellationToken token = default) - => context.Teams.Include(t => t.Members).OrderBy(t => t.Id) + => _context.Teams.Include(t => t.Members).OrderBy(t => t.Id) .Skip(skip).Take(count).ToArrayAsync(token); public Task GetUserTeams(UserInfo user, CancellationToken token = default) - => context.Teams.Where(t => t.Members.Any(u => u.Id == user.Id)) + => _context.Teams.Where(t => t.Members.Any(u => u.Id == user.Id)) .Include(t => t.Members).ToArrayAsync(token); public Task SearchTeams(string hint, CancellationToken token = default) - => context.Teams.Include(t => t.Members).Where(item => EF.Functions.Like(item.Name, $"%{hint}%")) + => _context.Teams.Include(t => t.Members).Where(item => EF.Functions.Like(item.Name, $"%{hint}%")) .OrderBy(t => t.Id).Take(30).ToArrayAsync(token); public Task Transfer(Team team, UserInfo user, CancellationToken token = default) @@ -75,7 +75,7 @@ public Task Transfer(Team team, UserInfo user, CancellationToken token = default public async Task VerifyToken(int id, string inviteCode, CancellationToken token = default) { - var team = await context.Teams.FirstOrDefaultAsync(t => t.Id == id, token); + var team = await _context.Teams.FirstOrDefaultAsync(t => t.Id == id, token); return team is not null && team.InviteCode == inviteCode; } } diff --git a/src/GZCTF/Services/CacheMaker.cs b/src/GZCTF/Services/CacheMaker.cs index 10a06cd89..a3762cc2c 100644 --- a/src/GZCTF/Services/CacheMaker.cs +++ b/src/GZCTF/Services/CacheMaker.cs @@ -33,65 +33,65 @@ public interface ICacheRequestHandler public class CacheMaker : IHostedService { - private readonly ILogger logger; - private readonly IDistributedCache cache; - private readonly ChannelReader channelReader; - private readonly IServiceScopeFactory serviceScopeFactory; - private CancellationTokenSource TokenSource { get; set; } = new CancellationTokenSource(); - private Dictionary cacheHandlers = new(); + private readonly ILogger _logger; + private readonly IDistributedCache _cache; + private readonly ChannelReader _channelReader; + private readonly IServiceScopeFactory _serviceScopeFactory; + private CancellationTokenSource _tokenSource { get; set; } = new CancellationTokenSource(); + private readonly Dictionary _cacheHandlers = new(); public CacheMaker( - ILogger _logger, - IDistributedCache _cache, - ChannelReader _channelReader, - IServiceScopeFactory _serviceScopeFactory) + ILogger logger, + IDistributedCache cache, + ChannelReader channelReader, + IServiceScopeFactory serviceScopeFactory) { - logger = _logger; - cache = _cache; - channelReader = _channelReader; - serviceScopeFactory = _serviceScopeFactory; + _logger = logger; + _cache = cache; + _channelReader = channelReader; + _serviceScopeFactory = serviceScopeFactory; } public void AddCacheRequestHandler(string key) where T : ICacheRequestHandler, new() - => cacheHandlers.Add(key, new T()); + => _cacheHandlers.Add(key, new T()); private async Task Maker(CancellationToken token = default) { - logger.SystemLog($"缓存更新线程已启动", TaskStatus.Pending, LogLevel.Debug); + _logger.SystemLog($"缓存更新线程已启动", TaskStatus.Pending, LogLevel.Debug); try { - await foreach (var item in channelReader.ReadAllAsync(token)) + await foreach (var item in _channelReader.ReadAllAsync(token)) { - if (!cacheHandlers.ContainsKey(item.Key)) + if (!_cacheHandlers.ContainsKey(item.Key)) { - logger.SystemLog($"缓存更新线程未找到匹配的请求:{item.Key}", TaskStatus.NotFound, LogLevel.Warning); + _logger.SystemLog($"缓存更新线程未找到匹配的请求:{item.Key}", TaskStatus.NotFound, LogLevel.Warning); continue; } - var handler = cacheHandlers[item.Key]; + var handler = _cacheHandlers[item.Key]; var key = handler.CacheKey(item); if (key is null) { - logger.SystemLog($"无效的缓存更新请求:{item.Key}", TaskStatus.NotFound, LogLevel.Warning); + _logger.SystemLog($"无效的缓存更新请求:{item.Key}", TaskStatus.NotFound, LogLevel.Warning); continue; } var updateLock = CacheKey.UpdateLock(key); - if (await cache.GetAsync(updateLock, token) is not null) + if (await _cache.GetAsync(updateLock, token) is not null) { // only one GZCTF instance will never encounter this problem - logger.SystemLog($"缓存更新线程已锁定:{key}", TaskStatus.Pending, LogLevel.Debug); + _logger.SystemLog($"缓存更新线程已锁定:{key}", TaskStatus.Pending, LogLevel.Debug); continue; } - await using var scope = serviceScopeFactory.CreateAsyncScope(); + await using var scope = _serviceScopeFactory.CreateAsyncScope(); try { - await cache.SetAsync(updateLock, Array.Empty(), new DistributedCacheEntryOptions + await _cache.SetAsync(updateLock, Array.Empty(), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) }, token); @@ -100,21 +100,21 @@ private async Task Maker(CancellationToken token = default) if (bytes is not null && bytes.Length > 0) { - await cache.SetAsync(key, bytes, item.Options ?? new DistributedCacheEntryOptions(), token); - logger.SystemLog($"缓存已更新:{key} @ {bytes.Length} bytes", TaskStatus.Success, LogLevel.Debug); + await _cache.SetAsync(key, bytes, item.Options ?? new DistributedCacheEntryOptions(), token); + _logger.SystemLog($"缓存已更新:{key} @ {bytes.Length} bytes", TaskStatus.Success, LogLevel.Debug); } else { - logger.SystemLog($"缓存生成失败:{key}", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"缓存生成失败:{key}", TaskStatus.Failed, LogLevel.Warning); } } catch (Exception e) { - logger.SystemLog($"缓存更新线程更新失败:{key} @ {e.Message}", TaskStatus.Failed, LogLevel.Error); + _logger.SystemLog($"缓存更新线程更新失败:{key} @ {e.Message}", TaskStatus.Failed, LogLevel.Error); } finally { - await cache.RemoveAsync(updateLock, token); + await _cache.RemoveAsync(updateLock, token); } token.ThrowIfCancellationRequested(); @@ -122,17 +122,17 @@ private async Task Maker(CancellationToken token = default) } catch (OperationCanceledException) { - logger.SystemLog($"任务取消,缓存更新线程将退出", TaskStatus.Exit, LogLevel.Debug); + _logger.SystemLog($"任务取消,缓存更新线程将退出", TaskStatus.Exit, LogLevel.Debug); } finally { - logger.SystemLog($"缓存更新线程已退出", TaskStatus.Exit, LogLevel.Debug); + _logger.SystemLog($"缓存更新线程已退出", TaskStatus.Exit, LogLevel.Debug); } } public Task StartAsync(CancellationToken token) { - TokenSource = new CancellationTokenSource(); + _tokenSource = new CancellationTokenSource(); #region Add Handlers @@ -140,16 +140,16 @@ public Task StartAsync(CancellationToken token) #endregion - _ = Maker(TokenSource.Token); + _ = Maker(_tokenSource.Token); return Task.CompletedTask; } public Task StopAsync(CancellationToken token) { - TokenSource.Cancel(); + _tokenSource.Cancel(); - logger.SystemLog("缓存更新已停用", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog("缓存更新已停用", TaskStatus.Success, LogLevel.Debug); return Task.CompletedTask; } diff --git a/src/GZCTF/Services/ConfigService.cs b/src/GZCTF/Services/ConfigService.cs index c693bae58..f70ed4bbe 100644 --- a/src/GZCTF/Services/ConfigService.cs +++ b/src/GZCTF/Services/ConfigService.cs @@ -8,17 +8,17 @@ namespace GZCTF.Services; public class ConfigService : IConfigService { - private readonly ILogger logger; - private readonly IConfigurationRoot? configuration; - private readonly AppDbContext context; + private readonly ILogger _logger; + private readonly IConfigurationRoot? _configuration; + private readonly AppDbContext _context; - public ConfigService(AppDbContext _context, - ILogger _logger, - IConfiguration _configuration) + public ConfigService(AppDbContext context, + ILogger logger, + IConfiguration configuration) { - context = _context; - logger = _logger; - configuration = _configuration as IConfigurationRoot; + _context = context; + _logger = logger; + _configuration = configuration as IConfigurationRoot; } private static void MapConfigsInternal(string key, HashSet configs, Type? type, object? value) @@ -70,7 +70,7 @@ public Task SaveConfig(T config, CancellationToken token = default) where T : private async Task SaveConfigInternal(HashSet configs, CancellationToken token = default) { - var dbConfigs = await context.Configs.ToDictionaryAsync(c => c.ConfigKey, c => c, token); + var dbConfigs = await _context.Configs.ToDictionaryAsync(c => c.ConfigKey, c => c, token); foreach (var conf in configs) { if (dbConfigs.TryGetValue(conf.ConfigKey, out var dbConf)) @@ -78,18 +78,18 @@ private async Task SaveConfigInternal(HashSet configs, CancellationToken if (dbConf.Value != conf.Value) { dbConf.Value = conf.Value; - logger.SystemLog($"更新全局设置:{conf.ConfigKey} => {conf.Value}", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog($"更新全局设置:{conf.ConfigKey} => {conf.Value}", TaskStatus.Success, LogLevel.Debug); } } else { - logger.SystemLog($"添加全局设置:{conf.ConfigKey} => {conf.Value}", TaskStatus.Success, LogLevel.Debug); - await context.Configs.AddAsync(conf, token); + _logger.SystemLog($"添加全局设置:{conf.ConfigKey} => {conf.Value}", TaskStatus.Success, LogLevel.Debug); + await _context.Configs.AddAsync(conf, token); } } - await context.SaveChangesAsync(token); - configuration?.Reload(); + await _context.SaveChangesAsync(token); + _configuration?.Reload(); } private static bool IsArrayLikeInterface(Type type) @@ -105,5 +105,5 @@ private static bool IsArrayLikeInterface(Type type) || genericTypeDefinition == typeof(ISet<>); } - public void ReloadConfig() => configuration?.Reload(); + public void ReloadConfig() => _configuration?.Reload(); } diff --git a/src/GZCTF/Services/CronJobService.cs b/src/GZCTF/Services/CronJobService.cs index 61e6b8458..bbd014656 100644 --- a/src/GZCTF/Services/CronJobService.cs +++ b/src/GZCTF/Services/CronJobService.cs @@ -9,20 +9,20 @@ namespace GZCTF.Services; public class CronJobService : IHostedService, IDisposable { - private readonly ILogger logger; - private readonly IServiceScopeFactory serviceProvider; - private Timer? timer; + private readonly ILogger _logger; + private readonly IServiceScopeFactory _serviceProvider; + private Timer? _timer; public CronJobService(IServiceScopeFactory provider, ILogger logger) { - serviceProvider = provider; - this.logger = logger; + _serviceProvider = provider; + _logger = logger; } public Task StartAsync(CancellationToken token) { - timer = new Timer(Execute, null, TimeSpan.Zero, TimeSpan.FromMinutes(3)); - logger.SystemLog("定时任务已启动", TaskStatus.Success, LogLevel.Debug); + _timer = new Timer(Execute, null, TimeSpan.Zero, TimeSpan.FromMinutes(3)); + _logger.SystemLog("定时任务已启动", TaskStatus.Success, LogLevel.Debug); return Task.CompletedTask; } @@ -35,7 +35,7 @@ private async Task ContainerChecker(AsyncServiceScope scope) { await containerService.DestroyContainerAsync(container); await containerRepo.RemoveContainer(container); - logger.SystemLog($"移除到期容器 [{container.ContainerId}]", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog($"移除到期容器 [{container.ContainerId}]", TaskStatus.Success, LogLevel.Debug); } } @@ -57,14 +57,14 @@ private async Task BootstrapCache(AsyncServiceScope scope) if (value is null) { await channelWriter.WriteAsync(ScoreboardCacheHandler.MakeCacheRequest(game)); - logger.SystemLog($"比赛 #{key} 即将开始,积分榜缓存已加入缓存队列", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog($"比赛 #{key} 即将开始,积分榜缓存已加入缓存队列", TaskStatus.Success, LogLevel.Debug); } } } private async void Execute(object? state) { - await using var scope = serviceProvider.CreateAsyncScope(); + await using var scope = _serviceProvider.CreateAsyncScope(); await ContainerChecker(scope); await BootstrapCache(scope); @@ -72,14 +72,14 @@ private async void Execute(object? state) public Task StopAsync(CancellationToken token) { - timer?.Change(Timeout.Infinite, 0); - logger.SystemLog("定时任务已停止", TaskStatus.Exit, LogLevel.Debug); + _timer?.Change(Timeout.Infinite, 0); + _logger.SystemLog("定时任务已停止", TaskStatus.Exit, LogLevel.Debug); return Task.CompletedTask; } public void Dispose() { - timer?.Dispose(); + _timer?.Dispose(); GC.SuppressFinalize(this); } } diff --git a/src/GZCTF/Services/DockerService.cs b/src/GZCTF/Services/DockerService.cs index 5ed8c6eeb..920963991 100644 --- a/src/GZCTF/Services/DockerService.cs +++ b/src/GZCTF/Services/DockerService.cs @@ -10,67 +10,67 @@ namespace GZCTF.Services; public class DockerService : IContainerService { - private readonly ILogger logger; - private readonly DockerConfig options; - private readonly string publicEntry; - private readonly DockerClient dockerClient; - private readonly AuthConfig? authConfig; + private readonly ILogger _logger; + private readonly DockerConfig _options; + private readonly string _publicEntry; + private readonly DockerClient _dockerClient; + private readonly AuthConfig? _authConfig; - public DockerService(IOptions _options, IOptions _registry, ILogger _logger) + public DockerService(IOptions options, IOptions registry, ILogger logger) { - options = _options.Value.DockerConfig ?? new(); - publicEntry = _options.Value.PublicEntry; - logger = _logger; - DockerClientConfiguration cfg = string.IsNullOrEmpty(options.Uri) ? new() : new(new Uri(options.Uri)); + _options = options.Value.DockerConfig ?? new(); + _publicEntry = options.Value.PublicEntry; + _logger = logger; + DockerClientConfiguration cfg = string.IsNullOrEmpty(_options.Uri) ? new() : new(new Uri(_options.Uri)); // TODO: Docker Auth Required - dockerClient = cfg.CreateClient(); + _dockerClient = cfg.CreateClient(); // Auth for registry - if (!string.IsNullOrWhiteSpace(_registry.Value.UserName) && !string.IsNullOrWhiteSpace(_registry.Value.Password)) + if (!string.IsNullOrWhiteSpace(registry.Value.UserName) && !string.IsNullOrWhiteSpace(registry.Value.Password)) { - authConfig = new AuthConfig() + _authConfig = new AuthConfig() { - Username = _registry.Value.UserName, - Password = _registry.Value.Password, + Username = registry.Value.UserName, + Password = registry.Value.Password, }; } - logger.SystemLog($"Docker 服务已启动 ({(string.IsNullOrEmpty(options.Uri) ? "localhost" : options.Uri)})", TaskStatus.Success, LogLevel.Debug); + logger.SystemLog($"Docker 服务已启动 ({(string.IsNullOrEmpty(_options.Uri) ? "localhost" : _options.Uri)})", TaskStatus.Success, LogLevel.Debug); } public Task CreateContainerAsync(ContainerConfig config, CancellationToken token = default) - => options.SwarmMode ? CreateContainerWithSwarm(config, token) : CreateContainerWithSingle(config, token); + => _options.SwarmMode ? CreateContainerWithSwarm(config, token) : CreateContainerWithSingle(config, token); public async Task DestroyContainerAsync(Container container, CancellationToken token = default) { try { - if (options.SwarmMode) - await dockerClient.Swarm.RemoveServiceAsync(container.ContainerId, token); + if (_options.SwarmMode) + await _dockerClient.Swarm.RemoveServiceAsync(container.ContainerId, token); else - await dockerClient.Containers.RemoveContainerAsync(container.ContainerId, new() { Force = true }, token); + await _dockerClient.Containers.RemoveContainerAsync(container.ContainerId, new() { Force = true }, token); } catch (DockerContainerNotFoundException) { - logger.SystemLog($"容器 {container.ContainerId} 已被销毁", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog($"容器 {container.ContainerId} 已被销毁", TaskStatus.Success, LogLevel.Debug); } catch (DockerApiException e) { if (e.StatusCode == HttpStatusCode.NotFound) { - logger.SystemLog($"容器 {container.ContainerId} 已被销毁", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog($"容器 {container.ContainerId} 已被销毁", TaskStatus.Success, LogLevel.Debug); } else { - logger.SystemLog($"容器 {container.ContainerId} 删除失败, 状态:{e.StatusCode}", TaskStatus.Failed, LogLevel.Warning); - logger.SystemLog($"容器 {container.ContainerId} 删除失败, 响应:{e.ResponseBody}", TaskStatus.Failed, LogLevel.Error); + _logger.SystemLog($"容器 {container.ContainerId} 删除失败, 状态:{e.StatusCode}", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"容器 {container.ContainerId} 删除失败, 响应:{e.ResponseBody}", TaskStatus.Failed, LogLevel.Error); return; } } catch (Exception e) { - logger.LogError(e, $"容器 {container.ContainerId} 删除失败"); + _logger.LogError(e, $"容器 {container.ContainerId} 删除失败"); return; } @@ -103,7 +103,7 @@ private static CreateContainerParameters GetCreateContainerParameters(ContainerC private ServiceCreateParameters GetServiceCreateParameters(ContainerConfig config) => new() { - RegistryAuth = authConfig, + RegistryAuth = _authConfig, Service = new() { Name = GetName(config), @@ -144,27 +144,27 @@ private ServiceCreateParameters GetServiceCreateParameters(ContainerConfig confi CreateContainer: try { - serviceRes = await dockerClient.Swarm.CreateServiceAsync(parameters, token); + serviceRes = await _dockerClient.Swarm.CreateServiceAsync(parameters, token); } catch (DockerApiException e) { if (e.StatusCode == HttpStatusCode.Conflict && retry < 3) { - logger.SystemLog($"容器 {parameters.Service.Name} 已存在,尝试移除后重新创建", TaskStatus.Duplicate, LogLevel.Warning); - await dockerClient.Swarm.RemoveServiceAsync(parameters.Service.Name, token); + _logger.SystemLog($"容器 {parameters.Service.Name} 已存在,尝试移除后重新创建", TaskStatus.Duplicate, LogLevel.Warning); + await _dockerClient.Swarm.RemoveServiceAsync(parameters.Service.Name, token); retry++; goto CreateContainer; } else { - logger.SystemLog($"容器 {parameters.Service.Name} 创建失败, 状态:{e.StatusCode}", TaskStatus.Failed, LogLevel.Warning); - logger.SystemLog($"容器 {parameters.Service.Name} 创建失败, 响应:{e.ResponseBody}", TaskStatus.Failed, LogLevel.Error); + _logger.SystemLog($"容器 {parameters.Service.Name} 创建失败, 状态:{e.StatusCode}", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"容器 {parameters.Service.Name} 创建失败, 响应:{e.ResponseBody}", TaskStatus.Failed, LogLevel.Error); return null; } } catch (Exception e) { - logger.LogError(e, $"容器 {parameters.Service.Name} 删除失败"); + _logger.LogError(e, $"容器 {parameters.Service.Name} 删除失败"); return null; } @@ -178,11 +178,11 @@ private ServiceCreateParameters GetServiceCreateParameters(ContainerConfig confi SwarmService? res; do { - res = await dockerClient.Swarm.InspectServiceAsync(serviceRes.ID, token); + res = await _dockerClient.Swarm.InspectServiceAsync(serviceRes.ID, token); retry++; if (retry == 3) { - logger.SystemLog($"容器 {parameters.Service.Name} 创建后未获取到端口暴露信息,创建失败", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"容器 {parameters.Service.Name} 创建后未获取到端口暴露信息,创建失败", TaskStatus.Failed, LogLevel.Warning); return null; } if (res is not { Endpoint.Ports.Count: > 0 }) @@ -197,8 +197,8 @@ private ServiceCreateParameters GetServiceCreateParameters(ContainerConfig confi container.Port = (int)port.PublishedPort; container.Status = ContainerStatus.Running; - if (!string.IsNullOrEmpty(publicEntry)) - container.PublicIP = publicEntry; + if (!string.IsNullOrEmpty(_publicEntry)) + container.PublicIP = _publicEntry; return container; } @@ -209,33 +209,33 @@ private ServiceCreateParameters GetServiceCreateParameters(ContainerConfig confi CreateContainerResponse? containerRes = null; try { - containerRes = await dockerClient.Containers.CreateContainerAsync(parameters, token); + containerRes = await _dockerClient.Containers.CreateContainerAsync(parameters, token); } catch (DockerImageNotFoundException) { - logger.SystemLog($"拉取容器镜像 {config.Image}", TaskStatus.Pending, LogLevel.Information); + _logger.SystemLog($"拉取容器镜像 {config.Image}", TaskStatus.Pending, LogLevel.Information); - await dockerClient.Images.CreateImageAsync(new() + await _dockerClient.Images.CreateImageAsync(new() { FromImage = config.Image - }, authConfig, new Progress(msg => + }, _authConfig, new Progress(msg => { Console.WriteLine($"{msg.Status}|{msg.ProgressMessage}|{msg.ErrorMessage}"); }), token); } catch (Exception e) { - logger.LogError(e, $"容器 {parameters.Name} 创建失败"); + _logger.LogError(e, $"容器 {parameters.Name} 创建失败"); return null; } try { - containerRes ??= await dockerClient.Containers.CreateContainerAsync(parameters, token); + containerRes ??= await _dockerClient.Containers.CreateContainerAsync(parameters, token); } catch (Exception e) { - logger.LogError(e, $"容器 {parameters.Name} 创建失败"); + _logger.LogError(e, $"容器 {parameters.Name} 创建失败"); return null; } @@ -250,25 +250,25 @@ await dockerClient.Images.CreateImageAsync(new() do { - started = await dockerClient.Containers.StartContainerAsync(containerRes.ID, new(), token); + started = await _dockerClient.Containers.StartContainerAsync(containerRes.ID, new(), token); retry++; if (retry == 3) { - logger.SystemLog($"启动容器实例 {container.ContainerId[..12]} ({config.Image.Split("/").LastOrDefault()}) 失败", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"启动容器实例 {container.ContainerId[..12]} ({config.Image.Split("/").LastOrDefault()}) 失败", TaskStatus.Failed, LogLevel.Warning); return null; } if (!started) await Task.Delay(500, token); } while (!started); - var info = await dockerClient.Containers.InspectContainerAsync(container.ContainerId, token); + var info = await _dockerClient.Containers.InspectContainerAsync(container.ContainerId, token); container.Status = (info.State.Dead || info.State.OOMKilled || info.State.Restarting) ? ContainerStatus.Destroyed : info.State.Running ? ContainerStatus.Running : ContainerStatus.Pending; if (container.Status != ContainerStatus.Running) { - logger.SystemLog($"创建 {config.Image.Split("/").LastOrDefault()} 实例遇到错误:{info.State.Error}", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"创建 {config.Image.Split("/").LastOrDefault()} 实例遇到错误:{info.State.Error}", TaskStatus.Failed, LogLevel.Warning); return null; } @@ -283,12 +283,12 @@ await dockerClient.Images.CreateImageAsync(new() if (int.TryParse(port, out var numport)) container.Port = numport; else - logger.SystemLog($"无法转换端口号:{port},这是非预期的行为", TaskStatus.Failed, LogLevel.Warning); + _logger.SystemLog($"无法转换端口号:{port},这是非预期的行为", TaskStatus.Failed, LogLevel.Warning); container.IP = info.NetworkSettings.IPAddress; - if (!string.IsNullOrEmpty(publicEntry)) - container.PublicIP = publicEntry; + if (!string.IsNullOrEmpty(_publicEntry)) + container.PublicIP = _publicEntry; return container; } diff --git a/src/GZCTF/Services/FlagChecker.cs b/src/GZCTF/Services/FlagChecker.cs index 208f010cb..a5f152611 100644 --- a/src/GZCTF/Services/FlagChecker.cs +++ b/src/GZCTF/Services/FlagChecker.cs @@ -8,35 +8,35 @@ namespace GZCTF.Services; public class FlagChecker : IHostedService { - private readonly ILogger logger; - private readonly ChannelReader channelReader; - private readonly ChannelWriter channelWriter; - private readonly IServiceScopeFactory serviceScopeFactory; + private readonly ILogger _logger; + private readonly ChannelReader _channelReader; + private readonly ChannelWriter _channelWriter; + private readonly IServiceScopeFactory _serviceScopeFactory; private CancellationTokenSource TokenSource { get; set; } = new CancellationTokenSource(); - public FlagChecker(ChannelReader _channelReader, - ChannelWriter _channelWriter, - ILogger _logger, - IServiceScopeFactory _serviceScopeFactory) + public FlagChecker(ChannelReader channelReader, + ChannelWriter channelWriter, + ILogger logger, + IServiceScopeFactory serviceScopeFactory) { - logger = _logger; - channelReader = _channelReader; - channelWriter = _channelWriter; - serviceScopeFactory = _serviceScopeFactory; + _logger = logger; + _channelReader = channelReader; + _channelWriter = channelWriter; + _serviceScopeFactory = serviceScopeFactory; } private async Task Checker(int id, CancellationToken token = default) { - logger.SystemLog($"检查线程 #{id} 已启动", TaskStatus.Pending, LogLevel.Debug); + _logger.SystemLog($"检查线程 #{id} 已启动", TaskStatus.Pending, LogLevel.Debug); try { - await foreach (var item in channelReader.ReadAllAsync(token)) + await foreach (var item in _channelReader.ReadAllAsync(token)) { - logger.SystemLog($"检查线程 #{id} 开始处理提交:{item.Answer}", TaskStatus.Pending, LogLevel.Debug); + _logger.SystemLog($"检查线程 #{id} 开始处理提交:{item.Answer}", TaskStatus.Pending, LogLevel.Debug); - await using var scope = serviceScopeFactory.CreateAsyncScope(); + await using var scope = _serviceScopeFactory.CreateAsyncScope(); var eventRepository = scope.ServiceProvider.GetRequiredService(); var instanceRepository = scope.ServiceProvider.GetRequiredService(); @@ -49,10 +49,10 @@ private async Task Checker(int id, CancellationToken token = default) var (type, ans) = await instanceRepository.VerifyAnswer(item, token); if (ans == AnswerResult.NotFound) - logger.Log($"[实例未知] 未找到队伍 [{item.Team.Name}] 提交题目 [{item.Challenge.Title}] 的实例", item.User!, TaskStatus.NotFound, LogLevel.Warning); + _logger.Log($"[实例未知] 未找到队伍 [{item.Team.Name}] 提交题目 [{item.Challenge.Title}] 的实例", item.User!, TaskStatus.NotFound, LogLevel.Warning); else if (ans == AnswerResult.Accepted) { - logger.Log($"[提交正确] 队伍 [{item.Team.Name}] 提交题目 [{item.Challenge.Title}] 的答案 [{item.Answer}]", item.User!, TaskStatus.Success, LogLevel.Information); + _logger.Log($"[提交正确] 队伍 [{item.Team.Name}] 提交题目 [{item.Challenge.Title}] 的答案 [{item.Answer}]", item.User!, TaskStatus.Success, LogLevel.Information); await eventRepository.AddEvent(GameEvent.FromSubmission(item, type, ans), token); @@ -62,7 +62,7 @@ private async Task Checker(int id, CancellationToken token = default) } else { - logger.Log($"[提交错误] 队伍 [{item.Team.Name}] 提交题目 [{item.Challenge.Title}] 的答案 [{item.Answer}]", item.User!, TaskStatus.Failed, LogLevel.Information); + _logger.Log($"[提交错误] 队伍 [{item.Team.Name}] 提交题目 [{item.Challenge.Title}] 的答案 [{item.Answer}]", item.User!, TaskStatus.Failed, LogLevel.Information); await eventRepository.AddEvent(GameEvent.FromSubmission(item, type, ans), token); @@ -71,7 +71,7 @@ private async Task Checker(int id, CancellationToken token = default) if (ans == AnswerResult.CheatDetected) { - logger.Log($"[作弊检查] 队伍 [{item.Team.Name}] 疑似违规 [{item.Challenge.Title}],相关队伍 [{result.SourceTeamName}]", item.User!, TaskStatus.Success, LogLevel.Information); + _logger.Log($"[作弊检查] 队伍 [{item.Team.Name}] 疑似违规 [{item.Challenge.Title}],相关队伍 [{result.SourceTeamName}]", item.User!, TaskStatus.Success, LogLevel.Information); await eventRepository.AddEvent(new() { Type = EventType.CheatDetected, @@ -93,13 +93,13 @@ await eventRepository.AddEvent(new() } catch (DbUpdateConcurrencyException) { - logger.SystemLog($"[数据库并发] 未能更新提交 #{item.Id} 的状态", TaskStatus.Failed, LogLevel.Warning); - await channelWriter.WriteAsync(item, token); + _logger.SystemLog($"[数据库并发] 未能更新提交 #{item.Id} 的状态", TaskStatus.Failed, LogLevel.Warning); + await _channelWriter.WriteAsync(item, token); } catch (Exception e) { - logger.SystemLog($"检查线程 #{id} 发生异常", TaskStatus.Failed, LogLevel.Debug); - logger.LogError(e.Message, e); + _logger.SystemLog($"检查线程 #{id} 发生异常", TaskStatus.Failed, LogLevel.Debug); + _logger.LogError(e.Message, e); } token.ThrowIfCancellationRequested(); @@ -107,11 +107,11 @@ await eventRepository.AddEvent(new() } catch (OperationCanceledException) { - logger.SystemLog($"任务取消,检查线程 #{id} 将退出", TaskStatus.Exit, LogLevel.Debug); + _logger.SystemLog($"任务取消,检查线程 #{id} 将退出", TaskStatus.Exit, LogLevel.Debug); } finally { - logger.SystemLog($"检查线程 #{id} 已退出", TaskStatus.Exit, LogLevel.Debug); + _logger.SystemLog($"检查线程 #{id} 已退出", TaskStatus.Exit, LogLevel.Debug); } } @@ -122,25 +122,25 @@ public async Task StartAsync(CancellationToken cancellationToken) for (int i = 0; i < 2; ++i) _ = Checker(i, TokenSource.Token); - await using var scope = serviceScopeFactory.CreateAsyncScope(); + await using var scope = _serviceScopeFactory.CreateAsyncScope(); var submissionRepository = scope.ServiceProvider.GetRequiredService(); var flags = await submissionRepository.GetUncheckedFlags(TokenSource.Token); foreach (var item in flags) - await channelWriter.WriteAsync(item, TokenSource.Token); + await _channelWriter.WriteAsync(item, TokenSource.Token); if (flags.Length > 0) - logger.SystemLog($"重新开始检查 {flags.Length} 个 flag", TaskStatus.Pending, LogLevel.Debug); + _logger.SystemLog($"重新开始检查 {flags.Length} 个 flag", TaskStatus.Pending, LogLevel.Debug); - logger.SystemLog("Flag 检查已启用", TaskStatus.Success, LogLevel.Debug); + _logger.SystemLog("Flag 检查已启用", TaskStatus.Success, LogLevel.Debug); } public Task StopAsync(CancellationToken cancellationToken) { TokenSource.Cancel(); - logger.SystemLog("Flag 检查已停止", TaskStatus.Exit, LogLevel.Debug); + _logger.SystemLog("Flag 检查已停止", TaskStatus.Exit, LogLevel.Debug); return Task.CompletedTask; } diff --git a/src/GZCTF/Services/K8sService.cs b/src/GZCTF/Services/K8sService.cs index 9abc55f39..eafe0114f 100644 --- a/src/GZCTF/Services/K8sService.cs +++ b/src/GZCTF/Services/K8sService.cs @@ -15,45 +15,45 @@ public class K8sService : IContainerService { private const string NetworkPolicy = "gzctf-policy"; - private readonly ILogger logger; - private readonly Kubernetes kubernetesClient; - private readonly string hostIP; - private readonly string publicEntry; - private readonly string? AuthSecretName; - private readonly K8sConfig options; + private readonly ILogger _logger; + private readonly Kubernetes _kubernetesClient; + private readonly string _hostIP; + private readonly string _publicEntry; + private readonly string? _authSecretName; + private readonly K8sConfig _options; - public K8sService(IOptions _registry, IOptions _provider, ILogger _logger) + public K8sService(IOptions registry, IOptions provider, ILogger logger) { - logger = _logger; - publicEntry = _provider.Value.PublicEntry; - options = _provider.Value.K8sConfig ?? new(); + _logger = logger; + _publicEntry = provider.Value.PublicEntry; + _options = provider.Value.K8sConfig ?? new(); - if (!File.Exists(options.KubeConfig)) + if (!File.Exists(_options.KubeConfig)) { - LogHelper.SystemLog(logger, $"无法加载 K8s 配置文件,请确保配置文件存在 {options.KubeConfig}"); - throw new FileNotFoundException(options.KubeConfig); + LogHelper.SystemLog(logger, $"无法加载 K8s 配置文件,请确保配置文件存在 {_options.KubeConfig}"); + throw new FileNotFoundException(_options.KubeConfig); } - var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(options.KubeConfig); + var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(_options.KubeConfig); - hostIP = config.Host[(config.Host.LastIndexOf('/') + 1)..config.Host.LastIndexOf(':')]; + _hostIP = config.Host[(config.Host.LastIndexOf('/') + 1)..config.Host.LastIndexOf(':')]; - kubernetesClient = new Kubernetes(config); + _kubernetesClient = new Kubernetes(config); - var registry = _registry.Value; - var withAuth = !string.IsNullOrWhiteSpace(registry.ServerAddress) - && !string.IsNullOrWhiteSpace(registry.UserName) - && !string.IsNullOrWhiteSpace(registry.Password); + var registryValue = registry.Value; + var withAuth = !string.IsNullOrWhiteSpace(registryValue.ServerAddress) + && !string.IsNullOrWhiteSpace(registryValue.UserName) + && !string.IsNullOrWhiteSpace(registryValue.Password); if (withAuth) { - var padding = $"{registry.UserName}@{registry.Password}@{registry.ServerAddress}".StrMD5(); - AuthSecretName = $"{registry.UserName}-{padding}".ToValidRFC1123String("secret"); + var padding = $"{registryValue.UserName}@{registryValue.Password}@{registryValue.ServerAddress}".StrMD5(); + _authSecretName = $"{registryValue.UserName}-{padding}".ToValidRFC1123String("secret"); } try { - InitK8s(withAuth, registry); + InitK8s(withAuth, registryValue); } catch (Exception e) { @@ -70,7 +70,7 @@ public K8sService(IOptions _registry, IOptions _registry, IOptions() { ["ctf.gzti.me/ResourceId"] = name, @@ -91,14 +91,14 @@ public K8sService(IOptions _registry, IOptions() : - new List() { new() { Name = AuthSecretName } }, + new List() { new() { Name = _authSecretName } }, DnsPolicy = "None", DnsConfig = new() { // FIXME: remove nullable when JsonObjectCreationHandling release - Nameservers = options.DNS ?? new[] { "8.8.8.8", "223.5.5.5", "114.114.114.114" }, + Nameservers = _options.DNS ?? new[] { "8.8.8.8", "223.5.5.5", "114.114.114.114" }, }, EnableServiceLinks = false, Containers = new[] @@ -136,23 +136,23 @@ public K8sService(IOptions _registry, IOptions _registry, IOptions() { ["ctf.gzti.me/ResourceId"] = name } }, Spec = new V1ServiceSpec() @@ -188,18 +188,18 @@ public K8sService(IOptions _registry, IOptions _registry, IOptions ns.Metadata.Name != options.Namespace)) - kubernetesClient.CoreV1.CreateNamespace(new() { Metadata = new() { Name = options.Namespace } }); + if (_kubernetesClient.CoreV1.ListNamespace().Items.All(ns => ns.Metadata.Name != _options.Namespace)) + _kubernetesClient.CoreV1.CreateNamespace(new() { Metadata = new() { Name = _options.Namespace } }); - if (kubernetesClient.NetworkingV1.ListNamespacedNetworkPolicy(options.Namespace).Items.All(np => np.Metadata.Name != NetworkPolicy)) + if (_kubernetesClient.NetworkingV1.ListNamespacedNetworkPolicy(_options.Namespace).Items.All(np => np.Metadata.Name != NetworkPolicy)) { - kubernetesClient.NetworkingV1.CreateNamespacedNetworkPolicy(new() + _kubernetesClient.NetworkingV1.CreateNamespacedNetworkPolicy(new() { Metadata = new() { Name = NetworkPolicy }, Spec = new() @@ -273,14 +273,14 @@ private void InitK8s(bool withAuth, RegistryConfig? registry) IpBlock = new() { Cidr = "0.0.0.0/0", // FIXME: remove nullable when JsonObjectCreationHandling release - Except = options.AllowCIDR ?? new[] { "10.0.0.0/8" } + Except = _options.AllowCIDR ?? new[] { "10.0.0.0/8" } } }, } } } } - }, options.Namespace); + }, _options.Namespace); } if (withAuth && registry is not null && registry.ServerAddress is not null) @@ -303,8 +303,8 @@ private void InitK8s(bool withAuth, RegistryConfig? registry) { Metadata = new V1ObjectMeta() { - Name = AuthSecretName, - NamespaceProperty = options.Namespace, + Name = _authSecretName, + NamespaceProperty = _options.Namespace, }, Data = new Dictionary() { [".dockerconfigjson"] = dockerjsonBytes }, Type = "kubernetes.io/dockerconfigjson" @@ -312,11 +312,11 @@ private void InitK8s(bool withAuth, RegistryConfig? registry) try { - kubernetesClient.CoreV1.ReplaceNamespacedSecret(secret, AuthSecretName, options.Namespace); + _kubernetesClient.CoreV1.ReplaceNamespacedSecret(secret, _authSecretName, _options.Namespace); } catch { - kubernetesClient.CoreV1.CreateNamespacedSecret(secret, options.Namespace); + _kubernetesClient.CoreV1.CreateNamespacedSecret(secret, _options.Namespace); } } } diff --git a/src/GZCTF/Services/MailSender.cs b/src/GZCTF/Services/MailSender.cs index 77dc584cc..02c86f28f 100644 --- a/src/GZCTF/Services/MailSender.cs +++ b/src/GZCTF/Services/MailSender.cs @@ -10,24 +10,24 @@ namespace GZCTF.Services; public class MailSender : IMailSender { - private readonly EmailConfig? options; - private readonly ILogger logger; + private readonly EmailConfig? _options; + private readonly ILogger _logger; public MailSender(IOptions options, ILogger logger) { - this.options = options.Value; - this.logger = logger; + _options = options.Value; + _logger = logger; } public async Task SendEmailAsync(string subject, string content, string to) { - if (options?.SendMailAddress is null || - options?.Smtp?.Host is null || - options?.Smtp?.Port is null) + if (_options?.SendMailAddress is null || + _options?.Smtp?.Host is null || + _options?.Smtp?.Port is null) return true; var msg = new MimeMessage(); - msg.From.Add(new MailboxAddress(options.SendMailAddress, options.SendMailAddress)); + msg.From.Add(new MailboxAddress(_options.SendMailAddress, _options.SendMailAddress)); msg.To.Add(new MailboxAddress(to, to)); msg.Subject = subject; msg.Body = new TextPart(MimeKit.Text.TextFormat.Html) { Text = content }; @@ -36,18 +36,18 @@ public async Task SendEmailAsync(string subject, string content, string to { using var client = new SmtpClient(); - await client.ConnectAsync(options.Smtp.Host, options.Smtp.Port.Value); + await client.ConnectAsync(_options.Smtp.Host, _options.Smtp.Port.Value); client.AuthenticationMechanisms.Remove("XOAUTH2"); - await client.AuthenticateAsync(options.UserName, options.Password); + await client.AuthenticateAsync(_options.UserName, _options.Password); await client.SendAsync(msg); await client.DisconnectAsync(true); - logger.SystemLog("发送邮件:" + to, TaskStatus.Success, LogLevel.Information); + _logger.SystemLog("发送邮件:" + to, TaskStatus.Success, LogLevel.Information); return true; } catch (Exception e) { - logger.LogError(e, "邮件发送遇到问题"); + _logger.LogError(e, "邮件发送遇到问题"); return false; } } @@ -56,7 +56,7 @@ public async Task SendUrlAsync(string? title, string? information, string? btnms { if (email is null || userName is null || title is null) { - logger.SystemLog("无效的邮件发送调用!", TaskStatus.Failed); + _logger.SystemLog("无效的邮件发送调用!", TaskStatus.Failed); return; } @@ -75,12 +75,12 @@ public async Task SendUrlAsync(string? title, string? information, string? btnms .Replace("{url}", url) .Replace("{nowtime}", DateTimeOffset.UtcNow.ToString("u")); if (!await SendEmailAsync(title, emailContent, email)) - logger.SystemLog("邮件发送失败!", TaskStatus.Failed); + _logger.SystemLog("邮件发送失败!", TaskStatus.Failed); } private bool SendUrlIfPossible(string? title, string? information, string? btnmsg, string? userName, string? email, string? url) { - if (options?.SendMailAddress is null) + if (_options?.SendMailAddress is null) return false; var _ = SendUrlAsync(title, information, btnmsg, userName, email, url); diff --git a/src/GZCTF/Utils/LogHelper.cs b/src/GZCTF/Utils/LogHelper.cs index 22102b06f..d8a3167d8 100644 --- a/src/GZCTF/Utils/LogHelper.cs +++ b/src/GZCTF/Utils/LogHelper.cs @@ -18,65 +18,65 @@ public static class LogHelper /// /// 记录一条系统日志(无用户信息,默认Info) /// - /// 传入的 Nlog.Logger + /// 传入的 Nlog.Logger /// Log 消息 /// 操作执行结果 /// Log 级别 - public static void SystemLog(this ILogger _logger, string msg, TaskStatus status = TaskStatus.Success, LogLevel? level = null) - => Log(_logger, msg, "System", string.Empty, status, level ?? LogLevel.Information); + public static void SystemLog(this ILogger logger, string msg, TaskStatus status = TaskStatus.Success, LogLevel? level = null) + => Log(logger, msg, "System", string.Empty, status, level ?? LogLevel.Information); /// /// 登记一条 Log 记录 /// - /// 传入的 Nlog.Logger + /// 传入的 Nlog.Logger /// Log 消息 /// 用户对象 /// 操作执行结果 /// Log 级别 - public static void Log(this ILogger _logger, string msg, UserInfo? user, TaskStatus status, LogLevel? level = null) - => Log(_logger, msg, user?.UserName ?? "Anonymous", user?.IP ?? "0.0.0.0", status, level); + public static void Log(this ILogger logger, string msg, UserInfo? user, TaskStatus status, LogLevel? level = null) + => Log(logger, msg, user?.UserName ?? "Anonymous", user?.IP ?? "0.0.0.0", status, level); /// /// 登记一条 Log 记录 /// - /// 传入的 Nlog.Logger + /// 传入的 Nlog.Logger /// Log 消息 /// Http上下文 /// 操作执行结果 /// Log 级别 - public static void Log(this ILogger _logger, string msg, HttpContext? context, TaskStatus status, LogLevel? level = null) + public static void Log(this ILogger logger, string msg, HttpContext? context, TaskStatus status, LogLevel? level = null) { var ip = context?.Connection?.RemoteIpAddress?.ToString() ?? IPAddress.Loopback.ToString(); var username = context?.User?.Identity?.Name ?? "Anonymous"; - Log(_logger, msg, username, ip, status, level); + Log(logger, msg, username, ip, status, level); } /// /// 登记一条 Log 记录 /// - /// 传入的 Nlog.Logger + /// 传入的 Nlog.Logger /// Log 消息 /// 连接IP /// 操作执行结果 /// Log 级别 - public static void Log(this ILogger _logger, string msg, string ip, TaskStatus status, LogLevel? level = null) - => Log(_logger, msg, "Anonymous", ip, status, level); + public static void Log(this ILogger logger, string msg, string ip, TaskStatus status, LogLevel? level = null) + => Log(logger, msg, "Anonymous", ip, status, level); /// /// 登记一条 Log 记录 /// - /// 传入的 Nlog.Logger + /// 传入的 Nlog.Logger /// Log 消息 /// 用户名 /// 当前IP /// 操作执行结果 /// Log 级别 - public static void Log(this ILogger _logger, string msg, string uname, string ip, TaskStatus status, LogLevel? level = null) + public static void Log(this ILogger logger, string msg, string uname, string ip, TaskStatus status, LogLevel? level = null) { - using (_logger.BeginScope("{UserName}{Status}{IP}", uname, status, ip)) + using (logger.BeginScope("{UserName}{Status}{IP}", uname, status, ip)) { - _logger.Log(level ?? LogLevel.Information, msg); + logger.Log(level ?? LogLevel.Information, msg); } }