Skip to content
32 changes: 32 additions & 0 deletions Attributes/AllowedFileExtensionsAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.ComponentModel.DataAnnotations;

namespace AonFreelancing.Attributes
{
public class AllowedFileExtensionsAttribute : ValidationAttribute
{
private readonly string[] _extensions;
private string _extension;
public AllowedFileExtensionsAttribute(string[] extensions)
{
_extensions = extensions;
}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{

if (value is not IFormFile file)
return ValidationResult.Success;

_extension = Path.GetExtension(file.FileName);
if (Utilities.FileCheckUtil.IsValidFileExtensionAndSignature(file.FileName, file.OpenReadStream(), _extensions))
return ValidationResult.Success;

return new ValidationResult(GetErrorMessage());
}

public string GetErrorMessage()
{
return $"either file extension ({_extension}) is not allowed or the file has been corrupted";
}
}
}
27 changes: 27 additions & 0 deletions Attributes/MaxFileSizeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;

namespace AonFreelancing.Attributes
{
public class MaxFileSizeAttribute : ValidationAttribute
{
private readonly int _maxFileSize;
public MaxFileSizeAttribute(int maxFileSize)
{
_maxFileSize = maxFileSize;
}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var file = value as IFormFile;
if (file != null && file.Length > _maxFileSize)
return new ValidationResult(GetErrorMessage());

return ValidationResult.Success;
}

public string GetErrorMessage()
{
return $"Maximum allowed file size is {_maxFileSize} bytes.";
}
}
}
36 changes: 27 additions & 9 deletions Contexts/MainAppContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AonFreelancing.Models;
using AonFreelancing.Utilities;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System.Reflection.Emit;
Expand All @@ -20,7 +21,8 @@ public class MainAppContext(DbContextOptions<MainAppContext> contextOptions)
public DbSet<TempUser> TempUsers { get; set; }
public DbSet<Bid> Bids { get; set; }
public DbSet<TaskEntity> Tasks { get; set; }

public DbSet<Skill> Skills { get; set; }
public DbSet<ProjectLike> ProjectLikes { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{

Expand All @@ -33,21 +35,24 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity<Freelancer>().ToTable("Freelancers");
builder.Entity<Client>().ToTable("Clients");
builder.Entity<SystemUser>().ToTable("SystemUsers");

builder.Entity<OTP>().ToTable("otps", o => o.HasCheckConstraint("CK_CODE","LEN([Code]) = 6"));

builder.Entity<Project>().ToTable("Projects", tb => tb.HasCheckConstraint("CK_PRICE_TYPE", "[PriceType] IN ('Fixed', 'PerHour')"));
builder.Entity<Project>().ToTable("Projects", tb => tb.HasCheckConstraint("CK_QUALIFICATION_NAME", "[QualificationName] IN ('uiux', 'frontend', 'mobile', 'backend', 'fullstack')"));
builder.Entity<Project>().ToTable("Projects", tb => tb.HasCheckConstraint("CK_STATUS", "[Status] IN ('Available', 'Closed')"))
.Property(p=>p.Status).HasDefaultValue("Available");

builder.Entity<TaskEntity>().ToTable("Tasks", t => t.HasCheckConstraint("CK_TASK_STATUS", $"[Status] IN ('{Constants.TASK_STATUS_DONE}', '{Constants.TASK_STATUS_IN_REVIEW}', '{Constants.TASK_STATUS_IN_PROGRESS}', '{Constants.TASK_STATUS_TO_DO}')"))
.Property(t => t.Status).HasDefaultValue(Constants.TASK_STATUS_TO_DO);

builder.Entity<ProjectLike>().HasIndex(pl => new { pl.ProjectId, pl.UserId }).IsUnique();
//set up relationships
builder.Entity<TempUser>().HasOne<OTP>()
.WithOne()
.HasForeignKey<OTP>()
.HasPrincipalKey<TempUser>(nameof(TempUser.PhoneNumber));

builder.Entity<Project>().ToTable("Projects", tb => tb.HasCheckConstraint("CK_PRICE_TYPE", "[PriceType] IN ('Fixed', 'PerHour')"));

builder.Entity<Project>()
.ToTable("Projects", tb => tb.HasCheckConstraint("CK_QUALIFICATION_NAME", "[QualificationName] IN ('uiux', 'frontend', 'mobile', 'backend', 'fullstack')"));
builder.Entity<Project>().ToTable("Projects", tb => tb.HasCheckConstraint("CK_STATUS", "[Status] IN ('Available', 'Closed')"))
.Property(p=>p.Status).HasDefaultValue("Available");

builder.Entity<Bid>()
.HasOne(b => b.Project)
.WithMany(p => p.Bids)
Expand All @@ -60,8 +65,21 @@ protected override void OnModelCreating(ModelBuilder builder)
.HasForeignKey(b => b.FreelancerId)
.OnDelete(DeleteBehavior.NoAction);

builder.Entity<Skill>().HasOne<Freelancer>()
.WithMany(f=>f.Skills)
.HasForeignKey(s=>s.UserId)
.HasPrincipalKey(f=>f.Id);

builder.Entity<ProjectLike>().HasOne<User>()
.WithMany()
.HasForeignKey(pl => pl.UserId)
.HasPrincipalKey(u => u.Id);
builder.Entity<ProjectLike>().HasOne<Project>()
.WithMany(p => p.ProjectLikes)
.HasForeignKey(pl => pl.ProjectId)
.OnDelete(DeleteBehavior.NoAction)
.HasPrincipalKey(p => p.Id);

builder.Entity<TaskEntity>().ToTable("Tasks");

base.OnModelCreating(builder);
}
Expand Down
2 changes: 1 addition & 1 deletion Controllers/BaseController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using AonFreelancing.Models;
using AonFreelancing.Models.Responses;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
Expand Down
4 changes: 3 additions & 1 deletion Controllers/Mobile/v1/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ AuthService authService
[HttpPost("sendVerificationCode")]
public async Task<IActionResult> SendVerificationCodeAsync([FromBody] PhoneNumberReq phoneNumberReq)
{
if (!ModelState.IsValid)
return CustomBadRequest();
var IsExist = await _authService.IsUserExistsInTempAsync(phoneNumberReq);
if (IsExist)
{
Expand Down Expand Up @@ -110,7 +112,7 @@ public async Task<IActionResult> CompleteRegistrationAsync([FromBody] RegisterRe
UserName = registerReq.Username,
PhoneNumber = tempUser.PhoneNumber,
PhoneNumberConfirmed = tempUser.PhoneNumberConfirmed,
Skills = registerReq.Skills ?? string.Empty,
//Skills = registerReq.Skills ?? string.Empty,
},
Constants.USER_TYPE_CLIENT => new Client()
{
Expand Down
Loading