-
Jakub Konvička authored7b7efd5b
ApiController.cs 13.60 KiB
using System.ComponentModel.DataAnnotations;
using System.Text;
using Antlr4.Runtime;
using Antlr4.Runtime.Tree;
using CodeParser.Cpp;
using Database;
using Database.Model;
using DiagramBuilder.AbstractCreator;
using DiagramBuilder.ConcreteCreator;
using Microsoft.AspNetCore.Mvc;
using WebAPI.DTO;
using WebAPI.DTO.External;
using WebAPI.Utils;
namespace WebAPI.Controllers
{
[ApiController]
[Route("api/")]
public class ApiController : ControllerBase
{
private readonly ILogger<ApiController> _logger;
private readonly IConfiguration _configuration;
private int tokenValidityMinutes => _configuration.GetValue<int>("UserManagement:TokenValidityMinutes");
public ApiController(ILogger<ApiController> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
using var db = new DatabaseContext();
DatabaseContext.EnsureSeedData(db);
}
#region SourceCodeTransformation
//convert-to-activity-diagram
[HttpGet("convert-to-activity-diagram", Name = "ConvertToActivityDiagram")]
[Produces("application/xml")]
public IActionResult ConvertToActivityDiagram(
[Required(ErrorMessage = "Token is required")]
[RegularExpression(@"^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$", ErrorMessage = "Invalid GUID format for Token")]
string token,
[Required(ErrorMessage = "SourceCodeId is required")]
[Range(1, int.MaxValue, ErrorMessage = "Id must be greater than 0")]
int sourceCodeId,
[Required(ErrorMessage = "FunctionIdentifier is required")]
string functionIdentifier)
{
if (TokenManager.VerifyAndRevalidateToken(token, tokenValidityMinutes))
{
var user = TokenManager.GetUser(token, tokenValidityMinutes);
using var db = new DatabaseContext();
var sourceCode = db.SourceCodes.FirstOrDefault(s => s.Id == sourceCodeId && s.UserId == user.Id);
if (sourceCode == null)
{
return NotFound("Code does not exist");
}
//base 64 string to string
string code = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(sourceCode.Code));
var inputStream = new AntlrInputStream(code);
var lexer = new CPP14Lexer(inputStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CPP14Parser parser = new CPP14Parser(tokens);
ActivityDiagramBuilderCreator activityDiagramBuilderCreator = new ActivityDiagramBuilderCreatorFactory();
var diagramBuilder = activityDiagramBuilderCreator.FactoryMethod("ActivityDiagram");
IParseTree tree = parser.translationUnit();
if (parser.NumberOfSyntaxErrors == 0)
{
CppActivityDiagramVisitor activityDiagramVisitor = new CppActivityDiagramVisitor(diagramBuilder, functionIdentifier);
Console.WriteLine(activityDiagramVisitor.Visit(tree));
}
var xmi = diagramBuilder.BuildDiagram();
byte[] xmiBytes = Encoding.UTF8.GetBytes(xmi);
var xmiStream = new MemoryStream(xmiBytes);
return File(xmiStream, "application/xml", "activity_diagram.xmi");
}
else
{
return BadRequest("Invalid token");
}
}
//convert-to-class-diagram
[HttpGet("convert-to-class-diagram", Name = "ConvertToClassDiagram")]
[Produces("application/xml")]
public IActionResult ConvertToClassDiagram([Required(ErrorMessage = "Token is required")]
[RegularExpression(@"^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$", ErrorMessage = "Invalid GUID format for Token")]
string token,
[Required(ErrorMessage = "SourceCodeId is required")]
[Range(1, int.MaxValue, ErrorMessage = "Id must be greater than 0")]
int sourceCodeId)
{
if (TokenManager.VerifyAndRevalidateToken(token, tokenValidityMinutes))
{
var user = TokenManager.GetUser(token, tokenValidityMinutes);
using var db = new DatabaseContext();
var sourceCode = db.SourceCodes.FirstOrDefault(s => s.Id == sourceCodeId && s.UserId == user.Id);
if (sourceCode == null)
{
return NotFound("Code does not exist");
}
//base 64 string to string
string code = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(sourceCode.Code));
var inputStream = new AntlrInputStream(code);
var lexer = new CPP14Lexer(inputStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CPP14Parser parser = new CPP14Parser(tokens);
ClassDiagramBuilderCreatorFactory classDiagramBuilderCreator = new ClassDiagramBuilderCreatorFactory();
var diagramBuilder = classDiagramBuilderCreator.FactoryMethod("ClassDiagram");
IParseTree tree = parser.translationUnit();
if (parser.NumberOfSyntaxErrors == 0)
{
CppClassDiagramVisitor classDiagramVisitor = new CppClassDiagramVisitor(diagramBuilder);
Console.WriteLine(classDiagramVisitor.Visit(tree));
}
var xmi = diagramBuilder.BuildDiagram();
byte[] xmiBytes = Encoding.UTF8.GetBytes(xmi);
var xmiStream = new MemoryStream(xmiBytes);
return File(xmiStream, "application/xml", "class_diagram.xmi");
}
else
{
return BadRequest("Invalid token");
}
}
#endregion
#region SourceCode
[HttpPost("code", Name = "UploadCode")]
public IActionResult UploadCode(UploadCodeModel model)
{
if (TokenManager.VerifyAndRevalidateToken(model.Token, tokenValidityMinutes))
{
var user = TokenManager.GetUser(model.Token, tokenValidityMinutes);
using var db = new DatabaseContext();
//string to base 64 string
//string codeBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(model.Code));
var sourceCode = new SourceCode
{
Code = model.Code,
UserId = user.Id
};
db.SourceCodes.Add(sourceCode);
db.SaveChanges();
return Ok($"Code uploaded, id: {sourceCode.Id}");
}
else
{
return BadRequest("Invalid token");
}
}
[HttpPost("code-file", Name = "UploadCodeFile")]
public IActionResult UploadCodeFile(string token, IFormFile file)
{
if (TokenManager.VerifyAndRevalidateToken(token, tokenValidityMinutes))
{
var user = TokenManager.GetUser(token, tokenValidityMinutes);
using var db = new DatabaseContext();
using var ms = new MemoryStream();
file.CopyTo(ms);
var fileBytes = ms.ToArray();
string code = System.Text.Encoding.UTF8.GetString(fileBytes);
var base64code = Convert.ToBase64String(fileBytes);
var sourceCode = new SourceCode
{
Code = base64code,
UserId = user.Id
};
db.SourceCodes.Add(sourceCode);
db.SaveChanges();
return Ok($"Code uploaded, id: {sourceCode.Id}");
}
else
{
return BadRequest("Invalid token");
}
}
[HttpDelete("code", Name = "RemoveCode")]
public IActionResult RemoveCode(RemoveCodeModel model)
{
if (TokenManager.VerifyAndRevalidateToken(model.Token, tokenValidityMinutes))
{
var user = TokenManager.GetUser(model.Token, tokenValidityMinutes);
using var db = new DatabaseContext();
var sourceCode = db.SourceCodes.FirstOrDefault(s => s.Id == model.Id && s.UserId == user.Id);
if (sourceCode == null)
{
return NotFound("Code does not exist");
}
db.SourceCodes.Remove(sourceCode);
db.SaveChanges();
return Ok("Code removed");
}
else
{
return BadRequest("Invalid token");
}
}
[HttpGet("code", Name = "ListCode")]
public IActionResult ListCode([Required(ErrorMessage = "Token is required")]
[RegularExpression(@"^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$", ErrorMessage = "Invalid GUID format for Token")]
string token,
[Required(ErrorMessage = "Id is required")]
[Range(1, int.MaxValue, ErrorMessage = "Id must be greater than 0")]
int id)
{
if (TokenManager.VerifyAndRevalidateToken(token, tokenValidityMinutes))
{
var user = TokenManager.GetUser(token, tokenValidityMinutes);
using var db = new DatabaseContext();
var sourceCodes = db.SourceCodes.Where(s =>
s.UserId == user.Id &&
s.Id == id)
.ToList();
if (sourceCodes.Count == 0)
{
return Ok(new List<SourceCodeExt>());
}
List<SourceCodeExt> sourceCodeExts = new List<SourceCodeExt>();
foreach (var sourceCode in sourceCodes)
{
sourceCodeExts.Add(new SourceCodeExt
{
Id = sourceCode.Id,
Code = sourceCode.Code
});
}
return Ok(sourceCodeExts);
}
else
{
return BadRequest("Invalid token");
}
}
[HttpGet("code-all", Name = "ListAllCode")]
public IActionResult ListAllCode([RegularExpression(@"^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$", ErrorMessage = "Invalid GUID format for Token")]
string token)
{
if (TokenManager.VerifyAndRevalidateToken(token, tokenValidityMinutes))
{
var user = TokenManager.GetUser(token, tokenValidityMinutes);
using var db = new DatabaseContext();
var sourceCodes = db.SourceCodes.Where(s =>
s.UserId == user.Id)
.ToList();
if (sourceCodes.Count == 0)
{
return Ok(new List<SourceCodeExt>());
}
List<SourceCodeExt> sourceCodeExts = new List<SourceCodeExt>();
foreach (var sourceCode in sourceCodes)
{
sourceCodeExts.Add(new SourceCodeExt
{
Id = sourceCode.Id,
Code = sourceCode.Code
});
}
return Ok(sourceCodeExts);
}
else
{
return BadRequest("Invalid token");
}
}
#endregion
#region User
[HttpPost("authenticate-user-password", Name = "AuthenticateUserPassword")]
public IActionResult AuthenticateUserPassword(AuthenticateUserModel model)
{
using var db = new DatabaseContext();
var user = db.Users.FirstOrDefault(u => u.Name == model.Username);
if (user == null)
{
return NotFound("User does not exist");
}
if (PasswordHasher.Verify(model.Password, user.PasswordHash))
{
TokenManager.AssignToken(user);
return Ok($"User authenticated, token: {user.Token}");
}
else
{
return BadRequest("User not authenticated");
}
}
[HttpPost("register-user", Name = "RegisterUser")]
public IActionResult RegisterUser(RegisterUserModel model)
{
if (TokenManager.VerifyAndRevalidateToken(model.Token, tokenValidityMinutes))
{
var passwordHash = PasswordHasher.Hash(model.Password);
using var db = new DatabaseContext();
var user = db.Users.FirstOrDefault(u => u.Name == passwordHash);
if (user != null)
{
//user exists
return BadRequest("User already exists");
}
db.Users.Add(new User
{
Name = model.Username,
PasswordHash = passwordHash,
Token = "NOT LOGGED IN YET",
LastAccess = DateTime.MinValue
});
db.SaveChanges();
return Ok("User created");
}
else
{
return BadRequest("Invalid token");
}
}
#endregion
}
}