From 60c2e6354adfaccc5d58c92371f37f89d888c7e6 Mon Sep 17 00:00:00 2001 From: TooYoungTooSimp <6648049+TooYoungTooSimp@users.noreply.github.com> Date: Mon, 8 Nov 2021 21:21:57 +0800 Subject: [PATCH] Mon, 08 Nov 2021 21:21:57 GMT --- Controllers/ApplicationFormController.cs | 47 +++++++++++++++++++ Controllers/ProblemController.cs | 6 +-- Controllers/StatusController.cs | 32 +++++++++++++ Models/StatusModel.cs | 12 +++++ Models/UserModel.cs | 59 ++++++++++++++++++++++++ Startup.cs | 3 +- Utilities/LabelsAttribute.cs | 27 +++++++++++ appsettings.json | 3 +- cugoj-ng-server.csproj | 8 ++-- 9 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 Controllers/ApplicationFormController.cs create mode 100644 Controllers/StatusController.cs create mode 100644 Models/StatusModel.cs create mode 100644 Utilities/LabelsAttribute.cs diff --git a/Controllers/ApplicationFormController.cs b/Controllers/ApplicationFormController.cs new file mode 100644 index 0000000..d6bf01e --- /dev/null +++ b/Controllers/ApplicationFormController.cs @@ -0,0 +1,47 @@ +using cugoj_ng_server.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace cugoj_ng_server.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ApplicationFormController : ControllerBase + { + [Route("Get"), HttpGet] + public async Task> GetAsync() + { + var user = HttpContext.Session.GetString("user"); + if (string.IsNullOrEmpty(user)) + return Unauthorized(); + var form = await UserModel.GetApplicationFormAsync(user); + if (form == null) return NoContent(); + return Ok(form); + } + [Route("Save"), HttpPost] + public async Task SaveAsync([FromBody] ApplicationForm form) + { + var user = HttpContext.Session.GetString("user"); + if (string.IsNullOrEmpty(user)) + return Unauthorized(); + form.UserId = user; + return Ok(await UserModel.SetApplicationFormAsync(form)); + } + + [Route("Submit"), HttpPost] + public async Task SubmitAsync([FromBody] ApplicationForm form) + { + var user = HttpContext.Session.GetString("user"); + if (string.IsNullOrEmpty(user)) + return Unauthorized(); + form.UserId = user; + if (!form.Validate()) + return BadRequest(); + return Ok(await UserModel.SetApplicationFormAsync(form)); + } + } +} diff --git a/Controllers/ProblemController.cs b/Controllers/ProblemController.cs index 2ac9343..f465828 100644 --- a/Controllers/ProblemController.cs +++ b/Controllers/ProblemController.cs @@ -37,7 +37,7 @@ namespace cugoj_ng_server.Controllers } [HttpGet] - [Route("List/{page}")] + [Route("List/{page:int:min(1)}")] public async Task GetProblemListAsync(int page) { if (page <= 0) return BadRequest(); @@ -52,7 +52,7 @@ namespace cugoj_ng_server.Controllers } [HttpGet] - [Route("{pid}")] + [Route("{pid:int}")] public async Task GetProblemAsync(int pid) { bool viewAll = await UserModel.Authorization.CanViewAllProblemsAsync(HttpContext.Session.GetString("user")); @@ -66,7 +66,7 @@ namespace cugoj_ng_server.Controllers [RequestSizeLimit(1 << 20)] [HttpPost] - [Route("Submit/{pid}")] + [Route("{pid:int}/Submit")] public async Task SubmitSolutionAsync(int pid, [FromForm] string lang, [FromForm] string code) { var user = HttpContext.Session.GetString("user"); diff --git a/Controllers/StatusController.cs b/Controllers/StatusController.cs new file mode 100644 index 0000000..db25e78 --- /dev/null +++ b/Controllers/StatusController.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; + +namespace cugoj_ng_server.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class StatusController : ControllerBase + { + readonly int maxStatusPerPage; + public StatusController(IConfiguration configuration) + { + maxStatusPerPage = configuration.GetValue("Config:MaxStatusPerPage"); + } + + [HttpGet] + public object List() + { + if (Request.Query.TryGetValue("cid", out var s)) + { + if (s.Any(x => !int.TryParse(x, out _))) + return BadRequest("cid must be int"); + } + return 1; + } + } +} diff --git a/Models/StatusModel.cs b/Models/StatusModel.cs new file mode 100644 index 0000000..40de2e4 --- /dev/null +++ b/Models/StatusModel.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace cugoj_ng_server.Models +{ + public class StatusModel + { + + } +} diff --git a/Models/UserModel.cs b/Models/UserModel.cs index 76b6a03..9daccc8 100644 --- a/Models/UserModel.cs +++ b/Models/UserModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Data; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using cugoj_ng_server.Utilities; using Dapper; @@ -54,5 +55,63 @@ namespace cugoj_ng_server.Models return (await conn.QueryAsync(@"select rightstr from privilege where user_id=@id and length(rightstr)>5", new { id = user_id })).ToArray(); } } + + public static async Task GetApplicationFormAsync(string uid) + { + using var conn = GetConnection(); + return await conn.QueryFirstOrDefaultAsync("select * from application_form where user_id=@uid", new { uid }); + } + + public static async Task SetApplicationFormAsync(ApplicationForm form) + { + using var conn = GetConnection(); + return await conn.ExecuteAsync(@" + REPLACE INTO application_form (user_id,name,student_id,college,major,mobile,qq,score,oj_accounts,text1,text2,text3,text4,status,comment) + VALUES (@UserId,@Name,@StudentId,@College,@Major,@Mobile,@QQ,@Score,@OJAccounts,@Text1,@Text2,@Text3,@Text4,@Status,@Comment) + ", form); + } + } + + public class ApplicationForm + { + public string UserId { get; set; } + + public string Name { get; set; } + + public string StudentId { get; set; } + + public string College { get; set; } + + public string Major { get; set; } + + public string Mobile { get; set; } + + public string QQ { get; set; } + + public string Score { get; set; } + + [Labels("Nullable")] + public string OJAccounts { get; set; } + + public string Text1 { get; set; } + + public string Text2 { get; set; } + + public string Text3 { get; set; } + + [Labels("Nullable")] + public string Text4 { get; set; } + + public string Status { get; set; } + + [Labels("Nullable")] + public string Comment { get; set; } + + static readonly PropertyInfo[] properties = + typeof(ApplicationForm).GetProperties().Where(prop => !prop.HasLabel("Nullable")).ToArray(); + + public bool Validate() => + properties.All(prop => + !string.IsNullOrWhiteSpace((string)prop.GetValue(this))); } } diff --git a/Startup.cs b/Startup.cs index 03e032d..19c7523 100644 --- a/Startup.cs +++ b/Startup.cs @@ -42,6 +42,7 @@ namespace cugoj_ng_server opt.Cookie.IsEssential = true; opt.IdleTimeout = TimeSpan.FromMinutes(sessionTimeout); }); + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; Utilities.Inject.SetPropertiesByType(typeof(Models.DbConn), null, new() { { typeof(IConnectionMultiplexer), ConnectionMultiplexer.Connect(redisConnstr) }, @@ -50,7 +51,7 @@ namespace cugoj_ng_server services.AddControllers().AddJsonOptions(opt => { opt.JsonSerializerOptions.IncludeFields = true; - }); + }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/Utilities/LabelsAttribute.cs b/Utilities/LabelsAttribute.cs new file mode 100644 index 0000000..ed8a126 --- /dev/null +++ b/Utilities/LabelsAttribute.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace cugoj_ng_server.Utilities +{ + [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] + sealed class LabelsAttribute : Attribute + { + private readonly HashSet LabelSet = null; + + + public LabelsAttribute(params string[] labels) + { + LabelSet = new(labels); + } + public bool HasLabel(string label) => LabelSet.Contains(label); + } + static class LabelExtension + { + public static bool HasLabel(this PropertyInfo propertyInfo, string label) => + propertyInfo.GetCustomAttributes().Any(attr => attr.HasLabel(label)); + } + +} diff --git a/appsettings.json b/appsettings.json index 4e80911..5bad8c6 100644 --- a/appsettings.json +++ b/appsettings.json @@ -9,6 +9,7 @@ "AllowedHosts": "*", "Config": { "SessionTimeout": 1440, - "ProblemsPerPage": 100 + "ProblemsPerPage": 100, + "MaxSolutionSize": 65535 } } diff --git a/cugoj-ng-server.csproj b/cugoj-ng-server.csproj index af4bd8f..93ff987 100644 --- a/cugoj-ng-server.csproj +++ b/cugoj-ng-server.csproj @@ -1,14 +1,14 @@ - net5.0 + net6.0 cugoj_ng_server - - - + + +