i did that shit

This commit is contained in:
fISHIE
2025-12-14 12:09:05 +05:00
parent cea629affa
commit 0d763ea736
14 changed files with 1087 additions and 71 deletions

View 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);
}
}
}

View File

@@ -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);