Skip to content

Commit

Permalink
More uploading features for included files.
Browse files Browse the repository at this point in the history
  • Loading branch information
DoggySazHi committed Jun 20, 2021
1 parent 3fc4162 commit e32b65d
Show file tree
Hide file tree
Showing 19 changed files with 263 additions and 104 deletions.
4 changes: 2 additions & 2 deletions Controllers/AdminController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ namespace Modulr.Controllers
[Route("/Admin/{**page}")]
public class AdminController : HTMLController
{
private readonly MySqlQuery _query;
private readonly SqlQuery _query;

public AdminController(ILogger<HTMLController> logger, MySqlQuery query, ModulrConfig config) : base(logger, config)
public AdminController(ILogger<HTMLController> logger, SqlQuery query, ModulrConfig config) : base(logger, config)
{
_query = query;
}
Expand Down
4 changes: 2 additions & 2 deletions Controllers/AdminSystemController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ namespace Modulr.Controllers
[Route("/Admin/System")]
public class AdminSystemController : ControllerBase
{
private readonly MySqlQuery _query;
private readonly SqlQuery _query;
private readonly GoogleAuth _auth;
private readonly IHostApplicationLifetime _app;

public AdminSystemController(MySqlQuery query, ModulrConfig config, GoogleAuth auth, IHostApplicationLifetime app)
public AdminSystemController(SqlQuery query, ModulrConfig config, GoogleAuth auth, IHostApplicationLifetime app)
{
_query = query;
ModulrJail.Config = config;
Expand Down
32 changes: 21 additions & 11 deletions Controllers/AdminTestController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ namespace Modulr.Controllers
[Route("/Admin/Tester")]
public class AdminTestController : ControllerBase
{
private readonly MySqlQuery _query;
private readonly SqlQuery _query;
private readonly ModulrConfig _config;
private readonly GoogleAuth _auth;

public AdminTestController(MySqlQuery query, ModulrConfig config, GoogleAuth auth)
public AdminTestController(SqlQuery query, ModulrConfig config, GoogleAuth auth)
{
_query = query;
_config = config;
Expand All @@ -41,7 +41,7 @@ public async Task<int> OnAdd([FromBody] UpdateTesterFiles input)
return -1;
}

return await _query.AddTest(input.TestName, input.Testers, input.Required);
return await _query.AddTest(input.TestName, input.TestDescription, input.Included, input.Testers, input.Required);
}

[HttpPost("GetAll")]
Expand Down Expand Up @@ -114,7 +114,7 @@ public async Task<bool> UpdateTest([FromBody] UpdateTesterFiles input)
return false;
}

return await _query.UpdateTest(input.TestID, input.TestName, input.Testers, input.Required);
return await _query.UpdateTest(input.TestID, input.TestName, input.TestDescription, input.Included, input.Testers, input.Required);
}

[HttpDelete("Delete")]
Expand All @@ -128,10 +128,18 @@ public async Task<bool> DeleteTest([FromBody] int id)

return await _query.DeleteTest(id);
}

[HttpPost("Upload")]

[HttpPost("UploadSource")]
[RequestSizeLimit(33554432)] // 32 MiB max
public async Task<string> FileUploadSource([FromForm] TesterFiles input)
=> await FileUpload(input, _config.SourceLocation, true);

[HttpPost("UploadInclude")]
[RequestSizeLimit(33554432)] // 32 MiB max
public async Task<string> FileUpload([FromForm] TesterFiles input)
public async Task<string> FileUploadInclude([FromForm] TesterFiles input)
=> await FileUpload(input, _config.IncludeLocation);

private async Task<string> FileUpload(TesterFiles input, string baseLocation, bool verify = false)
{
if (input.IsEmpty())
return "WARNING: No files were found, nothing was uploaded!";
Expand All @@ -154,23 +162,25 @@ public async Task<string> FileUpload([FromForm] TesterFiles input)
for (var i = 0; i < input.Files.Count; i++)
{
var file = input.Files[i];
if (file.Length > 8 * 1024 * 1024) continue;

var fileName = input.FileNames[i] ?? Path.GetFileName(file.FileName);
var outputPath = Path.Join(_config.SourceLocation, fileName);
var sourcePath = Path.Join(baseLocation, "" + input.TestID);
Directory.CreateDirectory(sourcePath);
var outputPath = Path.Combine(sourcePath, fileName);
var backupPath = outputPath;
if (System.IO.File.Exists(backupPath))
{
var counter = 0;
do
{
counter++;
backupPath = Path.Join(_config.SourceLocation, $"old-{counter}-{fileName}");
backupPath = Path.Combine(sourcePath, $"old-{counter}-{fileName}");
} while (System.IO.File.Exists(backupPath));
System.IO.File.Move(outputPath, backupPath);
output.AppendLine($"WARNING: {fileName} existed already, made a copy at {backupPath}.");
}

if (test != null && test.RequiredFiles.Contains(fileName))
if (verify && test != null && test.RequiredFiles.Contains(fileName))
output.AppendLine(
$"WARNING: {fileName} is a required file; it will not be copied during stipulation!");
await using var stream = new FileStream(outputPath, FileMode.Create);
Expand Down
4 changes: 2 additions & 2 deletions Controllers/GoogleAuth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ namespace Modulr.Controllers
public class GoogleAuth
{
private readonly ModulrConfig _config;
private readonly MySqlQuery _query;
private readonly SqlQuery _query;

public GoogleAuth(ModulrConfig config, MySqlQuery query)
public GoogleAuth(ModulrConfig config, SqlQuery query)
{
_config = config;
_query = query;
Expand Down
48 changes: 19 additions & 29 deletions Controllers/MySqlQuery.cs → Controllers/SqlQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Modulr.Controllers
/// <summary>
/// A class that manages database connections to the Modulr backend.
/// </summary>
public class MySqlQuery : IDisposable
public class SqlQuery : IDisposable
{
private IDbConnection Connection { get; }
private readonly ModulrConfig _config;
Expand All @@ -27,17 +27,17 @@ public void Dispose()
GC.SuppressFinalize(this);
}

~MySqlQuery()
~SqlQuery()
{
Dispose();
}

static MySqlQuery()
static SqlQuery()
{
DefaultTypeMap.MatchNamesWithUnderscores = true;
}

public MySqlQuery(ModulrConfig config)
public SqlQuery(ModulrConfig config)
{
_config = config;
if (config.UseMySql)
Expand All @@ -58,26 +58,11 @@ public async Task<Stipulatable> GetTest(int id)
if (results == null)
return null;
var description = results.description;
var included = JsonConvert.DeserializeObject<IEnumerable<string>>(results.included);
var testers = JsonConvert.DeserializeObject<IEnumerable<string>>(results.testers);
var required = JsonConvert.DeserializeObject<IEnumerable<string>>(results.required);
var included = JsonConvert.DeserializeObject<IEnumerable<string>>(results.provided);

return new Stipulatable(results.id, results.name, testers, required, description, included);
}

/// <summary>
/// Add a test to the database with the following parameters.
/// </summary>
/// <param name="name">The name of the test.</param>
/// <param name="testers">The order of compilation, as well as files that should be included.</param>
/// <param name="required">Files that are requested from the user on the interface.</param>
/// <returns>An integer, representing the ID of the <code>Stipulatable</code>.</returns>
public async Task<int> AddTest(string name, IEnumerable<string> testers, IEnumerable<string> required)
{
const string commandMySql = "INSERT INTO Modulr.Stipulatables (`name`, testers, required) VALUES (@Name, @Testers, @Required); SELECT LAST_INSERT_ID();";
var results = await Connection.QuerySingleOrDefaultAsync<int>(ConvertSql(commandMySql),
new {Name = name, Testers = JsonConvert.SerializeObject(testers), Required = JsonConvert.SerializeObject(required)});
return results;
return new Stipulatable(results.id, results.name, description, included, testers, required);
}

/// <summary>
Expand All @@ -89,27 +74,31 @@ public async Task<int> AddTest(string name, IEnumerable<string> testers, IEnumer
/// <param name="description">A short description of what the test is about.</param>
/// <param name="included">Files that are displayed for the user to download.</param>
/// <returns>An integer, representing the ID of the <code>Stipulatable</code>.</returns>
public async Task<int> AddTest(string name, IEnumerable<string> testers, IEnumerable<string> required, string description, IEnumerable<string> included)
public async Task<int> AddTest(string name, string description, IEnumerable<string> included, IEnumerable<string> testers, IEnumerable<string> required)
{
const string commandMySql = "INSERT INTO Modulr.Stipulatables (`name`, testers, required, provided, description) VALUES (@Name, @Testers, @Required, @Provided, @Description); SELECT LAST_INSERT_ID();";
const string commandMySql = "INSERT INTO Modulr.Stipulatables (`name`, testers, required, included, description) VALUES (@Name, @Testers, @Required, @Included, @Description); SELECT LAST_INSERT_ID();";
var results = await Connection.QuerySingleOrDefaultAsync<int>(ConvertSql(commandMySql),
new { Name = name, Testers = JsonConvert.SerializeObject(testers), Required = JsonConvert.SerializeObject(required), Provided = JsonConvert.SerializeObject(included), Description = description });
new { Name = name, Testers = JsonConvert.SerializeObject(testers), Required = JsonConvert.SerializeObject(required), Included = JsonConvert.SerializeObject(included), Description = description });
return results;
}

/// <summary>
/// Update a test's information by its ID.
/// </summary>
/// <param name="id">The ID of the test.</param>
/// <param name="name">The new name of the test.</param>
/// <param name="description">The description associated with the test</param>
/// <param name="included">The files that are available for the user to download.</param>
/// <param name="testers">The new compile/include order for the test.</param>
/// <param name="required">The new files</param>
/// <param name="required">The files that are requested from the user.</param>
/// <returns>Whether a test was updated or not.</returns>
public async Task<bool> UpdateTest(int id, string name, IEnumerable<string> testers, IEnumerable<string> required)
public async Task<bool> UpdateTest(int id, string name, string description, IEnumerable<string> included, IEnumerable<string> testers, IEnumerable<string> required)
{
const string commandMySql = "UPDATE Modulr.Stipulatables SET `name` = @Name, testers = @Testers, required = @Required WHERE id = @ID";
const string commandMySql = "UPDATE Modulr.Stipulatables SET `name` = @Name, `description` = @Description, included = @Included, testers = @Testers, required = @Required WHERE id = @ID";
return await Connection.ExecuteAsync(ConvertSql(commandMySql),
new { Name = name,
Description = description,
Included = JsonConvert.SerializeObject(included),
Testers = JsonConvert.SerializeObject(testers),
Required = JsonConvert.SerializeObject(required),
ID = id }) != 0;
Expand Down Expand Up @@ -207,9 +196,10 @@ public async Task<List<Stipulatable>> GetAllTests()
const string commandMySql = "SELECT * FROM Modulr.Stipulatables";
return (await Connection.QueryAsync(ConvertSql(commandMySql))).ToList().Select(o =>
{
var included = JsonConvert.DeserializeObject<List<string>>(o.included);
var testers = JsonConvert.DeserializeObject<List<string>>(o.testers);
var required = JsonConvert.DeserializeObject<List<string>>(o.required);
return new Stipulatable(o.id, o.name, testers, required);
return new Stipulatable(o.id, o.name, o.description, included, testers, required);
}).ToList();
}

Expand Down
17 changes: 9 additions & 8 deletions Controllers/TestController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ namespace Modulr.Controllers
public class TestReceivedController : ControllerBase
{
private readonly JavaUtils _java;
private readonly MySqlQuery _query;
private readonly SqlQuery _query;
private readonly GoogleAuth _auth;
private readonly ModulrConfig _config;

public TestReceivedController(JavaUtils java, MySqlQuery query, GoogleAuth auth, ModulrConfig config)
public TestReceivedController(JavaUtils java, SqlQuery query, GoogleAuth auth, ModulrConfig config)
{
_java = java;
_query = query;
Expand Down Expand Up @@ -90,22 +90,23 @@ public async Task<string> FileUpload([FromForm] TesterFiles input)
return Fail(404, "Failed to find Test ID!");

var path = _java.GetDummyFolder();
var srcPath = Path.Join(path, "source");
Directory.CreateDirectory(srcPath);
var inputPath = Path.Join(path, "source");
Directory.CreateDirectory(inputPath);
for (var i = 0; i < input.Files.Count; i++)
{
var file = input.Files[i];
if (file.Length > 8 * 1024 * 1024) continue;
var fileName = input.FileNames[i];
var outputPath = Path.Join(srcPath, fileName);
var outputPath = Path.Combine(inputPath, fileName);
await using var stream = new FileStream(outputPath, FileMode.Create);
await file.CopyToAsync(stream);
}

foreach (var file in test.TesterFiles)
{
var tester = Path.Join(_config.SourceLocation, file);
var testerOut = Path.Join(srcPath, file);
var sourcePath = Path.Join(_config.SourceLocation, "" + input.TestID);
var tester = Path.Combine(sourcePath, file);
var testerOut = Path.Combine(inputPath, file);
if (!System.IO.File.Exists(tester) || System.IO.File.Exists(testerOut))
continue;
System.IO.File.Copy(tester, testerOut);
Expand All @@ -118,7 +119,7 @@ public async Task<string> FileUpload([FromForm] TesterFiles input)
}

/// <summary>
/// Allow a user to download a provided file.
/// Allow a user to download an included file.
/// </summary>
/// <param name="file">A file requested from the user.</param>
/// <returns>Data representing the file, or an error message.</returns>
Expand Down
4 changes: 2 additions & 2 deletions Controllers/UserController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ namespace Modulr.Controllers
[Route("/Users")]
public class UserController : ControllerBase
{
private readonly MySqlQuery _query;
private readonly SqlQuery _query;
private readonly GoogleAuth _auth;

public UserController(MySqlQuery query, GoogleAuth auth)
public UserController(SqlQuery query, GoogleAuth auth)
{
_query = query;
_auth = auth;
Expand Down
77 changes: 77 additions & 0 deletions CreateDatabase.mssql.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* I just used the scripting option in SSMS, so some of this might be wrong. */

USE [master]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE DATABASE [Modulr]
CONTAINMENT = NONE
GO

USE [Modulr]
GO

CREATE TABLE [Tester].[Users]
(
[id] [int] IDENTITY (1,1) NOT NULL,
[google_id] [nvarchar](64) NOT NULL,
[username] [nvarchar](32) NOT NULL,
[name] [nvarchar](32) NOT NULL,
[email] [nvarchar](128) NOT NULL,
[tests_remaining] [int] NOT NULL,
[tests_timeout] [datetimeoffset](7) NOT NULL,
[role] [tinyint] NOT NULL,
CONSTRAINT [Users_pk] PRIMARY KEY NONCLUSTERED
(
[id] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [Tester].[Users]
ADD DEFAULT ((3)) FOR [tests_remaining]
GO

ALTER TABLE [Tester].[Users]
ADD DEFAULT (sysdatetimeoffset()) FOR [tests_timeout]
GO

ALTER TABLE [Tester].[Users]
ADD DEFAULT ((0)) FOR [role]
GO

CREATE TABLE [Tester].[Stipulatables]
(
[id] [int] IDENTITY (1,1) NOT NULL,
[name] [nvarchar](255) NOT NULL,
[testers] [nvarchar](4000) NOT NULL,
[required] [nvarchar](4000) NULL,
[included] [nvarchar](4000) NULL,
[description] [nvarchar](2048) NOT NULL,
CONSTRAINT [Stipulatables_pk] PRIMARY KEY NONCLUSTERED
(
[id] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [Tester].[Stipulatables]
ADD DEFAULT ('[]') FOR [testers]
GO

ALTER TABLE [Tester].[Stipulatables]
ADD DEFAULT ('[]') FOR [required]
GO

ALTER TABLE [Tester].[Stipulatables]
ADD DEFAULT ('[]') FOR [included]
GO

ALTER TABLE [Tester].[Stipulatables]
ADD DEFAULT ('') FOR [description]
GO
2 changes: 1 addition & 1 deletion CreateDatabase.sql → CreateDatabase.mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS Modulr.Stipulatables
name VARCHAR(255) NOT NULL,
testers JSON DEFAULT '[]' NOT NULL,
required JSON DEFAULT '[]' NOT NULL,
provided JSON default '[]' null,
included JSON default '[]' null,
description VARCHAR(2048) default '' not null,

PRIMARY KEY (id)
Expand Down
Loading

0 comments on commit e32b65d

Please sign in to comment.