mirror of
https://github.com/MvDevsUnion/WPetition.git
synced 2026-01-14 09:29:29 +00:00
i did that shit
This commit is contained in:
241
Submission.Api/Controllers/DebugController.cs
Normal file
241
Submission.Api/Controllers/DebugController.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using Ashi.MongoInterface.Service;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Submission.Api.Configuration;
|
||||
using Submission.Api.Models;
|
||||
using System.Globalization;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace Submission.Api.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class DebugController : ControllerBase
|
||||
{
|
||||
private readonly PetitionSettings _petitionSettings;
|
||||
private readonly IMongoRepository<Author> _authorRepository;
|
||||
private readonly IMongoRepository<PetitionDetail> _petitionRepository;
|
||||
|
||||
public DebugController(
|
||||
IOptions<PetitionSettings> petitionSettings,
|
||||
IMongoRepository<Author> authorRepository,
|
||||
IMongoRepository<PetitionDetail> petitionRepository)
|
||||
{
|
||||
_petitionSettings = petitionSettings.Value;
|
||||
_authorRepository = authorRepository;
|
||||
_petitionRepository = petitionRepository;
|
||||
}
|
||||
|
||||
[HttpGet("petitions", Name = "GetPetitions")]
|
||||
public IActionResult GetPetitions()
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = Directory.EnumerateFiles("Petitions");
|
||||
return Ok(files);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Problem("Petitions Folder not found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("create-petition-folder", Name = "CreatePetitionFolder")]
|
||||
public IActionResult create_petition_folder()
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory("Petitions");
|
||||
return Ok("Petitions folder created");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Problem(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("upload-petition", Name = "UploadPetition")]
|
||||
public async Task<IActionResult> UploadPetition(IFormFile file)
|
||||
{
|
||||
// Check if petition creation is allowed
|
||||
if (!_petitionSettings.AllowPetitionCreation)
|
||||
{
|
||||
return StatusCode(403, new { message = "Petition creation is disabled. Set 'PetitionSettings:AllowPetitionCreation' to true in appsettings.json" });
|
||||
}
|
||||
|
||||
// Validate file exists
|
||||
if (file == null || file.Length == 0)
|
||||
{
|
||||
return BadRequest(new { message = "No file uploaded" });
|
||||
}
|
||||
|
||||
// Validate file extension
|
||||
if (!file.FileName.EndsWith(".md", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return BadRequest(new { message = "Only .md files are allowed" });
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Read file content
|
||||
string fileContent;
|
||||
using (var reader = new StreamReader(file.OpenReadStream()))
|
||||
{
|
||||
fileContent = await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
// Parse frontmatter and body
|
||||
var (frontmatter, body) = ParseMarkdownFile(fileContent);
|
||||
|
||||
if (frontmatter == null)
|
||||
{
|
||||
return BadRequest(new { message = "Invalid markdown format. Frontmatter is required." });
|
||||
}
|
||||
|
||||
// Parse YAML frontmatter
|
||||
var deserializer = new DeserializerBuilder()
|
||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
||||
.Build();
|
||||
|
||||
var metadata = deserializer.Deserialize<Dictionary<string, object>>(frontmatter);
|
||||
|
||||
// Extract values
|
||||
var petitionId = Guid.NewGuid();
|
||||
var startDateStr = metadata["startDate"].ToString();
|
||||
var nameDhiv = metadata["nameDhiv"].ToString();
|
||||
var nameEng = metadata["nameEng"].ToString();
|
||||
var authorData = metadata["author"] as Dictionary<object, object>;
|
||||
|
||||
var authorName = authorData["name"].ToString();
|
||||
var authorNid = authorData["nid"].ToString();
|
||||
|
||||
// Parse start date (format: dd-MM-yyyy)
|
||||
var startDate = DateOnly.ParseExact(startDateStr, "dd-MM-yyyy", CultureInfo.InvariantCulture);
|
||||
|
||||
// Parse petition bodies from markdown
|
||||
var (petitionBodyDhiv, petitionBodyEng) = ParsePetitionBodies(body);
|
||||
|
||||
// Check if petition already exists
|
||||
var existingPetition = await _petitionRepository.FindByIdAsync(petitionId);
|
||||
if (existingPetition != null)
|
||||
{
|
||||
return Conflict(new { message = $"A petition with ID '{petitionId}' already exists in the database" });
|
||||
}
|
||||
|
||||
// Create or get author
|
||||
var author = await _authorRepository.FindOneAsync(x => x.NID == authorNid);
|
||||
if (author == null)
|
||||
{
|
||||
author = new Author
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = authorName,
|
||||
NID = authorNid
|
||||
};
|
||||
await _authorRepository.InsertOneAsync(author);
|
||||
}
|
||||
|
||||
// Create petition
|
||||
var petition = new PetitionDetail
|
||||
{
|
||||
Id = petitionId,
|
||||
StartDate = startDate,
|
||||
NameDhiv = nameDhiv,
|
||||
NameEng = nameEng,
|
||||
AuthorId = author.Id,
|
||||
PetitionBodyDhiv = petitionBodyDhiv,
|
||||
PetitionBodyEng = petitionBodyEng,
|
||||
SignatureCount = 0
|
||||
};
|
||||
|
||||
await _petitionRepository.InsertOneAsync(petition);
|
||||
|
||||
// Save file with GUID prefix
|
||||
Directory.CreateDirectory("Petitions");
|
||||
var newFileName = $"{Guid.NewGuid()}_{file.FileName}";
|
||||
var filePath = Path.Combine("Petitions", newFileName);
|
||||
|
||||
await System.IO.File.WriteAllTextAsync(filePath, fileContent);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
message = "Petition created successfully",
|
||||
petitionId = petitionId,
|
||||
fileName = newFileName,
|
||||
filePath = filePath,
|
||||
authorId = author.Id
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Problem(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private (string frontmatter, string body) ParseMarkdownFile(string content)
|
||||
{
|
||||
var lines = content.Split('\n');
|
||||
if (lines.Length < 3 || lines[0].Trim() != "---")
|
||||
{
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
var frontmatterLines = new List<string>();
|
||||
var bodyLines = new List<string>();
|
||||
var inFrontmatter = true;
|
||||
var frontmatterClosed = false;
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
if (lines[i].Trim() == "---" && inFrontmatter)
|
||||
{
|
||||
inFrontmatter = false;
|
||||
frontmatterClosed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inFrontmatter)
|
||||
{
|
||||
frontmatterLines.Add(lines[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
bodyLines.Add(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!frontmatterClosed)
|
||||
{
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
return (string.Join("\n", frontmatterLines), string.Join("\n", bodyLines));
|
||||
}
|
||||
|
||||
private (string dhivehiBody, string englishBody) ParsePetitionBodies(string body)
|
||||
{
|
||||
var dhivehiBody = "";
|
||||
var englishBody = "";
|
||||
|
||||
var sections = body.Split("##", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var section in sections)
|
||||
{
|
||||
var trimmed = section.Trim();
|
||||
if (trimmed.StartsWith("Petition Body (Dhivehi)", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dhivehiBody = trimmed.Replace("Petition Body (Dhivehi)", "").Trim();
|
||||
}
|
||||
else if (trimmed.StartsWith("Petition Body (English)", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
englishBody = trimmed.Replace("Petition Body (English)", "").Trim();
|
||||
}
|
||||
}
|
||||
|
||||
return (dhivehiBody, englishBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
using System.CodeDom;
|
||||
using System.Runtime.InteropServices;
|
||||
using Ashi.MongoInterface.Service;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using MongoDB.Driver;
|
||||
using Submission.Api.Dto;
|
||||
using Submission.Api.Models;
|
||||
|
||||
@@ -14,16 +12,16 @@ namespace Submission.Api.Controllers
|
||||
[ApiController]
|
||||
public class SignController : ControllerBase
|
||||
{
|
||||
|
||||
|
||||
private readonly IMongoRepository<Author> _authorRepository;
|
||||
private readonly IMongoRepository<PetitionDetail> _detailRepository;
|
||||
private readonly IMongoRepository<Widget> _signatureRepository;
|
||||
private readonly IMongoRepository<Signature> _signatureRepository;
|
||||
private readonly IMemoryCache _cache;
|
||||
|
||||
public SignController(
|
||||
IMongoRepository<Author> authorRepository,
|
||||
IMongoRepository<PetitionDetail> detailRepository,
|
||||
IMongoRepository<Widget> signatureRepository,
|
||||
IMongoRepository<Signature> signatureRepository,
|
||||
IMemoryCache cache)
|
||||
{
|
||||
_authorRepository = authorRepository;
|
||||
@@ -32,32 +30,53 @@ namespace Submission.Api.Controllers
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
[HttpPost(Name = "petition/{id}")]
|
||||
[HttpPost("petition/{petition_id}", Name = "SignPetition")]
|
||||
[EnableRateLimiting("SignPetitionPolicy")]
|
||||
public async Task<IActionResult> SignDisHoe([FromRoute]Guid petition_id,[FromBody] WidgetsDto body)
|
||||
public async Task<IActionResult> SignDisHoe([FromRoute] Guid petition_id, [FromBody] WidgetsDto body)
|
||||
{
|
||||
var cacheKey = $"petition_{petition_id}";
|
||||
|
||||
var pet = await _detailRepository.FindByIdAsync(petition_id);
|
||||
|
||||
if (pet == null)
|
||||
return NotFound();
|
||||
|
||||
//TODO : add svg validation
|
||||
|
||||
|
||||
//check to see if the same person signed the petition already
|
||||
//if dupe send error saying user already signed
|
||||
var dupe = await _signatureRepository.FindOneAsync(x => x.IdCard == body.IdCard);
|
||||
if (dupe != null)
|
||||
return Problem("You already signed this petition");
|
||||
|
||||
var dupe = await _signatureRepository.FindOneAsync(x => x.IdCard == body.IdCard);
|
||||
if (dupe != null)
|
||||
return Problem("You already signed this petition");
|
||||
|
||||
//add signature to the db
|
||||
await _signatureRepository.InsertOneAsync(new Widget
|
||||
await _signatureRepository.InsertOneAsync(new Signature
|
||||
{
|
||||
IdCard = body.IdCard,
|
||||
Name = body.Name,
|
||||
Signature_SVG = body.Signature,
|
||||
Timestamp = DateTime.Now
|
||||
Timestamp = DateTime.Now,
|
||||
PetitionId = petition_id
|
||||
});
|
||||
|
||||
|
||||
//update signature count
|
||||
|
||||
if (pet.SignatureCount == null)
|
||||
{
|
||||
pet.SignatureCount = 0;
|
||||
}
|
||||
|
||||
var count_update_filter = Builders<PetitionDetail>.Filter.Eq("_id", petition_id);
|
||||
var Countupdate = Builders<PetitionDetail>.Update.Inc("SignatureCount", 1);
|
||||
await _detailRepository.UpdateOneAsync(count_update_filter, Countupdate);
|
||||
|
||||
_cache.Remove(cacheKey);
|
||||
|
||||
return Ok("your signature has been submitted");
|
||||
}
|
||||
|
||||
[HttpGet(Name = "petition/{id}")]
|
||||
public async Task<IActionResult> GetDisHoe([FromRoute] Guid petition_id)
|
||||
[HttpGet("petition/{petition_id}", Name = "GetPetition")]
|
||||
public async Task<IActionResult> GetDisHoe([FromRoute] Guid petition_id)
|
||||
{
|
||||
var cacheKey = $"petition_{petition_id}";
|
||||
|
||||
@@ -68,7 +87,7 @@ namespace Submission.Api.Controllers
|
||||
}
|
||||
|
||||
// Not in cache, fetch from database
|
||||
var pet = await _detailRepository.FindByIdAsync(petition_id);
|
||||
var pet = await _detailRepository.FindByIdAsync(petition_id);
|
||||
|
||||
if (pet == null)
|
||||
return NotFound();
|
||||
@@ -88,12 +107,14 @@ namespace Submission.Api.Controllers
|
||||
{
|
||||
Name = author.Name,
|
||||
NID = author.NID,
|
||||
}
|
||||
},
|
||||
|
||||
SignatureCount = pet.SignatureCount
|
||||
};
|
||||
|
||||
// Store in cache with 5 minute expiration
|
||||
var cacheOptions = new MemoryCacheEntryOptions()
|
||||
.SetAbsoluteExpiration(TimeSpan.FromHours(12));
|
||||
.SetAbsoluteExpiration(TimeSpan.FromHours(1));
|
||||
|
||||
_cache.Set(cacheKey, dto, cacheOptions);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user