Skip to content

Commit

Permalink
Added downloading of files.
Browse files Browse the repository at this point in the history
  • Loading branch information
DoggySazHi committed Jun 19, 2021
1 parent d2e303d commit 3fc4162
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Docker/*.class
Docker/*.jar
TestingInput
TestingSource
TestingInclude
sqldialects.xml
contentModel.xml
workspace.xml
Expand Down
2 changes: 1 addition & 1 deletion Controllers/HTMLController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public virtual async Task<IActionResult> Get(string page)
}
}

private static string GetMIME(string file)
public static string GetMIME(string file)
{
var provider = new FileExtensionContentTypeProvider();
return !provider.TryGetContentType(file, out var contentType) ? "application/octet-stream" : contentType;
Expand Down
8 changes: 4 additions & 4 deletions Controllers/MySqlQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ public async Task<int> AddTest(string name, IEnumerable<string> testers, IEnumer
/// <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)
{
const string commandMySql = "INSERT INTO Modulr.Stipulatables (`name`, testers, required) VALUES (@Name, @Testers, @Required); SELECT LAST_INSERT_ID();";
const string commandMySql = "INSERT INTO Modulr.Stipulatables (`name`, testers, required, provided, description) VALUES (@Name, @Testers, @Required, @Provided, @Description); SELECT LAST_INSERT_ID();";
var results = await Connection.QuerySingleOrDefaultAsync<int>(ConvertSql(commandMySql),
new {Name = name, Testers = JsonConvert.SerializeObject(testers), Required = JsonConvert.SerializeObject(required)});
new { Name = name, Testers = JsonConvert.SerializeObject(testers), Required = JsonConvert.SerializeObject(required), Provided = JsonConvert.SerializeObject(included), Description = description });
return results;
}

Expand All @@ -109,10 +109,10 @@ public async Task<bool> UpdateTest(int id, string name, IEnumerable<string> test
{
const string commandMySql = "UPDATE Modulr.Stipulatables SET `name` = @Name, testers = @Testers, required = @Required WHERE id = @ID";
return await Connection.ExecuteAsync(ConvertSql(commandMySql),
new {Name = name,
new { Name = name,
Testers = JsonConvert.SerializeObject(testers),
Required = JsonConvert.SerializeObject(required),
ID = id}) != 0;
ID = id }) != 0;
}

/// <summary>
Expand Down
28 changes: 28 additions & 0 deletions Controllers/TestController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,34 @@ public async Task<string> FileUpload([FromForm] TesterFiles input)
await _query.DecrementAttempts(user.Subject);
return output;
}

/// <summary>
/// Allow a user to download a provided file.
/// </summary>
/// <param name="file">A file requested from the user.</param>
/// <returns>Data representing the file, or an error message.</returns>
[HttpPost("Download")]
public async Task<IActionResult> FileDownload([FromBody] DownloadFile file)
{
if (file.File == null)
return BadRequest("Bad Filename!!");

var (status, _) = await _auth.Verify(file.AuthToken);
if (status != GoogleAuth.LoginStatus.Success)
return Forbid();

var test = await _query.GetTest(file.TestID);
if (test == null)
return NotFound("Failed to find Test ID!");

var fileName = Path.GetFileName(file.File);
var path = Path.Combine(Path.Join(_config.IncludeLocation, "" + file.TestID), fileName!);
if (!System.IO.File.Exists(path))
return NotFound("File not found!");

var stream = System.IO.File.OpenRead(path);
return new FileStreamResult(stream, HTMLController.GetMIME(fileName));
}

/// <summary>
/// A simple way to fail with a HTTP status.
Expand Down
4 changes: 2 additions & 2 deletions Models/AdminStipulatable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public class AdminStipulatable
public bool Valid { get; set; }
public IReadOnlyCollection<TesterFile> TesterFiles => _testerFiles;
public IReadOnlyCollection<string> RequiredFiles => _requiredFiles;
private readonly List<TesterFile> _testerFiles = new List<TesterFile>();
private readonly List<string> _requiredFiles = new List<string>();
private readonly List<TesterFile> _testerFiles = new();
private readonly List<string> _requiredFiles = new();

public AdminStipulatable(Stipulatable sp)
{
Expand Down
8 changes: 8 additions & 0 deletions Models/DownloadFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Modulr.Models
{
public class DownloadFile : BasicAuth
{
public int TestID { get; set; }
public string File { get; set; }
}
}
3 changes: 1 addition & 2 deletions Models/TestQuery.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
namespace Modulr.Models
{
public class TestQuery
public class TestQuery : BasicAuth
{
public string AuthToken { get; set; }
public int TestID { get; set; }
}
}
13 changes: 13 additions & 0 deletions Modulr.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<Content Include="StaticViews\**\*.*" Exclude="StaticViews\img\manifest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Remove="TestingIncluded\**" />
</ItemGroup>

<ItemGroup>
Expand All @@ -29,4 +30,16 @@
<Folder Include="RestrictedViews\img" />
<Folder Include="TestingSource\hidden" />
</ItemGroup>

<ItemGroup>
<Compile Remove="TestingIncluded\**" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Remove="TestingIncluded\**" />
</ItemGroup>

<ItemGroup>
<None Remove="TestingIncluded\**" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Modulr
{
public class Program
public static class Program
{
public static void Main(string[] args)
{
Expand Down
1 change: 0 additions & 1 deletion Startup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Builder;
Expand Down
57 changes: 52 additions & 5 deletions StaticViews/js/tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ async function getAllTests() {
handleErrors(0, e);
}
}

async function getAttemptsLeft() {
try {
let response = await fetch("/Users/GetTimeout", {
Expand Down Expand Up @@ -299,11 +300,57 @@ function generateProvided(provided) {
let providedList = providedArea.querySelector(".center");
providedList.innerHTML = "";
for (let file of provided) {
let link = document.createElement("a");
link.href = "javascript:alert('Download link for " + file + "')";
link.className = "input normal";
link.innerHTML = file;
providedList.appendChild(link);
//<label class="input normal">GQ_Decimal_Converter.java<input type="file" name="GQ_Decimal_Converter.java"></label>
let button = document.createElement("button");
button.className = "input normal";
button.innerHTML = file;
button.addEventListener("click", async (e) => {
e.preventDefault();
await downloadFile(file);
});
providedList.appendChild(button);
}
}

async function downloadFile(file) {
try {
let response = await fetch("/Tester/Download", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"AuthToken": getLoginToken(),
"TestID": currentTest,
"File": file
})
});
if (response.status >= 400 && response.status < 600) {
handleErrors(response.status, null);
} else {
// What's compatibility? And can I eat it?
const newBlob = new Blob([ await response.blob() ], { type: response.headers.get("Content-Type") });

if (window.navigator && window.navigator.msSaveOrOpenBlob)
window.navigator.msSaveOrOpenBlob(newBlob);
else {
const data = URL.createObjectURL(newBlob);
/* const newPanel = open(data, "_blank");
if (newPanel !== null)
newPanel.focus(); */

let link = document.createElement("a");
link.href = data;
link.download = file;
link.click();

// I saw this somewhere, apparently for Firefox.
setTimeout(() => { URL.revokeObjectURL(data); }, 250);
}
}
}
catch (e) {
handleErrors(0, e);
}
}

Expand Down
5 changes: 5 additions & 0 deletions Tester/ModulrConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class ModulrConfig
[JsonProperty] public bool AutoUpdateDockerImage { get; private set; }
[JsonProperty] public string SaveLocation { get; private set; }
[JsonProperty] public string SourceLocation { get; private set; }
[JsonProperty] public string IncludeLocation { get; private set; }
[JsonProperty] public string SqlServer { get; private set; }
[JsonProperty] public int SqlPort { get; private set; }
[JsonProperty] public string SqlPassword { get; private set; }
Expand Down Expand Up @@ -95,6 +96,10 @@ private void SetDefaultConfig()
SqlServer = "localhost";
UseMySql = true;
TimeoutAttempts = -1;

SourceLocation = "TestingSource";
SaveLocation = "TestingInput";
IncludeLocation = "TestingInclude";
}

private readonly string[] _dockerWinPath = {
Expand Down
2 changes: 1 addition & 1 deletion Tester/ModulrJail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Modulr.Tester
/// </summary>
public abstract class ModulrJail : IDisposable
{
private static readonly string MODULR_STIPULATOR_GITHUB = "https://github.com/DoggySazHi/Modulr.Stipulator/releases/latest/download/Modulr.Stipulator.jar";
private const string MODULR_STIPULATOR_GITHUB = "https://github.com/DoggySazHi/Modulr.Stipulator/releases/latest/download/Modulr.Stipulator.jar";

public static ModulrConfig Config { private protected get; set; }
public static TestWorker WebSocket { private protected get; set; }
Expand Down

0 comments on commit 3fc4162

Please sign in to comment.