mirror of
https://github.com/MvDevsUnion/WPetition.git
synced 2026-04-29 03:23:13 +00:00
idk
This commit is contained in:
302
README.md
Normal file
302
README.md
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
# Petition Submission API
|
||||||
|
|
||||||
|
A petition signing API built with ASP.NET Core 9.0 that allows users to sign petitions and retrieve petition details. Features rate limiting to prevent spam and duplicate signature detection.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Sign petitions with digital signatures
|
||||||
|
- Retrieve petition details including author information
|
||||||
|
- Rate limiting (3 signatures per minute per IP)
|
||||||
|
- Duplicate signature prevention (one signature per ID card)
|
||||||
|
- MongoDB backend for data persistence
|
||||||
|
- Docker support for easy deployment
|
||||||
|
- Bilingual support (Dhivehi and English)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- .NET 9.0 SDK
|
||||||
|
- MongoDB instance
|
||||||
|
- Docker (optional, for containerized deployment)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### MongoDB Setup
|
||||||
|
|
||||||
|
1. Create a MongoDB database for the petition system
|
||||||
|
2. Create the following collections:
|
||||||
|
- `signatures` - stores petition signatures
|
||||||
|
- `petitions` - stores petition details
|
||||||
|
- `authors` - stores petition author information
|
||||||
|
|
||||||
|
### Application Configuration
|
||||||
|
|
||||||
|
Update `appsettings.json` with your MongoDB connection settings:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"MongoDbSettings": {
|
||||||
|
"ConnectionString": "mongodb://localhost:27017",
|
||||||
|
"DatabaseName": "petition_database"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rate Limiting Configuration
|
||||||
|
|
||||||
|
The API is configured with rate limiting to prevent spam. Default settings in `Program.cs`:
|
||||||
|
|
||||||
|
- **Limit**: 3 signatures per minute per IP address
|
||||||
|
- **Window**: Fixed 1-minute window
|
||||||
|
- **Queue**: Disabled (requests over limit receive HTTP 429)
|
||||||
|
|
||||||
|
To modify rate limits, edit `Program.cs`:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
limiterOptions.PermitLimit = 3; // Change this number
|
||||||
|
limiterOptions.Window = TimeSpan.FromMinutes(1); // Change time window
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
|
1. Clone the repository:
|
||||||
|
```bash
|
||||||
|
git clone <repository-url>
|
||||||
|
cd Submission.Api
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Restore dependencies:
|
||||||
|
```bash
|
||||||
|
dotnet restore
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Update `appsettings.json` with your MongoDB connection string
|
||||||
|
|
||||||
|
4. Run the application:
|
||||||
|
```bash
|
||||||
|
dotnet run --project Submission.Api
|
||||||
|
```
|
||||||
|
|
||||||
|
The API will be available at:
|
||||||
|
- HTTPS: `https://localhost:7xxx`
|
||||||
|
- HTTP: `http://localhost:5xxx`
|
||||||
|
|
||||||
|
### Docker Deployment
|
||||||
|
|
||||||
|
1. Build the Docker image:
|
||||||
|
```bash
|
||||||
|
docker build -t petition-api .
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run the container:
|
||||||
|
```bash
|
||||||
|
docker run -d -p 8080:8080 -p 8081:8081 \
|
||||||
|
-e MongoDbSettings__ConnectionString="mongodb://your-mongo-host:27017" \
|
||||||
|
-e MongoDbSettings__DatabaseName="petition_database" \
|
||||||
|
petition-api
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Sign a Petition
|
||||||
|
|
||||||
|
Signs a petition with user information and signature.
|
||||||
|
|
||||||
|
**Endpoint**: `POST /api/Sign`
|
||||||
|
|
||||||
|
**Rate Limit**: 3 requests per minute per IP
|
||||||
|
|
||||||
|
**Request Body**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "John Doe",
|
||||||
|
"idCard": "A123456",
|
||||||
|
"signature": "<svg>...</svg>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Field Validation**:
|
||||||
|
- `name`: Required, minimum 3 characters
|
||||||
|
- `idCard`: Required, 6-7 characters (typically National ID)
|
||||||
|
- `signature`: Required, SVG signature data
|
||||||
|
|
||||||
|
**Success Response** (200 OK):
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Error Responses**:
|
||||||
|
|
||||||
|
- **400 Bad Request** - Invalid request body or validation failed
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"errors": {
|
||||||
|
"name": ["The field Name must be a string with a minimum length of 3."],
|
||||||
|
"idCard": ["The field IdCard must be a string with a minimum length of 6 and a maximum length of 7."]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **429 Too Many Requests** - Rate limit exceeded
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 429,
|
||||||
|
"title": "Too Many Requests"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **500 Internal Server Error** - User already signed the petition
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "You already signed this petition"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Petition Details
|
||||||
|
|
||||||
|
Retrieves details of a specific petition including author information.
|
||||||
|
|
||||||
|
**Endpoint**: `GET /api/Sign/{petition_id}`
|
||||||
|
|
||||||
|
**URL Parameters**:
|
||||||
|
- `petition_id` (GUID) - The unique identifier of the petition
|
||||||
|
|
||||||
|
**Success Response** (200 OK):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"startDate": "2025-01-15",
|
||||||
|
"nameDhiv": "ޕެޓިޝަން ނަން",
|
||||||
|
"nameEng": "Petition Name",
|
||||||
|
"authorDetails": {
|
||||||
|
"name": "Author Name",
|
||||||
|
"nid": "A123456"
|
||||||
|
},
|
||||||
|
"petitionBodyDhiv": "ޕެޓިޝަން ތަފްސީލް...",
|
||||||
|
"petitionBodyEng": "Petition description...",
|
||||||
|
"signatureCount": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Error Response**:
|
||||||
|
|
||||||
|
- **404 Not Found** - Petition does not exist
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Data Models
|
||||||
|
|
||||||
|
### Signature (Widget)
|
||||||
|
```csharp
|
||||||
|
{
|
||||||
|
"id": "ObjectId",
|
||||||
|
"name": "string",
|
||||||
|
"idCard": "string",
|
||||||
|
"signature_SVG": "string",
|
||||||
|
"timestamp": "DateTime"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Petition Details
|
||||||
|
```csharp
|
||||||
|
{
|
||||||
|
"id": "Guid",
|
||||||
|
"startDate": "DateOnly",
|
||||||
|
"nameDhiv": "string",
|
||||||
|
"nameEng": "string",
|
||||||
|
"petitionBodyDhiv": "string",
|
||||||
|
"petitionBodyEng": "string",
|
||||||
|
"authorId": "Guid",
|
||||||
|
"signatureCount": "int"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Author
|
||||||
|
```csharp
|
||||||
|
{
|
||||||
|
"id": "Guid",
|
||||||
|
"name": "string",
|
||||||
|
"nid": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Features
|
||||||
|
|
||||||
|
### Rate Limiting
|
||||||
|
- Prevents spam by limiting signature submissions to 3 per minute per IP
|
||||||
|
- Uses ASP.NET Core built-in rate limiting middleware
|
||||||
|
- Returns HTTP 429 when limit is exceeded
|
||||||
|
|
||||||
|
### Duplicate Prevention
|
||||||
|
- Each ID card can only sign a petition once
|
||||||
|
- Checked before inserting into database
|
||||||
|
- Returns error message if duplicate detected
|
||||||
|
|
||||||
|
### Input Validation
|
||||||
|
- Name: Minimum 3 characters
|
||||||
|
- ID Card: Must be 6-7 characters (validates National ID format)
|
||||||
|
- Signature: Required field
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
```
|
||||||
|
Submission.Api/
|
||||||
|
├── Controllers/
|
||||||
|
│ └── SignController.cs # API endpoints
|
||||||
|
├── Dto/
|
||||||
|
│ ├── WidgetsDto.cs # Signature request DTO
|
||||||
|
│ ├── PetitionDetailsDto.cs # Petition response DTO
|
||||||
|
│ └── Author.cs # Author DTO
|
||||||
|
├── Models/
|
||||||
|
│ ├── Widget.cs # Signature database model
|
||||||
|
│ ├── PetitionDetail.cs # Petition database model
|
||||||
|
│ └── Author.cs # Author database model
|
||||||
|
├── Program.cs # Application configuration
|
||||||
|
├── Dockerfile # Docker configuration
|
||||||
|
└── appsettings.json # Application settings
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- ASP.NET Core 9.0
|
||||||
|
- MongoDB Driver (via Ashi.MongoInterface)
|
||||||
|
- Microsoft.AspNetCore.OpenApi 9.0.11
|
||||||
|
- Microsoft.AspNetCore.RateLimiting (built-in)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**MongoDB Connection Failed**
|
||||||
|
- Verify MongoDB is running
|
||||||
|
- Check connection string in `appsettings.json`
|
||||||
|
- Ensure network connectivity to MongoDB instance
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
When contributing to this project:
|
||||||
|
1. Follow existing code style and conventions
|
||||||
|
2. Test all endpoints thoroughly
|
||||||
|
3. Update documentation for any API changes
|
||||||
|
4. Ensure rate limiting is not disabled in production
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
if you use this you must mention that its powered by Mv Devs Union
|
||||||
|
|
||||||
|
also any forks must be open source
|
||||||
|
|
||||||
|
this must never be used for data collection and profiling people
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues or questions, please open an issue on the repository.
|
||||||
@@ -2,6 +2,13 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Submission.Api", "Submission.Api\Submission.Api.csproj", "{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Submission.Api", "Submission.Api\Submission.Api.csproj", "{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{204A1F7E-0832-4DEF-A64E-EB1A00F559A0}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
compose.yaml = compose.yaml
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ashi.MongoInterface", "external\OtherRepo\Ashi.MongoInterface\Ashi.MongoInterface.csproj", "{6F6B8940-4740-48D1-8790-8CD82A66676B}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -12,5 +19,12 @@ Global
|
|||||||
{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}.Release|Any CPU.Build.0 = Release|Any CPU
|
{F061EFE3-FFFE-4F0F-825A-9FF8B985912D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6F6B8940-4740-48D1-8790-8CD82A66676B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6F6B8940-4740-48D1-8790-8CD82A66676B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6F6B8940-4740-48D1-8790-8CD82A66676B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6F6B8940-4740-48D1-8790-8CD82A66676B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{6F6B8940-4740-48D1-8790-8CD82A66676B} = {204A1F7E-0832-4DEF-A64E-EB1A00F559A0}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
103
Submission.Api/Controllers/SignController.cs
Normal file
103
Submission.Api/Controllers/SignController.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
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 Submission.Api.Dto;
|
||||||
|
using Submission.Api.Models;
|
||||||
|
|
||||||
|
namespace Submission.Api.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class SignController : ControllerBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly IMongoRepository<Author> _authorRepository;
|
||||||
|
private readonly IMongoRepository<PetitionDetail> _detailRepository;
|
||||||
|
private readonly IMongoRepository<Widget> _signatureRepository;
|
||||||
|
private readonly IMemoryCache _cache;
|
||||||
|
|
||||||
|
public SignController(
|
||||||
|
IMongoRepository<Author> authorRepository,
|
||||||
|
IMongoRepository<PetitionDetail> detailRepository,
|
||||||
|
IMongoRepository<Widget> signatureRepository,
|
||||||
|
IMemoryCache cache)
|
||||||
|
{
|
||||||
|
_authorRepository = authorRepository;
|
||||||
|
_detailRepository = detailRepository;
|
||||||
|
_signatureRepository = signatureRepository;
|
||||||
|
_cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost(Name = "petition/{id}")]
|
||||||
|
[EnableRateLimiting("SignPetitionPolicy")]
|
||||||
|
public async Task<IActionResult> SignDisHoe([FromRoute]Guid petition_id,[FromBody] WidgetsDto body)
|
||||||
|
{
|
||||||
|
//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");
|
||||||
|
|
||||||
|
//add signature to the db
|
||||||
|
await _signatureRepository.InsertOneAsync(new Widget
|
||||||
|
{
|
||||||
|
IdCard = body.IdCard,
|
||||||
|
Name = body.Name,
|
||||||
|
Signature_SVG = body.Signature,
|
||||||
|
Timestamp = DateTime.Now
|
||||||
|
});
|
||||||
|
|
||||||
|
//update signature count
|
||||||
|
|
||||||
|
return Ok("your signature has been submitted");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet(Name = "petition/{id}")]
|
||||||
|
public async Task<IActionResult> GetDisHoe([FromRoute] Guid petition_id)
|
||||||
|
{
|
||||||
|
var cacheKey = $"petition_{petition_id}";
|
||||||
|
|
||||||
|
// Try to get from cache
|
||||||
|
if (_cache.TryGetValue(cacheKey, out PetitionDetailsDto cachedDto))
|
||||||
|
{
|
||||||
|
return Ok(cachedDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not in cache, fetch from database
|
||||||
|
var pet = await _detailRepository.FindByIdAsync(petition_id);
|
||||||
|
|
||||||
|
if (pet == null)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
var author = await _authorRepository.FindOneAsync(x => x.Id == pet.AuthorId);
|
||||||
|
|
||||||
|
var dto = new PetitionDetailsDto
|
||||||
|
{
|
||||||
|
Id = petition_id,
|
||||||
|
NameDhiv = pet.NameDhiv,
|
||||||
|
StartDate = pet.StartDate,
|
||||||
|
NameEng = pet.NameEng,
|
||||||
|
PetitionBodyDhiv = pet.PetitionBodyDhiv,
|
||||||
|
PetitionBodyEng = pet.PetitionBodyEng,
|
||||||
|
|
||||||
|
AuthorDetails = new AuthorsDto
|
||||||
|
{
|
||||||
|
Name = author.Name,
|
||||||
|
NID = author.NID,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store in cache with 5 minute expiration
|
||||||
|
var cacheOptions = new MemoryCacheEntryOptions()
|
||||||
|
.SetAbsoluteExpiration(TimeSpan.FromHours(12));
|
||||||
|
|
||||||
|
_cache.Set(cacheKey, dto, cacheOptions);
|
||||||
|
|
||||||
|
return Ok(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace Submission.Api.Dto;
|
namespace Submission.Api.Dto;
|
||||||
|
|
||||||
public class Author
|
public class AuthorsDto
|
||||||
{
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string NID { get; set; }
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,16 @@
|
|||||||
|
|
||||||
public class PetitionDetailsDto
|
public class PetitionDetailsDto
|
||||||
{
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public DateOnly StartDate { get; set; }
|
||||||
|
|
||||||
|
public string NameDhiv { get; set; }
|
||||||
|
public string NameEng { get; set; }
|
||||||
|
|
||||||
|
public AuthorsDto AuthorDetails { get; set; }
|
||||||
|
|
||||||
|
public string PetitionBodyDhiv { get; set; }
|
||||||
|
public string PetitionBodyEng { get; set; }
|
||||||
|
|
||||||
|
public int SignatureCount { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
namespace Submission.Api.Dto;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
public class WidgetDto
|
namespace Submission.Api.Dto;
|
||||||
|
|
||||||
|
public class WidgetsDto
|
||||||
{
|
{
|
||||||
|
[Required]
|
||||||
|
[MinLength(3)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[MinLength(6)]
|
||||||
|
[MaxLength(7)]
|
||||||
|
public string IdCard { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Signature { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
namespace Submission.Api.Models;
|
using Ashi.MongoInterface.Helper;
|
||||||
|
|
||||||
public class Author
|
namespace Submission.Api.Models;
|
||||||
|
|
||||||
|
[BsonCollection("author")]
|
||||||
|
public class Author : Document
|
||||||
{
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string NID { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,20 @@
|
|||||||
namespace Submission.Api.Models;
|
using System.Runtime.InteropServices;
|
||||||
|
using Ashi.MongoInterface.Helper;
|
||||||
|
|
||||||
public class PetitionDetail
|
namespace Submission.Api.Models;
|
||||||
|
|
||||||
|
[BsonCollection("petitionDetail")]
|
||||||
|
public class PetitionDetail : Document
|
||||||
{
|
{
|
||||||
|
public DateOnly StartDate { get; set; }
|
||||||
|
|
||||||
|
public string NameDhiv { get; set; }
|
||||||
|
public string NameEng { get; set; }
|
||||||
|
|
||||||
|
public Guid AuthorId { get; set; }
|
||||||
|
|
||||||
|
public string PetitionBodyDhiv { get; set; }
|
||||||
|
public string PetitionBodyEng { get; set; }
|
||||||
|
|
||||||
|
public int SignatureCount { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
namespace Submission.Api.Models;
|
using Ashi.MongoInterface.Helper;
|
||||||
|
|
||||||
public class Widget
|
namespace Submission.Api.Models;
|
||||||
|
|
||||||
|
[BsonCollection("signatures")]
|
||||||
|
public class Widget : Document
|
||||||
{
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string IdCard { get; set; }
|
||||||
|
public string Signature_SVG { get; set; }
|
||||||
|
public DateTime Timestamp { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,37 @@
|
|||||||
|
using System.Configuration;
|
||||||
|
using Ashi.MongoInterface;
|
||||||
|
using Ashi.MongoInterface.Service;
|
||||||
|
using Microsoft.AspNetCore.RateLimiting;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
|
builder.Services.Configure<MongoDbSettings>(builder.Configuration.GetSection("MongoDbSettings"));
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IMongoDbSettings>(serviceProvider =>
|
||||||
|
serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value);
|
||||||
|
|
||||||
|
builder.Services.AddScoped((typeof(IMongoRepository<>)), typeof(MongoRepository<>));
|
||||||
|
|
||||||
|
builder.Services.AddMemoryCache();
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||||
builder.Services.AddOpenApi();
|
builder.Services.AddOpenApi();
|
||||||
|
|
||||||
|
// Add rate limiting
|
||||||
|
builder.Services.AddRateLimiter(options =>
|
||||||
|
{
|
||||||
|
options.AddFixedWindowLimiter("SignPetitionPolicy", limiterOptions =>
|
||||||
|
{
|
||||||
|
limiterOptions.PermitLimit = 3;
|
||||||
|
limiterOptions.Window = TimeSpan.FromMinutes(1);
|
||||||
|
limiterOptions.QueueProcessingOrder = System.Threading.RateLimiting.QueueProcessingOrder.OldestFirst;
|
||||||
|
limiterOptions.QueueLimit = 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
@@ -16,6 +42,8 @@ if (app.Environment.IsDevelopment())
|
|||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseRateLimiter();
|
||||||
|
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|||||||
@@ -4,10 +4,22 @@
|
|||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.11"/>
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.11"/>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="..\.dockerignore">
|
||||||
|
<Link>.dockerignore</Link>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\external\OtherRepo\Ashi.MongoInterface\Ashi.MongoInterface.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
6
Submission.Api/Submission.Api.csproj.user
Normal file
6
Submission.Api/Submission.Api.csproj.user
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ActiveDebugProfile>https</ActiveDebugProfile>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
7
compose.yaml
Normal file
7
compose.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
services:
|
||||||
|
submission.api:
|
||||||
|
image: submission.api
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Submission.Api/Dockerfile
|
||||||
|
|
||||||
Reference in New Issue
Block a user