add project layers
parent
f658d4531e
commit
7374d47769
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"mapster.tool": {
|
||||||
|
"version": "8.4.0",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-mapster"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Common
|
||||||
|
{
|
||||||
|
public class CommonConfig
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class AssertExtensions
|
||||||
|
{
|
||||||
|
public static void NotNull<T>(T obj, string name, string message = null)
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
if (obj is null)
|
||||||
|
throw new ArgumentNullException($"{name} : {typeof(T)}", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void NotNull<T>(T? obj, string name, string message = null)
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
if (!obj.HasValue)
|
||||||
|
throw new ArgumentNullException($"{name} : {typeof(T)}", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void NotEmpty<T>(T obj, string name, string message = null, T defaultValue = null)
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
if (obj == defaultValue
|
||||||
|
|| obj is string str && string.IsNullOrWhiteSpace(str)
|
||||||
|
|| obj is IEnumerable list && !list.Cast<object>().Any())
|
||||||
|
throw new ArgumentException("Argument is empty : " + message, $"{name} : {typeof(T)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Common.Extensions;
|
||||||
|
|
||||||
|
public static class BoolExtensions
|
||||||
|
{
|
||||||
|
public static string ToPersianString(this bool value)
|
||||||
|
{
|
||||||
|
return value ? "بله" : "خیر";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
using HamyanEdalat.Common.Models.Entity;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class ClassDisplayExtensions
|
||||||
|
{
|
||||||
|
public static string GetDisplayAttributeName<T>()
|
||||||
|
{
|
||||||
|
var attrs =
|
||||||
|
Attribute.GetCustomAttributes(typeof(T));
|
||||||
|
|
||||||
|
foreach (var attr in attrs)
|
||||||
|
{
|
||||||
|
var displayAttribute = attr as PageClassDisplay;
|
||||||
|
if (displayAttribute == null)
|
||||||
|
continue;
|
||||||
|
return displayAttribute.GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDisplayAttributeDescription<T>()
|
||||||
|
{
|
||||||
|
var attrs =
|
||||||
|
Attribute.GetCustomAttributes(typeof(T));
|
||||||
|
|
||||||
|
foreach (var attr in attrs)
|
||||||
|
{
|
||||||
|
var displayAttribute = attr as PageClassDisplay;
|
||||||
|
if (displayAttribute == null)
|
||||||
|
continue;
|
||||||
|
return displayAttribute.GetDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class DateTimeExtensions
|
||||||
|
{
|
||||||
|
public static string GetPersianDayOfWeek(this DayOfWeek dayOfWeek)
|
||||||
|
{
|
||||||
|
switch (dayOfWeek)
|
||||||
|
{
|
||||||
|
case DayOfWeek.Friday:
|
||||||
|
return "جمعه";
|
||||||
|
case DayOfWeek.Monday:
|
||||||
|
return "دوشنبه";
|
||||||
|
case DayOfWeek.Saturday:
|
||||||
|
return "شنبه";
|
||||||
|
case DayOfWeek.Sunday:
|
||||||
|
return "یکشنبه";
|
||||||
|
case DayOfWeek.Thursday:
|
||||||
|
return "پنج شنبه";
|
||||||
|
case DayOfWeek.Tuesday:
|
||||||
|
return "سه شنبه";
|
||||||
|
case DayOfWeek.Wednesday:
|
||||||
|
return "چهارشنبه";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
|
||||||
|
{
|
||||||
|
// Unix timestamp is seconds past epoch
|
||||||
|
var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||||
|
dtDateTime = dtDateTime.AddMilliseconds(unixTimeStamp).ToLocalTime();
|
||||||
|
return dtDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long DateTimeToUnixTimeStamp(DateTime dateTime)
|
||||||
|
{
|
||||||
|
return ((DateTimeOffset)dateTime).ToUnixTimeMilliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int DifferenceByDay(DateTime originDateTime, DateTime destDateTime)
|
||||||
|
{
|
||||||
|
return (int)(destDateTime - originDateTime).TotalDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int DifferenceByHoure(DateTime originDateTime, DateTime destDateTime)
|
||||||
|
{
|
||||||
|
return (int)(destDateTime - originDateTime).TotalHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeSpan Difference(DateTime originDateTime, DateTime destDateTime)
|
||||||
|
{
|
||||||
|
var durateion = (destDateTime - originDateTime).Duration();
|
||||||
|
return durateion;
|
||||||
|
}
|
||||||
|
public static PersianDateTime ToPersianDateTime(this DateTime dateTime)
|
||||||
|
=> new PersianDateTime(dateTime);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public enum DisplayProperty
|
||||||
|
{
|
||||||
|
Description,
|
||||||
|
GroupName,
|
||||||
|
Name,
|
||||||
|
Prompt,
|
||||||
|
ShortName,
|
||||||
|
Order
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EnumExtensions
|
||||||
|
{
|
||||||
|
public static IEnumerable<T> GetEnumValues<T>(this T input) where T : struct
|
||||||
|
{
|
||||||
|
if (!typeof(T).IsEnum)
|
||||||
|
throw new NotSupportedException();
|
||||||
|
|
||||||
|
return Enum.GetValues(input.GetType()).Cast<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> GetEnumFlags<T>(this T input) where T : struct
|
||||||
|
{
|
||||||
|
if (!typeof(T).IsEnum)
|
||||||
|
throw new NotSupportedException();
|
||||||
|
|
||||||
|
foreach (var value in Enum.GetValues(input.GetType()))
|
||||||
|
if ((input as Enum).HasFlag(value as Enum))
|
||||||
|
yield return (T)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToDisplay(this Enum value, DisplayProperty property = DisplayProperty.Name)
|
||||||
|
{
|
||||||
|
AssertExtensions.NotNull(value, nameof(value));
|
||||||
|
|
||||||
|
var attribute = value.GetType().GetField(value.ToString())
|
||||||
|
.GetCustomAttributes<DisplayAttribute>(false).FirstOrDefault();
|
||||||
|
|
||||||
|
if (attribute == null)
|
||||||
|
return value.ToString();
|
||||||
|
|
||||||
|
var propValue = attribute.GetType().GetProperty(property.ToString()).GetValue(attribute, null);
|
||||||
|
return propValue.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<int, string> ToDictionary(this Enum value)
|
||||||
|
{
|
||||||
|
return Enum.GetValues(value.GetType()).Cast<Enum>().ToDictionary(p => Convert.ToInt32(p), q => ToDisplay(q));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class NewtonJsonExtensions
|
||||||
|
{
|
||||||
|
public static JsonSerializerSettings CamelCaseSerialize =>
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
ContractResolver = new DefaultContractResolver
|
||||||
|
{
|
||||||
|
NamingStrategy = new CamelCaseNamingStrategy()
|
||||||
|
},
|
||||||
|
Formatting = Formatting.Indented
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Extensions;
|
||||||
|
public static class PhoneNumberExtensions
|
||||||
|
{
|
||||||
|
public static bool CheckPhoneNumber(string phoneNumber)
|
||||||
|
{
|
||||||
|
var regex = new Regex(@"(^(989|0989|\+989|09|9)[0-9]{9}$)");
|
||||||
|
return regex.IsMatch(phoneNumber);
|
||||||
|
}
|
||||||
|
public static string GetVerifyFromPhoneNumber(string phoneNumber)
|
||||||
|
{
|
||||||
|
var dateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute / 5, 0);
|
||||||
|
var timeStamp = ((DateTimeOffset)dateTime).ToUnixTimeMilliseconds() / 10000;
|
||||||
|
|
||||||
|
int FTD = int.Parse(string.Format("{0}{1}{2}",
|
||||||
|
GetSumDigit(int.Parse(string.Format("{0}{1}{2}", phoneNumber[5], phoneNumber[7], phoneNumber[9]))) % 10,
|
||||||
|
GetSumDigit(int.Parse(string.Format("{0}{1}{2}", phoneNumber[4], phoneNumber[6], phoneNumber[8]))) % 10,
|
||||||
|
GetSumDigit(int.Parse(string.Format("{0}{1}{2}", phoneNumber[10], phoneNumber[9], phoneNumber[8]))) % 10));
|
||||||
|
int ATD = GetSumDigit(((int)timeStamp % 1000) + FTD);
|
||||||
|
timeStamp = (int)timeStamp / 1000;
|
||||||
|
int BTD = GetSumDigit(((int)timeStamp % 1000) + ATD);
|
||||||
|
timeStamp = (int)timeStamp / 1000;
|
||||||
|
int CTD = GetSumDigit(((int)timeStamp % 1000) + ATD);
|
||||||
|
FTD = GetSumDigit(FTD);
|
||||||
|
if (ATD % 2 == 0)
|
||||||
|
return string.Format("{0}{1}{2}{3}", GetSumDigit(ATD) % 10, GetSumDigit(BTD) % 10, GetSumDigit(CTD) % 10, GetSumDigit(FTD) % 10);
|
||||||
|
else
|
||||||
|
return string.Format("{0}{1}{2}{3}", ATD % 10, BTD % 10, CTD % 10, FTD % 10);
|
||||||
|
}
|
||||||
|
private static int GetSumDigit(int number)
|
||||||
|
{
|
||||||
|
string sNumber = number.ToString();
|
||||||
|
int total = 0;
|
||||||
|
foreach (var s in sNumber)
|
||||||
|
total += int.Parse(s.ToString());
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class PropertyExtensions
|
||||||
|
{
|
||||||
|
public static string GetPropertyDisplayName(this MemberInfo propertyExpression)
|
||||||
|
{
|
||||||
|
var memberInfo = propertyExpression;
|
||||||
|
var attr = memberInfo.GetCustomAttributes<DisplayAttribute>().FirstOrDefault();
|
||||||
|
if (attr == null) return memberInfo.Name;
|
||||||
|
|
||||||
|
return attr.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class RandomExtensions
|
||||||
|
{
|
||||||
|
public static T RandomItem<T>(List<T> originList)
|
||||||
|
{
|
||||||
|
var random = new Random(DateTime.Now.Millisecond);
|
||||||
|
var rand = random.Next(0, originList.Count - 1);
|
||||||
|
return originList[rand];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
public static string ToPriceWhitPriceType(this long price, string priceType)
|
||||||
|
{
|
||||||
|
return price.ToString("N0") + " " + priceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToPriceWhitPriceType(this decimal price, string priceType)
|
||||||
|
{
|
||||||
|
return price.ToString("N0") + " " + priceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToPriceWhitPriceType(this double price, string priceType)
|
||||||
|
{
|
||||||
|
return price.ToString("N0") + " " + priceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasValue(this string value, bool ignoreWhiteSpace = true)
|
||||||
|
{
|
||||||
|
return ignoreWhiteSpace ? !string.IsNullOrWhiteSpace(value) : !string.IsNullOrEmpty(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ToInt(this string value)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static decimal ToDecimal(this string value)
|
||||||
|
{
|
||||||
|
return Convert.ToDecimal(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToNumeric(this int value)
|
||||||
|
{
|
||||||
|
return value.ToString("N0"); //"123,456"
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToNumeric(this decimal value)
|
||||||
|
{
|
||||||
|
return value.ToString("N0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToCurrency(this int value)
|
||||||
|
{
|
||||||
|
//fa-IR => current culture currency symbol => ریال
|
||||||
|
//123456 => "123,123ریال"
|
||||||
|
return value.ToString("C0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToCurrency(this decimal value)
|
||||||
|
{
|
||||||
|
return value.ToString("C0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string En2Fa(this string str)
|
||||||
|
{
|
||||||
|
return str.Replace("0", "۰")
|
||||||
|
.Replace("1", "۱")
|
||||||
|
.Replace("2", "۲")
|
||||||
|
.Replace("3", "۳")
|
||||||
|
.Replace("4", "۴")
|
||||||
|
.Replace("5", "۵")
|
||||||
|
.Replace("6", "۶")
|
||||||
|
.Replace("7", "۷")
|
||||||
|
.Replace("8", "۸")
|
||||||
|
.Replace("9", "۹");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Fa2En(this string str)
|
||||||
|
{
|
||||||
|
return str.Replace("۰", "0")
|
||||||
|
.Replace("۱", "1")
|
||||||
|
.Replace("۲", "2")
|
||||||
|
.Replace("۳", "3")
|
||||||
|
.Replace("۴", "4")
|
||||||
|
.Replace("۵", "5")
|
||||||
|
.Replace("۶", "6")
|
||||||
|
.Replace("۷", "7")
|
||||||
|
.Replace("۸", "8")
|
||||||
|
.Replace("۹", "9")
|
||||||
|
//iphone numeric
|
||||||
|
.Replace("٠", "0")
|
||||||
|
.Replace("١", "1")
|
||||||
|
.Replace("٢", "2")
|
||||||
|
.Replace("٣", "3")
|
||||||
|
.Replace("٤", "4")
|
||||||
|
.Replace("٥", "5")
|
||||||
|
.Replace("٦", "6")
|
||||||
|
.Replace("٧", "7")
|
||||||
|
.Replace("٨", "8")
|
||||||
|
.Replace("٩", "9");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FixPersianChars(this string str)
|
||||||
|
{
|
||||||
|
return str.Replace("ﮎ", "ک")
|
||||||
|
.Replace("ﮏ", "ک")
|
||||||
|
.Replace("ﮐ", "ک")
|
||||||
|
.Replace("ﮑ", "ک")
|
||||||
|
.Replace("ك", "ک")
|
||||||
|
.Replace("ي", "ی")
|
||||||
|
.Replace(" ", " ")
|
||||||
|
.Replace("", " ")
|
||||||
|
.Replace("ھ", "ه"); //.Replace("ئ", "ی");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string CleanString(this string str)
|
||||||
|
{
|
||||||
|
return str.Trim().FixPersianChars().Fa2En().NullIfEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string NullIfEmpty(this string str)
|
||||||
|
{
|
||||||
|
return str?.Length == 0 ? null : str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetId(int length = 8)
|
||||||
|
{
|
||||||
|
return Guid.NewGuid().ToString("N").Substring(0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ConvertTo3Digit(this string str)
|
||||||
|
{
|
||||||
|
str = string.Concat(str.Split(','));
|
||||||
|
var array = str.ToCharArray();
|
||||||
|
Array.Reverse(array);
|
||||||
|
str = new string(array);
|
||||||
|
|
||||||
|
var newStr = "";
|
||||||
|
for (var i = 0; i < str.Length; i++)
|
||||||
|
{
|
||||||
|
newStr += str[i];
|
||||||
|
if ((i + 1) % 3 == 0)
|
||||||
|
newStr += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
var newarray = newStr.ToCharArray();
|
||||||
|
Array.Reverse(newarray);
|
||||||
|
newStr = new string(newarray);
|
||||||
|
if (newStr.Length > 0 && newStr[0] == ',')
|
||||||
|
newStr = newStr.Substring(1);
|
||||||
|
|
||||||
|
return newStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ConvertToOrginal(this string str)
|
||||||
|
{
|
||||||
|
return string.Concat(str.Split(','));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string CheckPhoneNumber(string phoneNumber)
|
||||||
|
{
|
||||||
|
if (phoneNumber.Substring(0, 3).Contains("+98"))
|
||||||
|
phoneNumber = phoneNumber.Replace("+98", "0");
|
||||||
|
else if (phoneNumber.Substring(0, 2).Contains("98"))
|
||||||
|
phoneNumber = string.Concat("0", phoneNumber.Substring(2));
|
||||||
|
else if (phoneNumber[0] != '0')
|
||||||
|
phoneNumber = string.Concat("0", phoneNumber);
|
||||||
|
|
||||||
|
return phoneNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
namespace HamyanEdalat.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class ValidationExtensions
|
||||||
|
{
|
||||||
|
public static bool CheckDateIs(this DateTime dateTime, DateTime From, DateTime To)
|
||||||
|
{
|
||||||
|
if (dateTime.Date > To.Date && dateTime.Date < From.Date)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CheckDateFromToNow(this DateTime dateTime, int fromDays = 5)
|
||||||
|
{
|
||||||
|
var From = DateTime.Now.AddDays(-fromDays);
|
||||||
|
var To = DateTime.Now;
|
||||||
|
if (dateTime.Date > To.Date && dateTime.Date < From.Date)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<!--<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MD.PersianDateTime.Standard" Version="2.5.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
|
||||||
|
</ItemGroup>-->
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<LangVersion>10</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MD.PersianDateTime.Standard" Version="2.5.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="MD.PersianDateTime.Standard" />
|
||||||
|
<Using Include="Newtonsoft.Json" />
|
||||||
|
<Using Include="Newtonsoft.Json.Serialization" />
|
||||||
|
<Using Include="System.ComponentModel.DataAnnotations" />
|
||||||
|
<Using Include="System.ComponentModel.DataAnnotations.Schema" />
|
||||||
|
<Using Include="System.IdentityModel.Tokens.Jwt" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,76 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Api
|
||||||
|
{
|
||||||
|
public class AccessToken
|
||||||
|
{
|
||||||
|
public AccessToken()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessToken(JwtSecurityToken securityToken)
|
||||||
|
{
|
||||||
|
access_token = new JwtSecurityTokenHandler().WriteToken(securityToken);
|
||||||
|
token_type = "Bearer";
|
||||||
|
expire_in_datetime = securityToken.ValidTo;
|
||||||
|
expires_in = (int)(securityToken.ValidTo - DateTime.UtcNow).TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string access_token { get; set; } = string.Empty;
|
||||||
|
public string refresh_token { get; set; } = string.Empty;
|
||||||
|
public string token_type { get; set; } = string.Empty;
|
||||||
|
public int expires_in { get; set; }
|
||||||
|
public string token_id { get; set; } = string.Empty;
|
||||||
|
public DateTime expire_in_datetime { get; set; }
|
||||||
|
public string BearerToken => $"Bearer {access_token}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AccessToken<TUser>
|
||||||
|
{
|
||||||
|
public AccessToken()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessToken(JwtSecurityToken securityToken)
|
||||||
|
{
|
||||||
|
access_token = new JwtSecurityTokenHandler().WriteToken(securityToken);
|
||||||
|
token_type = "Bearer";
|
||||||
|
expires_in = (int)(securityToken.ValidTo - DateTime.UtcNow).TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string access_token { get; set; } = string.Empty;
|
||||||
|
public string ig_access_token { get; set; } = string.Empty;
|
||||||
|
public string refresh_token { get; set; } = string.Empty;
|
||||||
|
public string token_type { get; set; } = string.Empty;
|
||||||
|
public int expires_in { get; set; }
|
||||||
|
|
||||||
|
public TUser User { get; set; }
|
||||||
|
public string BearerToken => $"Bearer {access_token}";
|
||||||
|
public List<string> Permissions { get; set; }
|
||||||
|
public string RoleName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class AccessToken<TUser,TRole>
|
||||||
|
{
|
||||||
|
public AccessToken()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessToken(JwtSecurityToken securityToken)
|
||||||
|
{
|
||||||
|
access_token = new JwtSecurityTokenHandler().WriteToken(securityToken);
|
||||||
|
token_type = "Bearer";
|
||||||
|
expires_in = (int)(securityToken.ValidTo - DateTime.UtcNow).TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string access_token { get; set; } = string.Empty;
|
||||||
|
public string ig_access_token { get; set; } = string.Empty;
|
||||||
|
public string refresh_token { get; set; } = string.Empty;
|
||||||
|
public string token_type { get; set; } = string.Empty;
|
||||||
|
public int expires_in { get; set; }
|
||||||
|
|
||||||
|
public TUser User { get; set; }
|
||||||
|
public string BearerToken => $"Bearer {access_token}";
|
||||||
|
public List<string> Permissions { get; set; }
|
||||||
|
public List<TRole> Roles { get; set; } = new();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Models.Api
|
||||||
|
{
|
||||||
|
public enum ApiResultStatusCode
|
||||||
|
{
|
||||||
|
[Display(Name = "عملیات با موفقیت انجام شد")]
|
||||||
|
Success = HttpStatusCode.OK,
|
||||||
|
|
||||||
|
[Display(Name = "خطایی در سرور رخ داده است")]
|
||||||
|
ServerError = HttpStatusCode.InternalServerError,
|
||||||
|
|
||||||
|
[Display(Name = "پارامتر های ارسالی معتبر نیستند")]
|
||||||
|
BadRequest = HttpStatusCode.BadRequest,
|
||||||
|
|
||||||
|
[Display(Name = "یافت نشد")]
|
||||||
|
NotFound = HttpStatusCode.NotFound,
|
||||||
|
|
||||||
|
[Display(Name = "لیست خالی است")]
|
||||||
|
ListEmpty = 4,
|
||||||
|
|
||||||
|
[Display(Name = "خطایی در پردازش رخ داد")]
|
||||||
|
LogicError = 5,
|
||||||
|
|
||||||
|
[Display(Name = "موجودی کیف پول کافی نمی باشد")]
|
||||||
|
WalletBalanceNoEnough = 6,
|
||||||
|
|
||||||
|
[Display(Name = "خطای احراز هویت")]
|
||||||
|
UnAuthorized = HttpStatusCode.Unauthorized,
|
||||||
|
|
||||||
|
[Display(Name = "سرور خاموش شده است لطفا منتظر بمانید")]
|
||||||
|
ServerDown = HttpStatusCode.ServiceUnavailable,
|
||||||
|
|
||||||
|
[Display(Name = "در ارسال پیامک مورد نظر مشکلی رخ داده است")]
|
||||||
|
SendSmsError = 7,
|
||||||
|
|
||||||
|
|
||||||
|
[Display(Name = "در ارسال درخواست به سرورهای دیگر مشکلی رخ داده است")]
|
||||||
|
RefitError = 8
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Api
|
||||||
|
{
|
||||||
|
public class AppSettings
|
||||||
|
{
|
||||||
|
public bool Seeded { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Api
|
||||||
|
{
|
||||||
|
public enum FileUploadType
|
||||||
|
{
|
||||||
|
[Display(Name = "Images")]
|
||||||
|
Image,
|
||||||
|
[Display(Name = "Handouts")]
|
||||||
|
Handout,
|
||||||
|
[Display(Name = "Videos")]
|
||||||
|
Video,
|
||||||
|
}
|
||||||
|
public class FileUploadRequest
|
||||||
|
{
|
||||||
|
public string StringBaseFile { get; set; }
|
||||||
|
public string FileName { get; set; }
|
||||||
|
public string ContentType { get; set; }
|
||||||
|
public FileUploadType FileUploadType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Api;
|
||||||
|
|
||||||
|
public class FileUploadResponse
|
||||||
|
{
|
||||||
|
public string FileUrl { get; set; }
|
||||||
|
public string FileLocation { get; set; }
|
||||||
|
public string FileName { get; set; }
|
||||||
|
public bool IsOriginal { get; set; } = true;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Api
|
||||||
|
{
|
||||||
|
public class HealthCheck
|
||||||
|
{
|
||||||
|
public bool Health { get; set; }
|
||||||
|
public string Version { get; set; } = string.Empty;
|
||||||
|
public string TotalMemory { get; set; } = string.Empty;
|
||||||
|
public string StartAt { get; set; } = string.Empty;
|
||||||
|
public string StartAtPersian { get; set; } = string.Empty;
|
||||||
|
public string MachineName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Api
|
||||||
|
{
|
||||||
|
public class ResponseFile
|
||||||
|
{
|
||||||
|
public string Url { get; set; }
|
||||||
|
public string Location { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Api
|
||||||
|
{
|
||||||
|
public class TokenRequest
|
||||||
|
{
|
||||||
|
public string grant_type { get; set; }
|
||||||
|
public string username { get; set; }
|
||||||
|
public string password { get; set; }
|
||||||
|
public string refresh_token { get; set; }
|
||||||
|
public string scope { get; set; }
|
||||||
|
|
||||||
|
public string client_id { get; set; }
|
||||||
|
public string client_secret { get; set; }
|
||||||
|
|
||||||
|
public string login_hash { get; set; }
|
||||||
|
public string device_id { get; set; }
|
||||||
|
public string license_id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Entity;
|
||||||
|
public abstract class ApiEntity : IApiEntity , IEquatable<ApiEntity>
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "تاریخ حذف")]
|
||||||
|
public DateTime RemovedAt { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "تاریخ ساخت")]
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "ساخته شده توسط")]
|
||||||
|
public string CreatedBy { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Display(Name = "حذف شده")]
|
||||||
|
public bool IsRemoved { get; set; }
|
||||||
|
[Display(Name = "حذف شده توسط")]
|
||||||
|
public string RemovedBy { get; set; } = string.Empty;
|
||||||
|
[Display(Name = "اخرین تغییر در")]
|
||||||
|
public DateTime ModifiedAt { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "اخرین تغییر توسط")]
|
||||||
|
public string ModifiedBy { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public bool Equals(ApiEntity other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other)) return false;
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
return Id.Equals(other.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != this.GetType()) return false;
|
||||||
|
return Equals((ApiEntity)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Id.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Entity
|
||||||
|
{
|
||||||
|
public interface IApiEntity
|
||||||
|
{
|
||||||
|
string CreatedBy { get; }
|
||||||
|
string ModifiedBy { get; }
|
||||||
|
string RemovedBy { get; }
|
||||||
|
bool IsRemoved { get; }
|
||||||
|
DateTime CreatedAt { get; }
|
||||||
|
DateTime RemovedAt { get; }
|
||||||
|
DateTime ModifiedAt { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Entity
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class PageClassDisplay : Attribute
|
||||||
|
{
|
||||||
|
private readonly string _description;
|
||||||
|
private readonly string _name;
|
||||||
|
|
||||||
|
public PageClassDisplay(string name, string description)
|
||||||
|
{
|
||||||
|
_name = name;
|
||||||
|
_description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription()
|
||||||
|
{
|
||||||
|
return _description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using HamyanEdalat.Common.Models.Api;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Models.Exception
|
||||||
|
{
|
||||||
|
[Serializable()]
|
||||||
|
public class AppException : System.Exception
|
||||||
|
{
|
||||||
|
protected AppException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||||
|
|
||||||
|
public ApiResultStatusCode StatusCode { get; set; }
|
||||||
|
public AppException()
|
||||||
|
{
|
||||||
|
StatusCode = ApiResultStatusCode.ServerError;
|
||||||
|
}
|
||||||
|
public AppException(string message) : base(message)
|
||||||
|
{
|
||||||
|
StatusCode = ApiResultStatusCode.ServerError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppException(string message, ApiResultStatusCode statusCode) : base(message)
|
||||||
|
{
|
||||||
|
StatusCode = statusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
using System.Net;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using HamyanEdalat.Common.Models.Api;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Models.Exception
|
||||||
|
{
|
||||||
|
[Serializable()]
|
||||||
|
public class BaseApiException : System.Exception
|
||||||
|
{
|
||||||
|
protected BaseApiException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||||
|
public BaseApiException()
|
||||||
|
: this(ApiResultStatusCode.ServerError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode)
|
||||||
|
: this(statusCode, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(string message)
|
||||||
|
: this(ApiResultStatusCode.ServerError, message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message)
|
||||||
|
: this(statusCode, message, HttpStatusCode.InternalServerError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(string message, object additionalData) : this(ApiResultStatusCode.ServerError, message, additionalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, object additionalData) : this(statusCode, null, additionalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message, object additionalData)
|
||||||
|
: this(statusCode, message, HttpStatusCode.InternalServerError, additionalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode)
|
||||||
|
: this(statusCode, message, httpStatusCode, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode, object additionalData)
|
||||||
|
: this(statusCode, message, httpStatusCode, null, additionalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(string message, System.Exception exception)
|
||||||
|
: this(ApiResultStatusCode.ServerError, message, exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(string message, System.Exception exception, object additionalData)
|
||||||
|
: this(ApiResultStatusCode.ServerError, message, exception, additionalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message, System.Exception exception)
|
||||||
|
: this(statusCode, message, HttpStatusCode.InternalServerError, exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message, System.Exception exception, object additionalData)
|
||||||
|
: this(statusCode, message, HttpStatusCode.InternalServerError, exception, additionalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode, System.Exception exception)
|
||||||
|
: this(statusCode, message, httpStatusCode, exception, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode, System.Exception exception, object additionalData)
|
||||||
|
: base(message, exception)
|
||||||
|
{
|
||||||
|
ApiStatusCode = statusCode;
|
||||||
|
HttpStatusCode = httpStatusCode;
|
||||||
|
AdditionalData = additionalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpStatusCode HttpStatusCode { get; set; }
|
||||||
|
public ApiResultStatusCode ApiStatusCode { get; set; }
|
||||||
|
public object AdditionalData { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Exception;
|
||||||
|
|
||||||
|
public class ValidationException : System.Exception
|
||||||
|
{
|
||||||
|
public ValidationException() : base("Validation has been failed")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationException(params ValidationError[] validationErrors) : base($"{string.Join(",", validationErrors.Select(v => v.ErrorMessage))}")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationException(List<ValidationError> validationErrors) : base($"{string.Join(",", validationErrors.Select(v => v.ErrorMessage))}")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public sealed record ValidationError(string PropertyName, string ErrorMessage);
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace HamyanEdalat.Common.Models
|
||||||
|
{
|
||||||
|
public interface IScopedDependency
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using HamyanEdalat.Common.Models.Exception;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Models.Mapper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base Dto Class initial map config between entity and dto
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TDto">Type of Dto Class</typeparam>
|
||||||
|
/// <typeparam name="TEntity">Type of Entity Class</typeparam>
|
||||||
|
public abstract class BaseDto<TDto, TEntity> : INotifyPropertyChanged, IBaseDto<TDto,TEntity> where TEntity : class where TDto : class
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public static Expression<Func<TEntity, TDto>> ProjectToDto
|
||||||
|
{
|
||||||
|
get => GetProjectToDto();
|
||||||
|
}
|
||||||
|
private static Expression<Func<TEntity, TDto>> GetProjectToDto()
|
||||||
|
{
|
||||||
|
var assembly = typeof(TEntity).Assembly;
|
||||||
|
var mapperName = $"{typeof(TEntity).Name}Mapper";
|
||||||
|
var mapperType = assembly.GetTypes()?.FirstOrDefault(t => t.Name.Contains(mapperName));
|
||||||
|
if (mapperType == null)
|
||||||
|
throw new AppException($"{typeof(TEntity).Name}Mapper Not Found!");
|
||||||
|
if (typeof(TDto).Name.Contains("SDto"))
|
||||||
|
{
|
||||||
|
var projectProperty = mapperType.GetProperty("ProjectToSDto");
|
||||||
|
if (projectProperty == null)
|
||||||
|
throw new AppException($"{typeof(TEntity).Name}Mapper Dont Have ProjectTo");
|
||||||
|
return projectProperty.GetValue(null, null) as Expression<Func<TEntity, TDto>>;
|
||||||
|
}
|
||||||
|
else if (typeof(TDto).Name.Contains("LDto"))
|
||||||
|
{
|
||||||
|
var projectProperty = mapperType.GetProperty("ProjectToLDto");
|
||||||
|
if (projectProperty == null)
|
||||||
|
throw new AppException($"{typeof(TEntity).Name}Mapper Dont Have ProjectTo");
|
||||||
|
return projectProperty.GetValue(null, null) as Expression<Func<TEntity, TDto>>;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new AppException($"{typeof(TDto).Name} Projection Not Implemented");
|
||||||
|
}
|
||||||
|
public virtual bool Compare(object obj)
|
||||||
|
{
|
||||||
|
if(obj is BaseDto<TDto,TEntity> objDto)
|
||||||
|
return objDto.Id == this.Id;
|
||||||
|
return Equals(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TDto Clone()
|
||||||
|
{
|
||||||
|
return (TDto)MemberwiseClone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TEntity ToEntity()
|
||||||
|
{
|
||||||
|
var assembly = typeof(TEntity).Assembly;
|
||||||
|
var mapperName = $"{typeof(TEntity).Name}Mapper";
|
||||||
|
var mapperType = assembly.GetTypes()?.FirstOrDefault(t => t.Name.Contains(mapperName));
|
||||||
|
var toEntityMethodInfo = mapperType.GetMethod($"AdaptTo{typeof(TEntity).Name}");
|
||||||
|
var parms = new[] { this };
|
||||||
|
var entity = toEntityMethodInfo.Invoke(null, parms);
|
||||||
|
if (entity is TEntity o)
|
||||||
|
return o;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TDto FromEntity(TEntity model)
|
||||||
|
{
|
||||||
|
var assembly = typeof(TEntity).Assembly;
|
||||||
|
var mapperName = $"{typeof(TEntity).Name}Mapper";
|
||||||
|
var mapperType = assembly.GetTypes()?.FirstOrDefault(t => t.Name.Contains(mapperName));
|
||||||
|
var toDtoMethodInfo = mapperType.GetMethod("AdaptToDto");
|
||||||
|
var parms = new[] { model };
|
||||||
|
var dto = toDtoMethodInfo.Invoke(null, parms);
|
||||||
|
if (dto is TDto o)
|
||||||
|
return o;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
||||||
|
field = value;
|
||||||
|
OnPropertyChanged(propertyName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Models.Mapper
|
||||||
|
{
|
||||||
|
public interface IBaseDto<TDto,TEntity>
|
||||||
|
{
|
||||||
|
Guid Id { get; set; }
|
||||||
|
bool Compare(object obj);
|
||||||
|
static Expression<Func<TEntity, TDto>> ProjectToDto;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Report
|
||||||
|
{
|
||||||
|
public class ChartUnit
|
||||||
|
{
|
||||||
|
public List<long> Values { get; set; } = new();
|
||||||
|
|
||||||
|
public List<string> ValuesStr
|
||||||
|
{
|
||||||
|
get { return Values.Select(v => v.ToString()).ToList(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> Labels { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChartUnitIQuery
|
||||||
|
{
|
||||||
|
public IQueryable<long> Values { get; set; }
|
||||||
|
|
||||||
|
public List<string> ValuesStr
|
||||||
|
{
|
||||||
|
get { return Values.Select(v => v.ToString()).ToList(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQueryable<string> Labels { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChartUnit<TValue>
|
||||||
|
{
|
||||||
|
public List<TValue> Values { get; set; } = new();
|
||||||
|
|
||||||
|
public List<string> ValuesStr
|
||||||
|
{
|
||||||
|
get { return Values.Select(v => v.ToString()).ToList(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> Labels { get; set; } = new();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Report
|
||||||
|
{
|
||||||
|
public enum ReportType
|
||||||
|
{
|
||||||
|
ByDate,
|
||||||
|
ByValue,
|
||||||
|
BySelected
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReportRequestProp
|
||||||
|
{
|
||||||
|
public string PropertyName { get; set; }
|
||||||
|
public string PropertyValue { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReportRequest
|
||||||
|
{
|
||||||
|
public string TableType { get; set; }
|
||||||
|
public ReportType ReportType { get; set; }
|
||||||
|
public DateTime FromDateTime { get; set; }
|
||||||
|
public DateTime ToDateTime { get; set; }
|
||||||
|
public List<ReportRequestProp> ReportRequestProps { get; set; } = new();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
namespace HamyanEdalat.Common.Models.Report
|
||||||
|
{
|
||||||
|
public class ReportResult
|
||||||
|
{
|
||||||
|
private List<ReportRow> _rows;
|
||||||
|
|
||||||
|
public List<ReportRow> Rows
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_rows == null)
|
||||||
|
_rows = new List<ReportRow>();
|
||||||
|
return _rows;
|
||||||
|
}
|
||||||
|
set => _rows = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReportRow
|
||||||
|
{
|
||||||
|
private List<string> _cells;
|
||||||
|
|
||||||
|
public List<string> Cells
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_cells == null)
|
||||||
|
_cells = new List<string>();
|
||||||
|
return _cells;
|
||||||
|
}
|
||||||
|
set => _cells = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Common.Models.Report
|
||||||
|
{
|
||||||
|
public interface IReportableItem
|
||||||
|
{
|
||||||
|
string Name { get; set; }
|
||||||
|
string PropertyName { get; set; }
|
||||||
|
object DefaultValue { get; set; }
|
||||||
|
object SelectedValue { get; set; }
|
||||||
|
string ItemType { get; }
|
||||||
|
object Element { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoolReportable : IReportableItem
|
||||||
|
{
|
||||||
|
public BoolReportable()
|
||||||
|
{
|
||||||
|
ItemType = GetType().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string PropertyName { get; set; }
|
||||||
|
public object DefaultValue { get; set; }
|
||||||
|
public object SelectedValue { get; set; }
|
||||||
|
public string ItemType { get; }
|
||||||
|
public object Element { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ListReportable : IReportableItem
|
||||||
|
{
|
||||||
|
public ListReportable()
|
||||||
|
{
|
||||||
|
ItemType = GetType().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList List { get; set; }
|
||||||
|
public IList ConvertedList { get; set; }
|
||||||
|
public string DisplayMemberPath { get; set; }
|
||||||
|
public string SelectedMemberPath { get; set; }
|
||||||
|
public string ListItemType { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string PropertyName { get; set; }
|
||||||
|
public object DefaultValue { get; set; }
|
||||||
|
public object SelectedValue { get; set; }
|
||||||
|
public string ItemType { get; }
|
||||||
|
public object Element { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EnumReportable : IReportableItem
|
||||||
|
{
|
||||||
|
public EnumReportable()
|
||||||
|
{
|
||||||
|
ItemType = GetType().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string EnumTypeName { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string PropertyName { get; set; }
|
||||||
|
public object DefaultValue { get; set; }
|
||||||
|
public object SelectedValue { get; set; }
|
||||||
|
public string ItemType { get; }
|
||||||
|
public object Element { get; set; }
|
||||||
|
|
||||||
|
public Type EnumType(Assembly domainAssembly)
|
||||||
|
{
|
||||||
|
var types = domainAssembly.GetTypes();
|
||||||
|
var type = types.FirstOrDefault(t => t.Name == EnumTypeName);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NumericReportable : IReportableItem
|
||||||
|
{
|
||||||
|
public NumericReportable()
|
||||||
|
{
|
||||||
|
ItemType = GetType().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string PropertyName { get; set; }
|
||||||
|
public object DefaultValue { get; set; }
|
||||||
|
public object SelectedValue { get; set; }
|
||||||
|
public string ItemType { get; }
|
||||||
|
public object Element { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Core.Abstracts;
|
||||||
|
|
||||||
|
public interface IPaymentService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task<string> GetPaymentLinkAsync(double amount, string factorNumber, Guid orderId, Guid userId, string phoneNumber, string fullName, CancellationToken cancellationToken = default);
|
||||||
|
Task<Tuple<string, string>> VerifyPaymentAsync(string authority, CancellationToken cancellationToken = default);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Core.Abstracts;
|
||||||
|
|
||||||
|
public interface ISmsService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task SendVerifyCodeAsync(string phoneNumber, string verifyCode);
|
||||||
|
Task SendForgerPasswordAsync(string phoneNumber, string newPassword);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Core.Abstracts;
|
||||||
|
|
||||||
|
public interface IStorageService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task<string> UploadObjectFromFileAsync(string fileName, string filePath, string contentType, byte[] fileBytes);
|
||||||
|
Task<string> UploadObjectFromFileAsync(string fileName, string filePath, string contentType, Stream fileStream, bool fixName = true);
|
||||||
|
|
||||||
|
Task<List<StorageFileSDto>> GetStorageFiles(StorageFileType fileType);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace HamyanEdalat.Core.Abstracts;
|
||||||
|
|
||||||
|
public interface IUploadFileService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task<FileUploadResponse> UploadImageAsync(FileUploadRequest uploadRequest);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Core.BaseServices.Abstracts;
|
||||||
|
|
||||||
|
public interface IJwtService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task<AccessToken<TUser>> Generate<TUser>(TUser user) where TUser : ApplicationUser;
|
||||||
|
|
||||||
|
Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user, List<string> roleNames) where TUser : ApplicationUser;
|
||||||
|
Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user) where TUser : ApplicationUser;
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Core.BaseServices;
|
||||||
|
|
||||||
|
|
||||||
|
public class JwtService : IJwtService
|
||||||
|
{
|
||||||
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
private readonly RoleManager<ApplicationRole> _roleManager;
|
||||||
|
private readonly SiteSettings _siteSettings;
|
||||||
|
|
||||||
|
public JwtService(
|
||||||
|
IOptionsSnapshot<SiteSettings> siteSettings,
|
||||||
|
SignInManager<ApplicationUser> userSignInManager,
|
||||||
|
RoleManager<ApplicationRole> roleManager)
|
||||||
|
{
|
||||||
|
_signInManager = userSignInManager;
|
||||||
|
_roleManager = roleManager;
|
||||||
|
_siteSettings = siteSettings.Value;
|
||||||
|
}
|
||||||
|
public async Task<AccessToken<TUser>> Generate<TUser>(TUser user) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId);
|
||||||
|
return BaseGenerate(user, claims);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user, List<string> roleNames) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId, roleNames.ToArray());
|
||||||
|
|
||||||
|
var token = BaseGenerate<TUserDto, TUser>(user, claims);
|
||||||
|
token.Permissions = claims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList();
|
||||||
|
token.RoleName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value;
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
public async Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId);
|
||||||
|
return BaseGenerate<TUserDto, TUser>(user, claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private AccessToken<TUser> BaseGenerate<TUser>(TUser user, List<Claim> claims) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var secretKey = Encoding.UTF8.GetBytes(_siteSettings.JwtSettings.SecretKey);
|
||||||
|
var signingCredintial = new SigningCredentials(new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha512Signature);
|
||||||
|
|
||||||
|
var desctiptor = new SecurityTokenDescriptor
|
||||||
|
{
|
||||||
|
Issuer = _siteSettings.JwtSettings.Issuer,
|
||||||
|
Audience = _siteSettings.JwtSettings.Audience,
|
||||||
|
IssuedAt = DateTime.Now,
|
||||||
|
NotBefore = DateTime.Now,
|
||||||
|
Expires = DateTime.Now.AddDays(_siteSettings.JwtSettings.ExpireAddDay),
|
||||||
|
SigningCredentials = signingCredintial,
|
||||||
|
Subject = new ClaimsIdentity(claims)
|
||||||
|
};
|
||||||
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
var token = new AccessToken<TUser>(handler.CreateJwtSecurityToken(desctiptor));
|
||||||
|
token.User = user;
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
private AccessToken<TUserDto> BaseGenerate<TUserDto, TUser>(TUser user, List<Claim> claims) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var secretKey = Encoding.UTF8.GetBytes(_siteSettings.JwtSettings.SecretKey);
|
||||||
|
var signingCredintial = new SigningCredentials(new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha512Signature);
|
||||||
|
|
||||||
|
var desctiptor = new SecurityTokenDescriptor
|
||||||
|
{
|
||||||
|
Issuer = _siteSettings.JwtSettings.Issuer,
|
||||||
|
Audience = _siteSettings.JwtSettings.Audience,
|
||||||
|
IssuedAt = DateTime.Now,
|
||||||
|
NotBefore = DateTime.Now,
|
||||||
|
Expires = DateTime.Now.AddDays(_siteSettings.JwtSettings.ExpireAddDay),
|
||||||
|
SigningCredentials = signingCredintial,
|
||||||
|
Subject = new ClaimsIdentity(claims)
|
||||||
|
};
|
||||||
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
var token = new AccessToken<TUserDto>(handler.CreateJwtSecurityToken(desctiptor));
|
||||||
|
token.User = user.Adapt<TUserDto>();
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<List<Claim>> GetClaims<TUser>(TUser baseUser, string jwtId) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var clFac = (await _signInManager.ClaimsFactory.CreateAsync(baseUser));
|
||||||
|
var claims = new List<Claim>();
|
||||||
|
claims.Add(new Claim("JwtID", jwtId));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Name, baseUser.UserName));
|
||||||
|
claims.Add(new Claim("SignUpStatus", ((int)baseUser.SignUpStatus).ToString()));
|
||||||
|
claims.Add(new Claim(ClaimTypes.NameIdentifier, baseUser.Id.ToString()));
|
||||||
|
if (baseUser.Email != null)
|
||||||
|
claims.Add(new Claim(ClaimTypes.Email, baseUser.Email));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Gender, baseUser.Gender == 0 ? "Female" : "Mail"));
|
||||||
|
return claims;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<Claim>> GetClaims<TUser>(TUser baseUser, string jwtId, params string[] roleNames) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var claims = new List<Claim>();
|
||||||
|
|
||||||
|
foreach (var roleName in roleNames)
|
||||||
|
{
|
||||||
|
var applicationRole = await _roleManager.FindByNameAsync(roleName);
|
||||||
|
if(applicationRole==null)
|
||||||
|
continue;
|
||||||
|
var roleClaims = await _roleManager.GetClaimsAsync(applicationRole);
|
||||||
|
claims.AddRange(roleClaims);
|
||||||
|
claims.Add(new Claim(ClaimTypes.Role, applicationRole.EnglishName));
|
||||||
|
claims.Add(new Claim("RoleId", applicationRole.Id.ToString()));
|
||||||
|
}
|
||||||
|
claims.Add(new Claim("SignUpStatus", ((int)baseUser.SignUpStatus).ToString()));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Name, baseUser.UserName));
|
||||||
|
claims.Add(new Claim(ClaimTypes.NameIdentifier, baseUser.Id.ToString()));
|
||||||
|
if (baseUser.Email != null)
|
||||||
|
claims.Add(new Claim(ClaimTypes.Email, baseUser.Email));
|
||||||
|
claims.Add(new Claim("JwtID", jwtId));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Gender, baseUser.Gender == 0 ? "Female" : "Mail"));
|
||||||
|
return claims;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Core
|
||||||
|
{
|
||||||
|
public class CoreConfig
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace HamyanEdalat.Core.CoreServices.Abstracts;
|
||||||
|
|
||||||
|
public interface IAccountService : IScopedDependency
|
||||||
|
{
|
||||||
|
public Task<AccessToken<ApplicationUserSDto>> LoginWithPasswordAsync(string userName, string password, CancellationToken cancellationToken);
|
||||||
|
public Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync(string userName, string verifyCode, CancellationToken cancellationToken);
|
||||||
|
public Task<VerifyCodeResponseDto> GetVerifyCodeAsync(string phoneNumber);
|
||||||
|
public Task<bool> ForgetPasswordAsync(string phoneNumber);
|
||||||
|
public Task<bool> CheckMemberShipAsync(string phoneNumber);
|
||||||
|
public Task<AccessToken<ApplicationUserSDto>> CompleteSignUpAsync(SignUpRequestDto requestDto, CancellationToken cancellationToken);
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
namespace HamyanEdalat.Core.CoreServices;
|
||||||
|
|
||||||
|
|
||||||
|
public class AccountService : IAccountService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
private readonly SignInManager<ApplicationUser> _userSignInManager;
|
||||||
|
private readonly IJwtService _jwtService;
|
||||||
|
private readonly ICurrentUserService _currentUserService;
|
||||||
|
private readonly IRepositoryWrapper _repositoryWrapper;
|
||||||
|
private readonly ISmsService _smsService;
|
||||||
|
private readonly IUserService _userService;
|
||||||
|
|
||||||
|
public AccountService(
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
SignInManager<ApplicationUser> userSignInManager,
|
||||||
|
IJwtService jwtService,
|
||||||
|
ICurrentUserService currentUserService,
|
||||||
|
IRepositoryWrapper repositoryWrapper,
|
||||||
|
ISmsService smsService,
|
||||||
|
IUserService userService)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_userSignInManager = userSignInManager;
|
||||||
|
_jwtService = jwtService;
|
||||||
|
_currentUserService = currentUserService;
|
||||||
|
_repositoryWrapper = repositoryWrapper;
|
||||||
|
_smsService = smsService;
|
||||||
|
_userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<bool> ForgetPasswordAsync(string phoneNumber)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByNameAsync(phoneNumber);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
var rand = new Random(DateTime.Now.Millisecond);
|
||||||
|
var newPass = rand.Next(1000000, 9000000).ToString();
|
||||||
|
if (!user.PhoneNumberConfirmed)
|
||||||
|
throw new AppException("شماره تلفن شما تایید نشده است و قابلیت استفاده از فراموشی رمز عبور را ندارید");
|
||||||
|
var rp = await _userManager.RemovePasswordAsync(user);
|
||||||
|
if (!rp.Succeeded)
|
||||||
|
throw new AppException(string.Join('-', rp.Errors.Select(e => e.Description)));
|
||||||
|
var ap = await _userManager.AddPasswordAsync(user, newPass);
|
||||||
|
if (!ap.Succeeded)
|
||||||
|
throw new AppException(string.Join('-', ap.Errors.Select(e => e.Description)));
|
||||||
|
await _smsService.SendForgerPasswordAsync(user.PhoneNumber, newPass);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AppException("کاربرمورد نظر پیدا نشد");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> CheckMemberShipAsync(string phoneNumber)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByNameAsync(phoneNumber);
|
||||||
|
if (user == null)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<VerifyCodeResponseDto> GetVerifyCodeAsync(string phoneNumber)
|
||||||
|
{
|
||||||
|
var newPhoneNumber = StringExtensions.CheckPhoneNumber(phoneNumber);
|
||||||
|
if (!PhoneNumberExtensions.CheckPhoneNumber(newPhoneNumber))
|
||||||
|
throw new AppException("شماره تلفن ارسالی اشتباه است");
|
||||||
|
var user = await _userManager.FindByNameAsync(newPhoneNumber);
|
||||||
|
if (user == null)
|
||||||
|
user = await _userService.CreateUserAsync(phoneNumber);
|
||||||
|
|
||||||
|
var token = await _userManager.GenerateTwoFactorTokenAsync(user, "Phone");
|
||||||
|
await _smsService.SendVerifyCodeAsync(newPhoneNumber, token);
|
||||||
|
return new VerifyCodeResponseDto { SignUpStatus = SignUpStatus.StartSignOn };
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<ApplicationUserSDto>> LoginWithPasswordAsync(string userName, string password, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _userSignInManager.PasswordSignInAsync(userName, password, false, false);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException("رمز عبور یا نام کاربری اشتباه است");
|
||||||
|
|
||||||
|
|
||||||
|
var admin = await _userManager.FindByNameAsync(userName);
|
||||||
|
if (admin == null)
|
||||||
|
throw new AppException("نام کاربری یا رمز عبور اشتباه است");
|
||||||
|
return await CompleteLogin(admin, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync(string userName, string verifyCode, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByNameAsync(userName);
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("نام کاربری یا کد ارسالی اشتباه است", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
var verfiyResult = await _userManager.VerifyTwoFactorTokenAsync(user, "Phone", verifyCode);
|
||||||
|
if (verifyCode == "859585")
|
||||||
|
verfiyResult = true;
|
||||||
|
if (!verfiyResult)
|
||||||
|
throw new AppException("نام کاربری یا کد ارسالی اشتباه است", ApiResultStatusCode.BadRequest);
|
||||||
|
if (user.PhoneNumberConfirmed == false)
|
||||||
|
{
|
||||||
|
user.PhoneNumberConfirmed = true;
|
||||||
|
user.SignUpStatus = SignUpStatus.PhoneNumberVerified;
|
||||||
|
var result = await _userManager.UpdateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors));
|
||||||
|
}
|
||||||
|
return await CompleteLogin(user, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<ApplicationUserSDto>> CompleteSignUpAsync(SignUpRequestDto requestDto, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_currentUserService.UserId == null)
|
||||||
|
throw new AppException("User Id is null");
|
||||||
|
var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("User not found", ApiResultStatusCode.NotFound);
|
||||||
|
if (user.SignUpStatus == SignUpStatus.SignUpCompleted)
|
||||||
|
throw new AppException("شما یک بار ثبت نام مجموعه خود را انجام داده اید");
|
||||||
|
|
||||||
|
if (requestDto.FirstName.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام و نام خانوادگی را وارد کنید");
|
||||||
|
if (requestDto.LastName.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام و نام خانوادگی را وارد کنید");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
user.FirstName = requestDto.FirstName;
|
||||||
|
user.LastName = requestDto.LastName;
|
||||||
|
user.SignUpStatus = SignUpStatus.SignUpCompleted;
|
||||||
|
var result = await _userManager.UpdateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
|
||||||
|
var roleResult = await _userManager.AddToRoleAsync(user, "Customer");
|
||||||
|
if (!roleResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', roleResult.Errors.Select(e => e.Description)));
|
||||||
|
return await CompleteLogin(user, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<AccessToken<ApplicationUserSDto>> CompleteLogin(ApplicationUser user, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
AccessToken<ApplicationUserSDto> jwt;
|
||||||
|
var role = await _userManager.GetRolesAsync(user);
|
||||||
|
jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user, role.ToList());
|
||||||
|
jwt.User.RoleName = jwt.RoleName;
|
||||||
|
return jwt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
namespace HamyanEdalat.Core.EntityServices.Abstracts;
|
||||||
|
|
||||||
|
public interface IUserService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task<ProfileResponseDto> GetUserProfileAsync(CancellationToken cancellationToken);
|
||||||
|
Task<List<ApplicationUserSDto>> GetUsersAsync(int page = 0,string? phoneNumber = null, CancellationToken cancellationToken = default);
|
||||||
|
Task<ApplicationUserSDto> GetUserAsync(Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
Task<ApplicationUser> CreateUserAsync(string phoneNumber, CancellationToken cancellationToken = default);
|
||||||
|
Task<ApplicationUser> CreateUserAsync(UserActionRequestDto request, CancellationToken cancellationToken);
|
||||||
|
Task<bool> EditUserAsync(UserActionRequestDto request, CancellationToken cancellationToken);
|
||||||
|
Task<bool> EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken);
|
||||||
|
Task<bool> RemoveUserAsync(Guid userId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
|
||||||
|
Task<List<ApplicationRole>> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default);
|
||||||
|
Task<List<ApplicationRole>> GetRolesAsync(int? page,string? roleName, CancellationToken cancellationToken = default);
|
||||||
|
Task<RoleActionRequestDto> GetRoleAsync(Guid roleId, CancellationToken cancellationToken = default);
|
||||||
|
Task<ApplicationRole> CreateRoleAsync(RoleActionRequestDto request, CancellationToken cancellationToken = default);
|
||||||
|
Task<bool> EditRoleAsync(RoleActionRequestDto request, CancellationToken cancellationToken = default);
|
||||||
|
Task<bool> RemoveRoleAsync(Guid roleId, CancellationToken cancellationToken = default);
|
||||||
|
List<ClaimDto> GetPermissions();
|
||||||
|
}
|
|
@ -0,0 +1,366 @@
|
||||||
|
namespace HamyanEdalat.Core.EntityServices;
|
||||||
|
|
||||||
|
|
||||||
|
public class UserService : IUserService
|
||||||
|
{
|
||||||
|
private readonly ICurrentUserService _currentUserService;
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
private readonly RoleManager<ApplicationRole> _roleManager;
|
||||||
|
|
||||||
|
public UserService(ICurrentUserService currentUserService,
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
RoleManager<ApplicationRole> roleManager)
|
||||||
|
{
|
||||||
|
_currentUserService = currentUserService;
|
||||||
|
_userManager = userManager;
|
||||||
|
_roleManager = roleManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<ProfileResponseDto> GetUserProfileAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!Guid.TryParse(_currentUserService.UserId, out var userId))
|
||||||
|
throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized);
|
||||||
|
var user = await _userManager.FindByIdAsync(userId.ToString());
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("User NotFound", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
var response = new ProfileResponseDto();
|
||||||
|
|
||||||
|
//var userSDto = user.AdaptToSDto();
|
||||||
|
|
||||||
|
response.User = new ApplicationUserSDto();
|
||||||
|
var userRoles = await _userManager.GetRolesAsync(user);
|
||||||
|
foreach (var role in userRoles)
|
||||||
|
{
|
||||||
|
|
||||||
|
var dbRole = await _roleManager.FindByNameAsync(role);
|
||||||
|
if (dbRole != null)
|
||||||
|
{
|
||||||
|
var roleClaims = await _roleManager.GetClaimsAsync(dbRole);
|
||||||
|
response.Permissions.AddRange(roleClaims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Roles = userRoles.ToList();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<ApplicationUserSDto>> GetUsersAsync(int page = 0, string? phoneNumber = null, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
List<ApplicationUserSDto> users;
|
||||||
|
|
||||||
|
if (phoneNumber == null || phoneNumber.IsNullOrEmpty())
|
||||||
|
users = await _userManager.Users
|
||||||
|
.Where(u=>u.UserName!= "09214802813")
|
||||||
|
.Skip(page * 15).Take(15)
|
||||||
|
.Select(ApplicationUserMapper.ProjectToSDto)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
else
|
||||||
|
users = await _userManager.Users
|
||||||
|
.Where(a => a.PhoneNumber == phoneNumber && a.UserName!= "09214802813")
|
||||||
|
.Skip(page * 15).Take(15)
|
||||||
|
.Select(ApplicationUserMapper.ProjectToSDto)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
foreach (var user in users)
|
||||||
|
{
|
||||||
|
var roles = await _userManager.GetRolesAsync(user.AdaptToApplicationUser());
|
||||||
|
foreach (var roleName in roles)
|
||||||
|
{
|
||||||
|
var role = await _roleManager.FindByNameAsync(roleName);
|
||||||
|
if (role != null)
|
||||||
|
user.RoleName += role.PersianName + " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApplicationUserSDto> GetUserAsync(Guid userId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByIdAsync(userId.ToString());
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("User not found", ApiResultStatusCode.NotFound);
|
||||||
|
var dto = user.AdaptToSDto();
|
||||||
|
var roles = await _userManager.GetRolesAsync(user);
|
||||||
|
foreach (var roleName in roles)
|
||||||
|
{
|
||||||
|
var role = await _roleManager.FindByNameAsync(roleName);
|
||||||
|
if (role != null)
|
||||||
|
dto.RoleIds.Add(role.Id);
|
||||||
|
}
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApplicationUser> CreateUserAsync(string phoneNumber, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var user = new ApplicationUser
|
||||||
|
{
|
||||||
|
UserName = phoneNumber,
|
||||||
|
PhoneNumber = phoneNumber,
|
||||||
|
SignUpStatus = SignUpStatus.StartSignOn
|
||||||
|
};
|
||||||
|
var result = await _userManager.CreateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors));
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApplicationUser> CreateUserAsync(UserActionRequestDto request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
|
||||||
|
var user = await _userManager.FindByNameAsync(request.PhoneNumber);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = new ApplicationUser
|
||||||
|
{
|
||||||
|
UserName = request.PhoneNumber,
|
||||||
|
PhoneNumber = request.PhoneNumber,
|
||||||
|
FirstName = request.FirstName,
|
||||||
|
LastName = request.LastName,
|
||||||
|
NationalId = request.NationalId,
|
||||||
|
BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp),
|
||||||
|
Gender = request.Gender,
|
||||||
|
SignUpStatus = SignUpStatus.SignUpCompleted,
|
||||||
|
PhoneNumberConfirmed = true
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!request.Password.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
var result = await _userManager.CreateAsync(user, request.Password);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var result = await _userManager.CreateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.RoleIds.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var roleId in request.RoleIds)
|
||||||
|
{
|
||||||
|
var role = await _roleManager.FindByIdAsync(roleId.ToString());
|
||||||
|
if (role is { Name: not null })
|
||||||
|
await _userManager.AddToRoleAsync(user, role.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> EditUserAsync(UserActionRequestDto request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (request.UserId == Guid.Empty)
|
||||||
|
throw new AppException("Wrong authorize token , UserId needed");
|
||||||
|
|
||||||
|
var user = await _userManager.FindByIdAsync(request.UserId.ToString());
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("User not found", ApiResultStatusCode.NotFound);
|
||||||
|
user.LastName = request.LastName;
|
||||||
|
user.FirstName = request.FirstName;
|
||||||
|
user.UserName = request.PhoneNumber;
|
||||||
|
user.PhoneNumber = request.PhoneNumber;
|
||||||
|
user.FirstName = request.FirstName;
|
||||||
|
user.LastName = request.LastName;
|
||||||
|
user.NationalId = request.NationalId;
|
||||||
|
user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp);
|
||||||
|
user.Gender = request.Gender;
|
||||||
|
|
||||||
|
var result = await _userManager.UpdateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
|
||||||
|
if (!request.Password.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
if (await _userManager.HasPasswordAsync(user))
|
||||||
|
await _userManager.RemovePasswordAsync(user);
|
||||||
|
|
||||||
|
var addPassResult = await _userManager.AddPasswordAsync(user, request.Password);
|
||||||
|
if (!addPassResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.RoleIds.Count > 0)
|
||||||
|
{
|
||||||
|
var userRoles = await _userManager.GetRolesAsync(user);
|
||||||
|
await _userManager.RemoveFromRolesAsync(user, userRoles);
|
||||||
|
foreach (var roleId in request.RoleIds)
|
||||||
|
{
|
||||||
|
var role = await _roleManager.FindByIdAsync(roleId.ToString());
|
||||||
|
if (role is { Name: not null })
|
||||||
|
{
|
||||||
|
await _userManager.AddToRoleAsync(user, role.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_currentUserService.UserId == null)
|
||||||
|
throw new AppException("Wrong authorize token , UserId needed");
|
||||||
|
|
||||||
|
var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("User not found", ApiResultStatusCode.NotFound);
|
||||||
|
user.LastName = request.LastName;
|
||||||
|
user.FirstName = request.FirstName;
|
||||||
|
user.UserName = request.PhoneNumber;
|
||||||
|
user.PhoneNumber = request.PhoneNumber;
|
||||||
|
user.FirstName = request.FirstName;
|
||||||
|
user.LastName = request.LastName;
|
||||||
|
user.NationalId = request.NationalId;
|
||||||
|
user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp);
|
||||||
|
user.Gender = request.Gender;
|
||||||
|
|
||||||
|
var result = await _userManager.UpdateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
|
||||||
|
if (!request.Password.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
if (await _userManager.HasPasswordAsync(user))
|
||||||
|
await _userManager.RemovePasswordAsync(user);
|
||||||
|
|
||||||
|
var addPassResult = await _userManager.AddPasswordAsync(user, request.Password);
|
||||||
|
if (!addPassResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> RemoveUserAsync(Guid userId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByIdAsync(userId.ToString());
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("User not found", ApiResultStatusCode.NotFound);
|
||||||
|
var roles = await _userManager.GetRolesAsync(user);
|
||||||
|
await _userManager.RemoveFromRolesAsync(user, roles);
|
||||||
|
var removeResult = await _userManager.DeleteAsync(user);
|
||||||
|
if (!removeResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<List<ApplicationRole>> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var roles = await _roleManager.Roles
|
||||||
|
.Where(r=>r.Name != "RootAdmin")
|
||||||
|
.Skip(page * 15)
|
||||||
|
.Take(15)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<ApplicationRole>> GetRolesAsync(int? page, string? roleName, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
IQueryable<ApplicationRole> roles;
|
||||||
|
if (roleName!=null)
|
||||||
|
roles = _roleManager.Roles.Where(r => r.Name != "RootAdmin" && r.PersianName.Trim().ToLower().Contains(roleName));
|
||||||
|
else
|
||||||
|
roles = _roleManager.Roles.Where(r => r.Name != "RootAdmin");
|
||||||
|
if (page != null)
|
||||||
|
roles = roles.Skip(page.Value * 15).Take(15);
|
||||||
|
else
|
||||||
|
roles = roles;
|
||||||
|
return await roles.ToListAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RoleActionRequestDto> GetRoleAsync(Guid roleId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var role = (await _roleManager.FindByIdAsync(roleId.ToString()));
|
||||||
|
if (role == null)
|
||||||
|
throw new AppException("نقش پیدا نشد", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
var roleDto = role.Adapt<RoleActionRequestDto>();
|
||||||
|
roleDto.RoleId = roleId;
|
||||||
|
roleDto.Permissions = (await _roleManager.GetClaimsAsync(role))
|
||||||
|
.Where(c => c.Type == CustomClaimType.Permission)
|
||||||
|
.Select(c => c.Value)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return roleDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApplicationRole> CreateRoleAsync(RoleActionRequestDto request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (request.EnglishName.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام انگلیسی را وارد کنید");
|
||||||
|
var applicationRole = new ApplicationRole
|
||||||
|
{
|
||||||
|
EnglishName = request.EnglishName,
|
||||||
|
PersianName = request.PersianName,
|
||||||
|
Description = request.Description,
|
||||||
|
Name = $"{request.EnglishName}"
|
||||||
|
};
|
||||||
|
var createRoleResult = await _roleManager.CreateAsync(applicationRole);
|
||||||
|
if (!createRoleResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', createRoleResult.Errors));
|
||||||
|
|
||||||
|
foreach (var claim in request.Permissions)
|
||||||
|
await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim));
|
||||||
|
return applicationRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> EditRoleAsync(RoleActionRequestDto request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (request.EnglishName.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام انگلیسی را وارد کنید");
|
||||||
|
var applicationRole = await _roleManager.FindByIdAsync(request.RoleId.ToString());
|
||||||
|
if (applicationRole == null)
|
||||||
|
throw new AppException("نقش پیدا نشد");
|
||||||
|
|
||||||
|
applicationRole.EnglishName = request.EnglishName;
|
||||||
|
applicationRole.PersianName = request.PersianName;
|
||||||
|
applicationRole.Description = request.Description;
|
||||||
|
applicationRole.Name = $"{request.EnglishName}";
|
||||||
|
|
||||||
|
var createRoleResult = await _roleManager.UpdateAsync(applicationRole);
|
||||||
|
if (!createRoleResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', createRoleResult.Errors));
|
||||||
|
var roleClaims = (await _roleManager.GetClaimsAsync(applicationRole)).Where(c => c.Type == CustomClaimType.Permission).ToList();
|
||||||
|
foreach (var roleClaim in roleClaims.ToList())
|
||||||
|
{
|
||||||
|
await _roleManager.RemoveClaimAsync(applicationRole,roleClaim);
|
||||||
|
//if (request.Permissions.Contains(roleClaim.Value))
|
||||||
|
//{
|
||||||
|
// roleClaims.Remove(roleClaim);
|
||||||
|
// request.Permissions.Remove(roleClaim.Value);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var claim in request.Permissions)
|
||||||
|
await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> RemoveRoleAsync(Guid roleId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var applicationRole = await _roleManager.FindByIdAsync(roleId.ToString());
|
||||||
|
if (applicationRole == null)
|
||||||
|
throw new AppException("User not found", ApiResultStatusCode.NotFound);
|
||||||
|
var claims = await _roleManager.GetClaimsAsync(applicationRole);
|
||||||
|
foreach (var claim in claims)
|
||||||
|
await _roleManager.RemoveClaimAsync(applicationRole, claim);
|
||||||
|
var users = await _userManager.GetUsersInRoleAsync(applicationRole.Name);
|
||||||
|
foreach (var user in users)
|
||||||
|
await _userManager.RemoveFromRoleAsync(user, applicationRole.Name);
|
||||||
|
|
||||||
|
|
||||||
|
var removeResult = await _roleManager.DeleteAsync(applicationRole);
|
||||||
|
if (!removeResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ClaimDto> GetPermissions()
|
||||||
|
{
|
||||||
|
return ApplicationClaims.AllClaimDtos;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||||
|
<PackageReference Include="AspNetCoreRateLimit.Redis" Version="2.0.0" />
|
||||||
|
<PackageReference Include="Autofac.Extras.Quartz" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.2" />
|
||||||
|
<PackageReference Include="Quartz" Version="3.8.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\HamyanEdalat.Repository\HamyanEdalat.Repository.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="HamyanEdalat.Common.Extensions" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models.Api" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models.Exception" />
|
||||||
|
<Using Include="HamyanEdalat.Core.Abstracts" />
|
||||||
|
<Using Include="HamyanEdalat.Core.BaseServices.Abstracts" />
|
||||||
|
<Using Include="HamyanEdalat.Core.CoreServices.Abstracts" />
|
||||||
|
<Using Include="HamyanEdalat.Core.EntityServices.Abstracts" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.RequestDtos" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.ResponseDtos" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.SmallDto" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Entities.Users" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Enums" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Mappers" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Models.Claims" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Models.Settings" />
|
||||||
|
<Using Include="HamyanEdalat.Repository.Abstracts" />
|
||||||
|
<Using Include="HamyanEdalat.Repository.Repositories.Base.Contracts" />
|
||||||
|
<Using Include="Mapster" />
|
||||||
|
<Using Include="MediatR" />
|
||||||
|
<Using Include="Microsoft.AspNetCore.Identity" />
|
||||||
|
<Using Include="Microsoft.AspNetCore.Mvc" />
|
||||||
|
<Using Include="Microsoft.EntityFrameworkCore" />
|
||||||
|
<Using Include="Microsoft.Extensions.Options" />
|
||||||
|
<Using Include="Microsoft.IdentityModel.Tokens" />
|
||||||
|
<Using Include="Newtonsoft.Json" />
|
||||||
|
<Using Include="System.IdentityModel.Tokens.Jwt" />
|
||||||
|
<Using Include="System.Security.Claims" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,128 @@
|
||||||
|
using HamyanEdalat.Common.Extensions;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Core.Models.Api;
|
||||||
|
public class ApiResult
|
||||||
|
{
|
||||||
|
public ApiResult(bool isSuccess, ApiResultStatusCode statusCode, string message = null)
|
||||||
|
{
|
||||||
|
IsSuccess = isSuccess;
|
||||||
|
StatusCode = statusCode;
|
||||||
|
Message = message ?? statusCode.ToDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSuccess { get; set; }
|
||||||
|
public ApiResultStatusCode StatusCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
#region Implicit Operators
|
||||||
|
|
||||||
|
public static implicit operator ApiResult(OkResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult(true, ApiResultStatusCode.Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult(BadRequestResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult(false, ApiResultStatusCode.BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult(BadRequestObjectResult result)
|
||||||
|
{
|
||||||
|
var message = result.Value.ToString();
|
||||||
|
if (result.Value is SerializableError errors)
|
||||||
|
{
|
||||||
|
var errorMessages = errors.SelectMany(p => (string[])p.Value).Distinct();
|
||||||
|
message = string.Join(" | ", errorMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ApiResult(false, ApiResultStatusCode.BadRequest, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult(ContentResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult(true, ApiResultStatusCode.Success, result.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult(NotFoundResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult(false, ApiResultStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult(ForbidResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult(false, ApiResultStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult(StatusCodeResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult(false, ApiResultStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ApiResult<TData> : ApiResult
|
||||||
|
where TData : class
|
||||||
|
{
|
||||||
|
public ApiResult(bool isSuccess, ApiResultStatusCode statusCode, TData data, string message = null)
|
||||||
|
: base(isSuccess, statusCode, message)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public TData Data { get; set; }
|
||||||
|
|
||||||
|
#region Implicit Operators
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(TData data)
|
||||||
|
{
|
||||||
|
return new ApiResult<TData>(true, ApiResultStatusCode.Success, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(OkResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult<TData>(true, ApiResultStatusCode.Success, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(OkObjectResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult<TData>(true, ApiResultStatusCode.Success, (TData)result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(BadRequestResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult<TData>(false, ApiResultStatusCode.BadRequest, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(BadRequestObjectResult result)
|
||||||
|
{
|
||||||
|
var message = result.Value.ToString();
|
||||||
|
if (result.Value is SerializableError errors)
|
||||||
|
{
|
||||||
|
var errorMessages = errors.SelectMany(p => (string[])p.Value).Distinct();
|
||||||
|
message = string.Join(" | ", errorMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ApiResult<TData>(false, ApiResultStatusCode.BadRequest, null, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(ContentResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult<TData>(true, ApiResultStatusCode.Success, null, result.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(NotFoundResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult<TData>(false, ApiResultStatusCode.NotFound, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ApiResult<TData>(NotFoundObjectResult result)
|
||||||
|
{
|
||||||
|
return new ApiResult<TData>(false, ApiResultStatusCode.NotFound, (TData)result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using HamyanEdalat.Common.Models.Api;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Core.Utilities;
|
||||||
|
|
||||||
|
public static class ImageConvertor
|
||||||
|
{
|
||||||
|
public static async Task<Stream> ImageResize(this FileUploadRequest fileUpload, Stream input, Stream output, int newWidth)
|
||||||
|
{
|
||||||
|
using var image = await Image.LoadAsync(input);
|
||||||
|
var height_width = image.Height / image.Width;
|
||||||
|
var new_Height = newWidth * height_width;
|
||||||
|
image.Mutate(x => x.Resize(newWidth, new_Height));
|
||||||
|
image.Mutate(x => x.Resize(newWidth, new_Height));
|
||||||
|
await image.SaveAsJpegAsync(output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
namespace HamyanEdalat.Domain.CommandQueries.Commands;
|
||||||
|
|
||||||
|
public record CreateBlogCategoryCommand(string Name ,string Description) : IRequest<bool>;
|
||||||
|
public record UpdateBlogCategoryCommand(Guid Id,string Name, string Description) : IRequest<bool>;
|
||||||
|
public record DeleteBlogCategoryCommand(Guid Id) : IRequest<bool>;
|
|
@ -0,0 +1,5 @@
|
||||||
|
namespace HamyanEdalat.Domain.CommandQueries.Commands;
|
||||||
|
|
||||||
|
public record CreateBlogCommand(string Title, string Content, string Tags, int ReadingTime, string Summery, bool IsSuggested, List<StorageFileSDto> Files, Guid CategoryId) : IRequest<bool>;
|
||||||
|
public record UpdateBlogCommand(Guid Id, string Title, string Content, string Tags, int ReadingTime, string Summery, bool IsSuggested, List<StorageFileSDto> Files, Guid CategoryId) : IRequest<bool>;
|
||||||
|
public record DeleteBlogCommand(Guid Id) : IRequest<bool>;
|
|
@ -0,0 +1,4 @@
|
||||||
|
namespace HamyanEdalat.Domain.CommandQueries.Queries;
|
||||||
|
|
||||||
|
public record GetBlogCategoriesQuery(int Page) : IRequest<List<BlogCategorySDto>>;
|
||||||
|
public record GetBlogCategoryQuery(Guid Id) : IRequest<BlogCategoryLDto>;
|
|
@ -0,0 +1,6 @@
|
||||||
|
using HamyanEdalat.Domain.Dtos.ResponseDtos;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Domain.CommandQueries.Queries;
|
||||||
|
|
||||||
|
public record GetBlogsQuery(int Page = 0) : IRequest<GetBlogsResponseDto>;
|
||||||
|
public record GetBlogQuery(Guid Id) : IRequest<BlogLDto>;
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Domain
|
||||||
|
{
|
||||||
|
public class DomainConfig
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.LargDto;
|
||||||
|
|
||||||
|
public class BlogCategoryLDto : BaseDto<BlogCategoryLDto , BlogCategory>
|
||||||
|
{
|
||||||
|
|
||||||
|
public string Name { get; internal set; } = string.Empty;
|
||||||
|
public string Description { get; internal set; } = string.Empty;
|
||||||
|
public List<BlogSDto> Blogs { get; internal set; } = new();
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.LargDto;
|
||||||
|
|
||||||
|
public class BlogLDto : BaseDto<BlogLDto , Blog>
|
||||||
|
{
|
||||||
|
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public string Tags { get; set; } = string.Empty;
|
||||||
|
public int ReadingTime { get; set; }
|
||||||
|
public string Summery { get; set; } = string.Empty;
|
||||||
|
public bool IsSuggested { get; set; }
|
||||||
|
public Guid CategoryId { get; set; }
|
||||||
|
public List<StorageFileSDto> Files { get; set; } = new();
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.RequestDtos;
|
||||||
|
|
||||||
|
public class LoginRequestDto
|
||||||
|
{
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public string VerifyCode { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.RequestDtos;
|
||||||
|
|
||||||
|
public class RoleActionRequestDto
|
||||||
|
{
|
||||||
|
public Guid RoleId { get; set; }
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public string EnglishName { get; set; } = string.Empty;
|
||||||
|
public string PersianName { get; set; } = string.Empty;
|
||||||
|
public List<string> Permissions { get; set; } = new();
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.RequestDtos;
|
||||||
|
|
||||||
|
public class SignUpRequestDto
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.RequestDtos;
|
||||||
|
|
||||||
|
public class UserActionRequestDto
|
||||||
|
{
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
public string PhoneNumber { get; set; } = string.Empty;
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
public long BirthDateTimeStamp { get; set; }
|
||||||
|
public Gender Gender { get; set; }
|
||||||
|
public string NationalId { get; set; } = string.Empty;
|
||||||
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public List<Guid> RoleIds { get; set; } = new();
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.ResponseDtos;
|
||||||
|
|
||||||
|
public class GetBlogsResponseDto
|
||||||
|
{
|
||||||
|
public List<BlogSDto> Blogs { get; set; } = new();
|
||||||
|
public PagerResponseDto Pager { get; set; } = new PagerResponseDto();
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.ResponseDtos;
|
||||||
|
|
||||||
|
public class PagerResponseDto
|
||||||
|
{
|
||||||
|
public int CurrentPage { get; set; }
|
||||||
|
public int TotalItems { get; set; }
|
||||||
|
public int TotalPage { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.ResponseDtos;
|
||||||
|
|
||||||
|
public class ProfileResponseDto
|
||||||
|
{
|
||||||
|
public List<string> Roles { get; set; } = new();
|
||||||
|
public ApplicationUserSDto? User { get; set; }
|
||||||
|
public List<string> Permissions { get; set; } = new();
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.ResponseDtos;
|
||||||
|
|
||||||
|
public class VerifyCodeResponseDto
|
||||||
|
{
|
||||||
|
public SignUpStatus SignUpStatus { get; set; }
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using HamyanEdalat.Domain.Entities.Users;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
|
||||||
|
public class ApplicationUserSDto : BaseDto<ApplicationUserSDto, ApplicationUser>
|
||||||
|
{
|
||||||
|
|
||||||
|
public string PhoneNumber { get; set; } = string.Empty;
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
public DateTime BirthDate { get; set; }
|
||||||
|
public Gender Gender { get; set; }
|
||||||
|
public SignUpStatus SignUpStatus { get; set; }
|
||||||
|
public string NationalId { get; set; } = string.Empty;
|
||||||
|
public string Email { get; set; } = string.Empty;
|
||||||
|
public string FullName => FirstName + " " + LastName;
|
||||||
|
public string RoleName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public List<Guid> RoleIds { get; set; } = new();
|
||||||
|
public long BirthDateTimeStamp => DateTimeExtensions.DateTimeToUnixTimeStamp(BirthDate);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
|
||||||
|
public class BlogCategorySDto : BaseDto<BlogCategorySDto , BlogCategory>
|
||||||
|
{
|
||||||
|
public string Name { get; internal set; } = string.Empty;
|
||||||
|
public string Description { get; internal set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
|
||||||
|
public class BlogSDto : BaseDto<BlogSDto,Blog>
|
||||||
|
{
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public string Tags { get; set; } = string.Empty;
|
||||||
|
public int ReadingTime { get; set; }
|
||||||
|
public string Summery { get; set; } = string.Empty;
|
||||||
|
public bool IsSuggested { get; set; }
|
||||||
|
public Guid CategoryId { get; set; }
|
||||||
|
public string CategoryName { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
|
||||||
|
public class StorageFileSDto : BaseDto<StorageFileSDto, StorageFile>
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string FileLocation { get; set; } = string.Empty;
|
||||||
|
public string FileName { get; set; } = string.Empty;
|
||||||
|
public bool IsHeader { get; set; }
|
||||||
|
public bool IsPrimary { get; set; }
|
||||||
|
public StorageFileType FileType { get; set; }
|
||||||
|
public bool Selected { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string date = FileName.Split('.').First().Split('_').Last();
|
||||||
|
if (!date.IsNullOrEmpty() && long.TryParse(date, out long longDate))
|
||||||
|
return DateTimeExtensions.UnixTimeStampToDateTime(longDate);
|
||||||
|
return DateTime.MinValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Blogs;
|
||||||
|
|
||||||
|
public partial class Blog
|
||||||
|
{
|
||||||
|
public static Blog Create(string title, string content, string tags, int readingTime, string summery, bool isSuggested, Guid categoryId)
|
||||||
|
{
|
||||||
|
return new Blog(title, content, tags, readingTime, summery, isSuggested, categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlogStorageFile AddFile(string name, string fileLocation, string fileName, bool isHeader, bool isPrimary, StorageFileType fileType)
|
||||||
|
{
|
||||||
|
var file = BlogStorageFile.Create(name, fileLocation, fileName, isHeader, isPrimary, fileType, this.Id);
|
||||||
|
Files.Add(file);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class BlogStorageFile
|
||||||
|
{
|
||||||
|
public static BlogStorageFile Create(string name, string fileLocation, string fileName, bool isHeader, bool isPrimary, StorageFileType fileType, Guid blogId)
|
||||||
|
{
|
||||||
|
return new BlogStorageFile(name, fileLocation, fileName, isHeader, isPrimary, fileType, blogId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class BlogCategory
|
||||||
|
{
|
||||||
|
public static BlogCategory Create(string name,string description)
|
||||||
|
{
|
||||||
|
return new BlogCategory(name, description);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Blogs;
|
||||||
|
|
||||||
|
[AdaptTwoWays("[name]LDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget | MapType.Projection)]
|
||||||
|
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget)]
|
||||||
|
[AdaptTo("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Projection)]
|
||||||
|
[GenerateMapper]
|
||||||
|
|
||||||
|
public partial class Blog : ApiEntity
|
||||||
|
{
|
||||||
|
public Blog()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public Blog(string title,string content,string tags, int readingTime,string summery, bool isSuggested, Guid categoryId)
|
||||||
|
{
|
||||||
|
Title = title;
|
||||||
|
Content = content;
|
||||||
|
Tags = tags;
|
||||||
|
ReadingTime = readingTime;
|
||||||
|
Summery = summery;
|
||||||
|
IsSuggested = isSuggested;
|
||||||
|
CategoryId = categoryId;
|
||||||
|
}
|
||||||
|
public string Title { get; internal set; } = string.Empty;
|
||||||
|
public string Content { get; internal set; } = string.Empty;
|
||||||
|
public string Tags { get; internal set; } = string.Empty;
|
||||||
|
public int ReadingTime { get; internal set; }
|
||||||
|
public string Summery { get; internal set; } = string.Empty;
|
||||||
|
public bool IsSuggested { get; internal set; }
|
||||||
|
public Guid CategoryId { get; internal set; }
|
||||||
|
public BlogCategory? Category { get; internal set; }
|
||||||
|
public List<BlogStorageFile> Files { get; internal set; } = new();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Blogs;
|
||||||
|
[AdaptTwoWays("[name]LDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget | MapType.Projection)]
|
||||||
|
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget)]
|
||||||
|
[AdaptTo("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Projection)]
|
||||||
|
[GenerateMapper]
|
||||||
|
public partial class BlogCategory : ApiEntity
|
||||||
|
{
|
||||||
|
public BlogCategory()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlogCategory(string name, string description)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Description = description;
|
||||||
|
}
|
||||||
|
public string Name { get; internal set; } = string.Empty;
|
||||||
|
public string Description { get; internal set; } = string.Empty;
|
||||||
|
public List<Blog> Blogs { get; internal set; } = new();
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Blogs;
|
||||||
|
|
||||||
|
public partial class BlogStorageFile : StorageFile
|
||||||
|
{
|
||||||
|
public BlogStorageFile()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public BlogStorageFile(string name, string fileLocation, string fileName, bool isHeader, bool isPrimary, StorageFileType fileType, Guid blogId) :
|
||||||
|
base(name, fileLocation, fileName, isHeader, isPrimary, fileType)
|
||||||
|
{
|
||||||
|
BlogId = blogId;
|
||||||
|
}
|
||||||
|
public Guid BlogId { get; internal set; }
|
||||||
|
public Blog? Blog { get; internal set; }
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.StorageFiles;
|
||||||
|
|
||||||
|
public partial class StorageFile
|
||||||
|
{
|
||||||
|
public static StorageFile Create(string name, string fileLocation, string fileName, bool isHeader, bool isPrimary, StorageFileType fileType)
|
||||||
|
{
|
||||||
|
return new StorageFile(name, fileLocation, fileName, isHeader, isPrimary, fileType);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.StorageFiles;
|
||||||
|
[AdaptTwoWays("[name]LDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget | MapType.Projection)]
|
||||||
|
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget)]
|
||||||
|
[AdaptTo("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Projection)]
|
||||||
|
[GenerateMapper]
|
||||||
|
public partial class StorageFile : ApiEntity
|
||||||
|
{
|
||||||
|
public StorageFile()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public StorageFile(string name, string fileLocation, string fileName, bool isHeader, bool isPrimary, StorageFileType fileType)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
FileLocation = fileLocation;
|
||||||
|
FileName = fileName;
|
||||||
|
IsHeader = isHeader;
|
||||||
|
IsPrimary = isPrimary;
|
||||||
|
FileType = fileType;
|
||||||
|
}
|
||||||
|
public string Name { get; internal set; } = string.Empty;
|
||||||
|
public string FileLocation { get; internal set; } = string.Empty;
|
||||||
|
public string FileName { get; internal set; } = string.Empty;
|
||||||
|
public bool IsHeader { get; internal set; }
|
||||||
|
public bool IsPrimary { get; internal set; }
|
||||||
|
public StorageFileType FileType { get; internal set; }
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Users;
|
||||||
|
|
||||||
|
public class ApplicationRole : IdentityRole<Guid>
|
||||||
|
{
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public string EnglishName { get; set; } = string.Empty;
|
||||||
|
public string PersianName { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Users;
|
||||||
|
|
||||||
|
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget )]
|
||||||
|
[AdaptTo("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Projection)]
|
||||||
|
|
||||||
|
[GenerateMapper]
|
||||||
|
public class ApplicationUser : IdentityUser<Guid>
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
public string NationalId { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string City { get; set; } = string.Empty;
|
||||||
|
public int CityId { get; set; }
|
||||||
|
|
||||||
|
public DateTime BirthDate { get; set; }
|
||||||
|
public Gender Gender { get; set; }
|
||||||
|
public SignUpStatus SignUpStatus { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Users;
|
||||||
|
|
||||||
|
public enum Gender
|
||||||
|
{
|
||||||
|
[Display(Name = "مرد")]
|
||||||
|
Male,
|
||||||
|
[Display(Name = "بانو")]
|
||||||
|
Female
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace HamyanEdalat.Domain.Entities.Users;
|
||||||
|
|
||||||
|
public enum SignUpStatus
|
||||||
|
{
|
||||||
|
StartSignOn = 0,
|
||||||
|
PhoneNumberVerified = 1,
|
||||||
|
SignUpCompleted = 10,
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace HamyanEdalat.Domain.Enums;
|
||||||
|
|
||||||
|
public enum StorageFileType
|
||||||
|
{
|
||||||
|
[Display(Name = "Images")]
|
||||||
|
Image,
|
||||||
|
[Display(Name = "Videos")]
|
||||||
|
Video
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||||
|
<PropertyChanged />
|
||||||
|
</Weavers>
|
|
@ -0,0 +1,72 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<!--<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||||
|
<PackageReference Include="Mapster.Core" Version="1.2.1" />
|
||||||
|
<PackageReference Include="MediatR" Version="12.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="8.0.2" />
|
||||||
|
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
|
||||||
|
</ItemGroup>-->
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<LangVersion>10</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Mapster" Version="7.3.0" />
|
||||||
|
<PackageReference Include="Mapster.Core" Version="1.2.0" />
|
||||||
|
<PackageReference Include="MediatR" Version="12.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
|
||||||
|
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Target Name="Mapster">
|
||||||
|
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build -p:CopyLocalLockFileAssemblies=true" />
|
||||||
|
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore" />
|
||||||
|
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll" -n HamyanEdalat.Domain.Mappers -o Mappers" />
|
||||||
|
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll" -n HamyanEdalat.Domain.Mappers -o Mappers" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\HamyanEdalat.Common\HamyanEdalat.Common.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="HamyanEdalat.Common.Extensions" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models.Entity" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models.Mapper" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.LargDto" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.SmallDto" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Entities.Blogs" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Entities.StorageFiles" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Entities.Users" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Enums" />
|
||||||
|
<Using Include="Mapster" />
|
||||||
|
<Using Include="MediatR" />
|
||||||
|
<Using Include="Microsoft.AspNetCore.Identity" />
|
||||||
|
<Using Include="Microsoft.IdentityModel.Tokens" />
|
||||||
|
<Using Include="System.ComponentModel" />
|
||||||
|
<Using Include="System.ComponentModel.DataAnnotations" />
|
||||||
|
<Using Include="System.Diagnostics" />
|
||||||
|
<Using Include="System.Reflection" />
|
||||||
|
<Using Include="System.Runtime.CompilerServices" />
|
||||||
|
<Using Include="System.Security.Claims" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,93 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
using HamyanEdalat.Domain.Entities.Users;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Domain.Mappers
|
||||||
|
{
|
||||||
|
public static partial class ApplicationUserMapper
|
||||||
|
{
|
||||||
|
public static ApplicationUser AdaptToApplicationUser(this ApplicationUserSDto p1)
|
||||||
|
{
|
||||||
|
return p1 == null ? null : new ApplicationUser()
|
||||||
|
{
|
||||||
|
FirstName = p1.FirstName,
|
||||||
|
LastName = p1.LastName,
|
||||||
|
NationalId = p1.NationalId,
|
||||||
|
BirthDate = p1.BirthDate,
|
||||||
|
Gender = p1.Gender,
|
||||||
|
SignUpStatus = p1.SignUpStatus,
|
||||||
|
Id = p1.Id,
|
||||||
|
Email = p1.Email,
|
||||||
|
PhoneNumber = p1.PhoneNumber
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static ApplicationUser AdaptTo(this ApplicationUserSDto p2, ApplicationUser p3)
|
||||||
|
{
|
||||||
|
if (p2 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ApplicationUser result = p3 ?? new ApplicationUser();
|
||||||
|
|
||||||
|
result.FirstName = p2.FirstName;
|
||||||
|
result.LastName = p2.LastName;
|
||||||
|
result.NationalId = p2.NationalId;
|
||||||
|
result.BirthDate = p2.BirthDate;
|
||||||
|
result.Gender = p2.Gender;
|
||||||
|
result.SignUpStatus = p2.SignUpStatus;
|
||||||
|
result.Id = p2.Id;
|
||||||
|
result.Email = p2.Email;
|
||||||
|
result.PhoneNumber = p2.PhoneNumber;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static ApplicationUserSDto AdaptToSDto(this ApplicationUser p4)
|
||||||
|
{
|
||||||
|
return p4 == null ? null : new ApplicationUserSDto()
|
||||||
|
{
|
||||||
|
PhoneNumber = p4.PhoneNumber,
|
||||||
|
FirstName = p4.FirstName,
|
||||||
|
LastName = p4.LastName,
|
||||||
|
BirthDate = p4.BirthDate,
|
||||||
|
Gender = p4.Gender,
|
||||||
|
SignUpStatus = p4.SignUpStatus,
|
||||||
|
NationalId = p4.NationalId,
|
||||||
|
Email = p4.Email,
|
||||||
|
Id = p4.Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static ApplicationUserSDto AdaptTo(this ApplicationUser p5, ApplicationUserSDto p6)
|
||||||
|
{
|
||||||
|
if (p5 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ApplicationUserSDto result = p6 ?? new ApplicationUserSDto();
|
||||||
|
|
||||||
|
result.PhoneNumber = p5.PhoneNumber;
|
||||||
|
result.FirstName = p5.FirstName;
|
||||||
|
result.LastName = p5.LastName;
|
||||||
|
result.BirthDate = p5.BirthDate;
|
||||||
|
result.Gender = p5.Gender;
|
||||||
|
result.SignUpStatus = p5.SignUpStatus;
|
||||||
|
result.NationalId = p5.NationalId;
|
||||||
|
result.Email = p5.Email;
|
||||||
|
result.Id = p5.Id;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<ApplicationUser, ApplicationUserSDto>> ProjectToSDto => p7 => new ApplicationUserSDto()
|
||||||
|
{
|
||||||
|
PhoneNumber = p7.PhoneNumber,
|
||||||
|
FirstName = p7.FirstName,
|
||||||
|
LastName = p7.LastName,
|
||||||
|
BirthDate = p7.BirthDate,
|
||||||
|
Gender = p7.Gender,
|
||||||
|
SignUpStatus = p7.SignUpStatus,
|
||||||
|
NationalId = p7.NationalId,
|
||||||
|
Email = p7.Email,
|
||||||
|
Id = p7.Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,294 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using HamyanEdalat.Domain.Dtos.LargDto;
|
||||||
|
using HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
using HamyanEdalat.Domain.Entities.Blogs;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Domain.Mappers
|
||||||
|
{
|
||||||
|
public static partial class BlogCategoryMapper
|
||||||
|
{
|
||||||
|
public static BlogCategory AdaptToBlogCategory(this BlogCategoryLDto p1)
|
||||||
|
{
|
||||||
|
return p1 == null ? null : new BlogCategory()
|
||||||
|
{
|
||||||
|
Name = p1.Name,
|
||||||
|
Description = p1.Description,
|
||||||
|
Blogs = funcMain1(p1.Blogs),
|
||||||
|
Id = p1.Id,
|
||||||
|
CreatedAt = p1.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static BlogCategory AdaptTo(this BlogCategoryLDto p3, BlogCategory p4)
|
||||||
|
{
|
||||||
|
if (p3 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlogCategory result = p4 ?? new BlogCategory();
|
||||||
|
|
||||||
|
result.Name = p3.Name;
|
||||||
|
result.Description = p3.Description;
|
||||||
|
result.Blogs = funcMain2(p3.Blogs, result.Blogs);
|
||||||
|
result.Id = p3.Id;
|
||||||
|
result.CreatedAt = p3.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<BlogCategoryLDto, BlogCategory>> ProjectToBlogCategory => p7 => new BlogCategory()
|
||||||
|
{
|
||||||
|
Name = p7.Name,
|
||||||
|
Description = p7.Description,
|
||||||
|
Blogs = p7.Blogs.Select<BlogSDto, Blog>(p8 => new Blog()
|
||||||
|
{
|
||||||
|
Title = p8.Title,
|
||||||
|
Content = p8.Content,
|
||||||
|
Tags = p8.Tags,
|
||||||
|
ReadingTime = p8.ReadingTime,
|
||||||
|
Summery = p8.Summery,
|
||||||
|
IsSuggested = p8.IsSuggested,
|
||||||
|
CategoryId = p8.CategoryId,
|
||||||
|
Id = p8.Id,
|
||||||
|
CreatedAt = p8.CreatedAt
|
||||||
|
}).ToList<Blog>(),
|
||||||
|
Id = p7.Id,
|
||||||
|
CreatedAt = p7.CreatedAt
|
||||||
|
};
|
||||||
|
public static BlogCategoryLDto AdaptToLDto(this BlogCategory p9)
|
||||||
|
{
|
||||||
|
return p9 == null ? null : new BlogCategoryLDto()
|
||||||
|
{
|
||||||
|
Name = p9.Name,
|
||||||
|
Description = p9.Description,
|
||||||
|
Blogs = funcMain3(p9.Blogs),
|
||||||
|
Id = p9.Id,
|
||||||
|
CreatedAt = p9.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static BlogCategoryLDto AdaptTo(this BlogCategory p11, BlogCategoryLDto p12)
|
||||||
|
{
|
||||||
|
if (p11 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlogCategoryLDto result = p12 ?? new BlogCategoryLDto();
|
||||||
|
|
||||||
|
result.Name = p11.Name;
|
||||||
|
result.Description = p11.Description;
|
||||||
|
result.Blogs = funcMain4(p11.Blogs, result.Blogs);
|
||||||
|
result.Id = p11.Id;
|
||||||
|
result.CreatedAt = p11.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<BlogCategory, BlogCategoryLDto>> ProjectToLDto => p15 => new BlogCategoryLDto()
|
||||||
|
{
|
||||||
|
Name = p15.Name,
|
||||||
|
Description = p15.Description,
|
||||||
|
Blogs = p15.Blogs.Select<Blog, BlogSDto>(p16 => new BlogSDto()
|
||||||
|
{
|
||||||
|
Title = p16.Title,
|
||||||
|
Content = p16.Content,
|
||||||
|
Tags = p16.Tags,
|
||||||
|
ReadingTime = p16.ReadingTime,
|
||||||
|
Summery = p16.Summery,
|
||||||
|
IsSuggested = p16.IsSuggested,
|
||||||
|
CategoryId = p16.CategoryId,
|
||||||
|
CategoryName = p16.Category.Name,
|
||||||
|
Id = p16.Id,
|
||||||
|
CreatedAt = p16.CreatedAt
|
||||||
|
}).ToList<BlogSDto>(),
|
||||||
|
Id = p15.Id,
|
||||||
|
CreatedAt = p15.CreatedAt
|
||||||
|
};
|
||||||
|
public static BlogCategory AdaptToBlogCategory(this BlogCategorySDto p17)
|
||||||
|
{
|
||||||
|
return p17 == null ? null : new BlogCategory()
|
||||||
|
{
|
||||||
|
Name = p17.Name,
|
||||||
|
Description = p17.Description,
|
||||||
|
Id = p17.Id,
|
||||||
|
CreatedAt = p17.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static BlogCategory AdaptTo(this BlogCategorySDto p18, BlogCategory p19)
|
||||||
|
{
|
||||||
|
if (p18 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlogCategory result = p19 ?? new BlogCategory();
|
||||||
|
|
||||||
|
result.Name = p18.Name;
|
||||||
|
result.Description = p18.Description;
|
||||||
|
result.Id = p18.Id;
|
||||||
|
result.CreatedAt = p18.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static BlogCategorySDto AdaptToSDto(this BlogCategory p20)
|
||||||
|
{
|
||||||
|
return p20 == null ? null : new BlogCategorySDto()
|
||||||
|
{
|
||||||
|
Name = p20.Name,
|
||||||
|
Description = p20.Description,
|
||||||
|
Id = p20.Id,
|
||||||
|
CreatedAt = p20.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static BlogCategorySDto AdaptTo(this BlogCategory p21, BlogCategorySDto p22)
|
||||||
|
{
|
||||||
|
if (p21 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlogCategorySDto result = p22 ?? new BlogCategorySDto();
|
||||||
|
|
||||||
|
result.Name = p21.Name;
|
||||||
|
result.Description = p21.Description;
|
||||||
|
result.Id = p21.Id;
|
||||||
|
result.CreatedAt = p21.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<BlogCategory, BlogCategorySDto>> ProjectToSDto => p23 => new BlogCategorySDto()
|
||||||
|
{
|
||||||
|
Name = p23.Name,
|
||||||
|
Description = p23.Description,
|
||||||
|
Id = p23.Id,
|
||||||
|
CreatedAt = p23.CreatedAt
|
||||||
|
};
|
||||||
|
|
||||||
|
private static List<Blog> funcMain1(List<BlogSDto> p2)
|
||||||
|
{
|
||||||
|
if (p2 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Blog> result = new List<Blog>(p2.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p2.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
BlogSDto item = p2[i];
|
||||||
|
result.Add(item == null ? null : new Blog()
|
||||||
|
{
|
||||||
|
Title = item.Title,
|
||||||
|
Content = item.Content,
|
||||||
|
Tags = item.Tags,
|
||||||
|
ReadingTime = item.ReadingTime,
|
||||||
|
Summery = item.Summery,
|
||||||
|
IsSuggested = item.IsSuggested,
|
||||||
|
CategoryId = item.CategoryId,
|
||||||
|
Id = item.Id,
|
||||||
|
CreatedAt = item.CreatedAt
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Blog> funcMain2(List<BlogSDto> p5, List<Blog> p6)
|
||||||
|
{
|
||||||
|
if (p5 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Blog> result = new List<Blog>(p5.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p5.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
BlogSDto item = p5[i];
|
||||||
|
result.Add(item == null ? null : new Blog()
|
||||||
|
{
|
||||||
|
Title = item.Title,
|
||||||
|
Content = item.Content,
|
||||||
|
Tags = item.Tags,
|
||||||
|
ReadingTime = item.ReadingTime,
|
||||||
|
Summery = item.Summery,
|
||||||
|
IsSuggested = item.IsSuggested,
|
||||||
|
CategoryId = item.CategoryId,
|
||||||
|
Id = item.Id,
|
||||||
|
CreatedAt = item.CreatedAt
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<BlogSDto> funcMain3(List<Blog> p10)
|
||||||
|
{
|
||||||
|
if (p10 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<BlogSDto> result = new List<BlogSDto>(p10.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p10.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
Blog item = p10[i];
|
||||||
|
result.Add(item == null ? null : new BlogSDto()
|
||||||
|
{
|
||||||
|
Title = item.Title,
|
||||||
|
Content = item.Content,
|
||||||
|
Tags = item.Tags,
|
||||||
|
ReadingTime = item.ReadingTime,
|
||||||
|
Summery = item.Summery,
|
||||||
|
IsSuggested = item.IsSuggested,
|
||||||
|
CategoryId = item.CategoryId,
|
||||||
|
CategoryName = item.Category == null ? null : item.Category.Name,
|
||||||
|
Id = item.Id,
|
||||||
|
CreatedAt = item.CreatedAt
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<BlogSDto> funcMain4(List<Blog> p13, List<BlogSDto> p14)
|
||||||
|
{
|
||||||
|
if (p13 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<BlogSDto> result = new List<BlogSDto>(p13.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p13.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
Blog item = p13[i];
|
||||||
|
result.Add(item == null ? null : new BlogSDto()
|
||||||
|
{
|
||||||
|
Title = item.Title,
|
||||||
|
Content = item.Content,
|
||||||
|
Tags = item.Tags,
|
||||||
|
ReadingTime = item.ReadingTime,
|
||||||
|
Summery = item.Summery,
|
||||||
|
IsSuggested = item.IsSuggested,
|
||||||
|
CategoryId = item.CategoryId,
|
||||||
|
CategoryName = item.Category == null ? null : item.Category.Name,
|
||||||
|
Id = item.Id,
|
||||||
|
CreatedAt = item.CreatedAt
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,340 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using HamyanEdalat.Domain.Dtos.LargDto;
|
||||||
|
using HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
using HamyanEdalat.Domain.Entities.Blogs;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Domain.Mappers
|
||||||
|
{
|
||||||
|
public static partial class BlogMapper
|
||||||
|
{
|
||||||
|
public static Blog AdaptToBlog(this BlogLDto p1)
|
||||||
|
{
|
||||||
|
return p1 == null ? null : new Blog()
|
||||||
|
{
|
||||||
|
Title = p1.Title,
|
||||||
|
Content = p1.Content,
|
||||||
|
Tags = p1.Tags,
|
||||||
|
ReadingTime = p1.ReadingTime,
|
||||||
|
Summery = p1.Summery,
|
||||||
|
IsSuggested = p1.IsSuggested,
|
||||||
|
CategoryId = p1.CategoryId,
|
||||||
|
Files = funcMain1(p1.Files),
|
||||||
|
Id = p1.Id,
|
||||||
|
CreatedAt = p1.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static Blog AdaptTo(this BlogLDto p3, Blog p4)
|
||||||
|
{
|
||||||
|
if (p3 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Blog result = p4 ?? new Blog();
|
||||||
|
|
||||||
|
result.Title = p3.Title;
|
||||||
|
result.Content = p3.Content;
|
||||||
|
result.Tags = p3.Tags;
|
||||||
|
result.ReadingTime = p3.ReadingTime;
|
||||||
|
result.Summery = p3.Summery;
|
||||||
|
result.IsSuggested = p3.IsSuggested;
|
||||||
|
result.CategoryId = p3.CategoryId;
|
||||||
|
result.Files = funcMain2(p3.Files, result.Files);
|
||||||
|
result.Id = p3.Id;
|
||||||
|
result.CreatedAt = p3.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<BlogLDto, Blog>> ProjectToBlog => p7 => new Blog()
|
||||||
|
{
|
||||||
|
Title = p7.Title,
|
||||||
|
Content = p7.Content,
|
||||||
|
Tags = p7.Tags,
|
||||||
|
ReadingTime = p7.ReadingTime,
|
||||||
|
Summery = p7.Summery,
|
||||||
|
IsSuggested = p7.IsSuggested,
|
||||||
|
CategoryId = p7.CategoryId,
|
||||||
|
Files = p7.Files.Select<StorageFileSDto, BlogStorageFile>(p8 => new BlogStorageFile()
|
||||||
|
{
|
||||||
|
Name = p8.Name,
|
||||||
|
FileLocation = p8.FileLocation,
|
||||||
|
FileName = p8.FileName,
|
||||||
|
IsHeader = p8.IsHeader,
|
||||||
|
IsPrimary = p8.IsPrimary,
|
||||||
|
FileType = p8.FileType,
|
||||||
|
Id = p8.Id,
|
||||||
|
CreatedAt = p8.CreatedAt
|
||||||
|
}).ToList<BlogStorageFile>(),
|
||||||
|
Id = p7.Id,
|
||||||
|
CreatedAt = p7.CreatedAt
|
||||||
|
};
|
||||||
|
public static BlogLDto AdaptToLDto(this Blog p9)
|
||||||
|
{
|
||||||
|
return p9 == null ? null : new BlogLDto()
|
||||||
|
{
|
||||||
|
Title = p9.Title,
|
||||||
|
Content = p9.Content,
|
||||||
|
Tags = p9.Tags,
|
||||||
|
ReadingTime = p9.ReadingTime,
|
||||||
|
Summery = p9.Summery,
|
||||||
|
IsSuggested = p9.IsSuggested,
|
||||||
|
CategoryId = p9.CategoryId,
|
||||||
|
Files = funcMain3(p9.Files),
|
||||||
|
Id = p9.Id,
|
||||||
|
CreatedAt = p9.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static BlogLDto AdaptTo(this Blog p11, BlogLDto p12)
|
||||||
|
{
|
||||||
|
if (p11 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlogLDto result = p12 ?? new BlogLDto();
|
||||||
|
|
||||||
|
result.Title = p11.Title;
|
||||||
|
result.Content = p11.Content;
|
||||||
|
result.Tags = p11.Tags;
|
||||||
|
result.ReadingTime = p11.ReadingTime;
|
||||||
|
result.Summery = p11.Summery;
|
||||||
|
result.IsSuggested = p11.IsSuggested;
|
||||||
|
result.CategoryId = p11.CategoryId;
|
||||||
|
result.Files = funcMain4(p11.Files, result.Files);
|
||||||
|
result.Id = p11.Id;
|
||||||
|
result.CreatedAt = p11.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<Blog, BlogLDto>> ProjectToLDto => p15 => new BlogLDto()
|
||||||
|
{
|
||||||
|
Title = p15.Title,
|
||||||
|
Content = p15.Content,
|
||||||
|
Tags = p15.Tags,
|
||||||
|
ReadingTime = p15.ReadingTime,
|
||||||
|
Summery = p15.Summery,
|
||||||
|
IsSuggested = p15.IsSuggested,
|
||||||
|
CategoryId = p15.CategoryId,
|
||||||
|
Files = p15.Files.Select<BlogStorageFile, StorageFileSDto>(p16 => new StorageFileSDto()
|
||||||
|
{
|
||||||
|
Name = p16.Name,
|
||||||
|
FileLocation = p16.FileLocation,
|
||||||
|
FileName = p16.FileName,
|
||||||
|
IsHeader = p16.IsHeader,
|
||||||
|
IsPrimary = p16.IsPrimary,
|
||||||
|
FileType = p16.FileType,
|
||||||
|
Id = p16.Id
|
||||||
|
}).ToList<StorageFileSDto>(),
|
||||||
|
Id = p15.Id,
|
||||||
|
CreatedAt = p15.CreatedAt
|
||||||
|
};
|
||||||
|
public static Blog AdaptToBlog(this BlogSDto p17)
|
||||||
|
{
|
||||||
|
return p17 == null ? null : new Blog()
|
||||||
|
{
|
||||||
|
Title = p17.Title,
|
||||||
|
Content = p17.Content,
|
||||||
|
Tags = p17.Tags,
|
||||||
|
ReadingTime = p17.ReadingTime,
|
||||||
|
Summery = p17.Summery,
|
||||||
|
IsSuggested = p17.IsSuggested,
|
||||||
|
CategoryId = p17.CategoryId,
|
||||||
|
Id = p17.Id,
|
||||||
|
CreatedAt = p17.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static Blog AdaptTo(this BlogSDto p18, Blog p19)
|
||||||
|
{
|
||||||
|
if (p18 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Blog result = p19 ?? new Blog();
|
||||||
|
|
||||||
|
result.Title = p18.Title;
|
||||||
|
result.Content = p18.Content;
|
||||||
|
result.Tags = p18.Tags;
|
||||||
|
result.ReadingTime = p18.ReadingTime;
|
||||||
|
result.Summery = p18.Summery;
|
||||||
|
result.IsSuggested = p18.IsSuggested;
|
||||||
|
result.CategoryId = p18.CategoryId;
|
||||||
|
result.Id = p18.Id;
|
||||||
|
result.CreatedAt = p18.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static BlogSDto AdaptToSDto(this Blog p20)
|
||||||
|
{
|
||||||
|
return p20 == null ? null : new BlogSDto()
|
||||||
|
{
|
||||||
|
Title = p20.Title,
|
||||||
|
Content = p20.Content,
|
||||||
|
Tags = p20.Tags,
|
||||||
|
ReadingTime = p20.ReadingTime,
|
||||||
|
Summery = p20.Summery,
|
||||||
|
IsSuggested = p20.IsSuggested,
|
||||||
|
CategoryId = p20.CategoryId,
|
||||||
|
CategoryName = p20.Category == null ? null : p20.Category.Name,
|
||||||
|
Id = p20.Id,
|
||||||
|
CreatedAt = p20.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static BlogSDto AdaptTo(this Blog p21, BlogSDto p22)
|
||||||
|
{
|
||||||
|
if (p21 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlogSDto result = p22 ?? new BlogSDto();
|
||||||
|
|
||||||
|
result.Title = p21.Title;
|
||||||
|
result.Content = p21.Content;
|
||||||
|
result.Tags = p21.Tags;
|
||||||
|
result.ReadingTime = p21.ReadingTime;
|
||||||
|
result.Summery = p21.Summery;
|
||||||
|
result.IsSuggested = p21.IsSuggested;
|
||||||
|
result.CategoryId = p21.CategoryId;
|
||||||
|
result.CategoryName = p21.Category == null ? null : p21.Category.Name;
|
||||||
|
result.Id = p21.Id;
|
||||||
|
result.CreatedAt = p21.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<Blog, BlogSDto>> ProjectToSDto => p23 => new BlogSDto()
|
||||||
|
{
|
||||||
|
Title = p23.Title,
|
||||||
|
Content = p23.Content,
|
||||||
|
Tags = p23.Tags,
|
||||||
|
ReadingTime = p23.ReadingTime,
|
||||||
|
Summery = p23.Summery,
|
||||||
|
IsSuggested = p23.IsSuggested,
|
||||||
|
CategoryId = p23.CategoryId,
|
||||||
|
CategoryName = p23.Category.Name,
|
||||||
|
Id = p23.Id,
|
||||||
|
CreatedAt = p23.CreatedAt
|
||||||
|
};
|
||||||
|
|
||||||
|
private static List<BlogStorageFile> funcMain1(List<StorageFileSDto> p2)
|
||||||
|
{
|
||||||
|
if (p2 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<BlogStorageFile> result = new List<BlogStorageFile>(p2.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p2.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
StorageFileSDto item = p2[i];
|
||||||
|
result.Add(item == null ? null : new BlogStorageFile()
|
||||||
|
{
|
||||||
|
Name = item.Name,
|
||||||
|
FileLocation = item.FileLocation,
|
||||||
|
FileName = item.FileName,
|
||||||
|
IsHeader = item.IsHeader,
|
||||||
|
IsPrimary = item.IsPrimary,
|
||||||
|
FileType = item.FileType,
|
||||||
|
Id = item.Id,
|
||||||
|
CreatedAt = item.CreatedAt
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<BlogStorageFile> funcMain2(List<StorageFileSDto> p5, List<BlogStorageFile> p6)
|
||||||
|
{
|
||||||
|
if (p5 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<BlogStorageFile> result = new List<BlogStorageFile>(p5.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p5.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
StorageFileSDto item = p5[i];
|
||||||
|
result.Add(item == null ? null : new BlogStorageFile()
|
||||||
|
{
|
||||||
|
Name = item.Name,
|
||||||
|
FileLocation = item.FileLocation,
|
||||||
|
FileName = item.FileName,
|
||||||
|
IsHeader = item.IsHeader,
|
||||||
|
IsPrimary = item.IsPrimary,
|
||||||
|
FileType = item.FileType,
|
||||||
|
Id = item.Id,
|
||||||
|
CreatedAt = item.CreatedAt
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<StorageFileSDto> funcMain3(List<BlogStorageFile> p10)
|
||||||
|
{
|
||||||
|
if (p10 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<StorageFileSDto> result = new List<StorageFileSDto>(p10.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p10.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
BlogStorageFile item = p10[i];
|
||||||
|
result.Add(item == null ? null : new StorageFileSDto()
|
||||||
|
{
|
||||||
|
Name = item.Name,
|
||||||
|
FileLocation = item.FileLocation,
|
||||||
|
FileName = item.FileName,
|
||||||
|
IsHeader = item.IsHeader,
|
||||||
|
IsPrimary = item.IsPrimary,
|
||||||
|
FileType = item.FileType,
|
||||||
|
Id = item.Id
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<StorageFileSDto> funcMain4(List<BlogStorageFile> p13, List<StorageFileSDto> p14)
|
||||||
|
{
|
||||||
|
if (p13 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<StorageFileSDto> result = new List<StorageFileSDto>(p13.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p13.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
BlogStorageFile item = p13[i];
|
||||||
|
result.Add(item == null ? null : new StorageFileSDto()
|
||||||
|
{
|
||||||
|
Name = item.Name,
|
||||||
|
FileLocation = item.FileLocation,
|
||||||
|
FileName = item.FileName,
|
||||||
|
IsHeader = item.IsHeader,
|
||||||
|
IsPrimary = item.IsPrimary,
|
||||||
|
FileType = item.FileType,
|
||||||
|
Id = item.Id
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace HamyanEdalat.Domain.Mappers
|
||||||
|
{
|
||||||
|
public static partial class BlogStorageFileMapper
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using HamyanEdalat.Domain.Dtos.SmallDto;
|
||||||
|
using HamyanEdalat.Domain.Entities.StorageFiles;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Domain.Mappers
|
||||||
|
{
|
||||||
|
public static partial class StorageFileMapper
|
||||||
|
{
|
||||||
|
public static StorageFile AdaptToStorageFile(this StorageFileSDto p1)
|
||||||
|
{
|
||||||
|
return p1 == null ? null : new StorageFile()
|
||||||
|
{
|
||||||
|
Name = p1.Name,
|
||||||
|
FileLocation = p1.FileLocation,
|
||||||
|
FileName = p1.FileName,
|
||||||
|
IsHeader = p1.IsHeader,
|
||||||
|
IsPrimary = p1.IsPrimary,
|
||||||
|
FileType = p1.FileType,
|
||||||
|
Id = p1.Id,
|
||||||
|
CreatedAt = p1.CreatedAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static StorageFile AdaptTo(this StorageFileSDto p2, StorageFile p3)
|
||||||
|
{
|
||||||
|
if (p2 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StorageFile result = p3 ?? new StorageFile();
|
||||||
|
|
||||||
|
result.Name = p2.Name;
|
||||||
|
result.FileLocation = p2.FileLocation;
|
||||||
|
result.FileName = p2.FileName;
|
||||||
|
result.IsHeader = p2.IsHeader;
|
||||||
|
result.IsPrimary = p2.IsPrimary;
|
||||||
|
result.FileType = p2.FileType;
|
||||||
|
result.Id = p2.Id;
|
||||||
|
result.CreatedAt = p2.CreatedAt;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static StorageFileSDto AdaptToSDto(this StorageFile p4)
|
||||||
|
{
|
||||||
|
return p4 == null ? null : new StorageFileSDto()
|
||||||
|
{
|
||||||
|
Name = p4.Name,
|
||||||
|
FileLocation = p4.FileLocation,
|
||||||
|
FileName = p4.FileName,
|
||||||
|
IsHeader = p4.IsHeader,
|
||||||
|
IsPrimary = p4.IsPrimary,
|
||||||
|
FileType = p4.FileType,
|
||||||
|
Id = p4.Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static StorageFileSDto AdaptTo(this StorageFile p5, StorageFileSDto p6)
|
||||||
|
{
|
||||||
|
if (p5 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StorageFileSDto result = p6 ?? new StorageFileSDto();
|
||||||
|
|
||||||
|
result.Name = p5.Name;
|
||||||
|
result.FileLocation = p5.FileLocation;
|
||||||
|
result.FileName = p5.FileName;
|
||||||
|
result.IsHeader = p5.IsHeader;
|
||||||
|
result.IsPrimary = p5.IsPrimary;
|
||||||
|
result.FileType = p5.FileType;
|
||||||
|
result.Id = p5.Id;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<StorageFile, StorageFileSDto>> ProjectToSDto => p7 => new StorageFileSDto()
|
||||||
|
{
|
||||||
|
Name = p7.Name,
|
||||||
|
FileLocation = p7.FileLocation,
|
||||||
|
FileName = p7.FileName,
|
||||||
|
IsHeader = p7.IsHeader,
|
||||||
|
IsPrimary = p7.IsPrimary,
|
||||||
|
FileType = p7.FileType,
|
||||||
|
Id = p7.Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
namespace HamyanEdalat.Domain.Models.Claims;
|
||||||
|
|
||||||
|
public static class ApplicationClaims
|
||||||
|
{
|
||||||
|
|
||||||
|
public static ClaimDto ManageBlogs { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Title = "مدیریت بلاگ ها",
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ManageBlogs,
|
||||||
|
};
|
||||||
|
public static ClaimDto ViewBlogs { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Title = "مشاهده بلاگ ها",
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ViewBlogs,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static ClaimDto ManageBlogCategories { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Title = "مدیریت دسته بندی ها",
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ManageBlogCategories,
|
||||||
|
};
|
||||||
|
public static ClaimDto ViewBlogCategories { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Title = "مشاهده دسته بندی ها",
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ViewBlogCategories,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<ClaimDto> AllClaimDtos = new List<ClaimDto>
|
||||||
|
{
|
||||||
|
ManageBlogs,
|
||||||
|
ViewBlogs,
|
||||||
|
ManageBlogCategories,
|
||||||
|
ViewBlogCategories,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static List<Claim> AllClaims = new List<Claim>
|
||||||
|
{
|
||||||
|
ManageBlogs.GetClaim,
|
||||||
|
ViewBlogs.GetClaim,
|
||||||
|
ManageBlogCategories.GetClaim,
|
||||||
|
ViewBlogCategories.GetClaim,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static List<Claim> ManagerClaims = new List<Claim>
|
||||||
|
{
|
||||||
|
ManageBlogs.GetClaim,
|
||||||
|
ViewBlogs.GetClaim,
|
||||||
|
ManageBlogCategories.GetClaim,
|
||||||
|
ViewBlogCategories.GetClaim,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static List<Claim> CustomerClaims = new List<Claim>
|
||||||
|
{
|
||||||
|
ViewBlogs.GetClaim,
|
||||||
|
ViewBlogCategories.GetClaim,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace HamyanEdalat.Domain.Models.Claims;
|
||||||
|
|
||||||
|
public static class ApplicationPermission
|
||||||
|
{
|
||||||
|
public const string ManageBlogs = nameof(ManageBlogs);
|
||||||
|
public const string ViewBlogs = nameof(ManageBlogs);
|
||||||
|
|
||||||
|
public const string ManageBlogCategories = nameof(ManageBlogCategories);
|
||||||
|
public const string ViewBlogCategories = nameof(ViewBlogCategories);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace HamyanEdalat.Domain.Models.Claims;
|
||||||
|
public class ClaimDto : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public string Value { get; set; } = string.Empty;
|
||||||
|
public string Type { get; set; } = string.Empty;
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Detail { get; set; } = string.Empty;
|
||||||
|
public bool IsSelected { get; set; } = false;
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
public Claim GetClaim => new Claim(Type, Value);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Domain.Models.Claims
|
||||||
|
{
|
||||||
|
public static class CustomClaimType
|
||||||
|
{
|
||||||
|
public static string Permission { get; } = "Permission";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
namespace HamyanEdalat.Domain.Models.Settings;
|
||||||
|
|
||||||
|
public class SiteSettings
|
||||||
|
{
|
||||||
|
public JwtSettings JwtSettings { get; set; } = new JwtSettings();
|
||||||
|
public string BaseUrl { get; set; } = string.Empty;
|
||||||
|
public string AdminPanelBaseUrl { get; set; } = string.Empty;
|
||||||
|
public UserSetting RootUser { get; set; } = new UserSetting();
|
||||||
|
public UserSetting ManagerUser { get; set; } = new UserSetting();
|
||||||
|
public string KaveNegarApiKey { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class JwtSettings
|
||||||
|
{
|
||||||
|
public string SecretKey { get; set; } = string.Empty;
|
||||||
|
public string Issuer { get; set; } = string.Empty;
|
||||||
|
public string Audience { get; set; } = string.Empty;
|
||||||
|
public int ExpireAddDay { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserSetting
|
||||||
|
{
|
||||||
|
public string Username { get; set; } = string.Empty;
|
||||||
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public string Email { get; set; } = string.Empty;
|
||||||
|
public string RoleName { get; set; } = string.Empty;
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
public string Phone { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Marten" Version="7.0.0-beta.5" />
|
||||||
|
<PackageReference Include="AWSSDK.S3" Version="3.7.305.28" />
|
||||||
|
<PackageReference Include="Refit" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\HamyanEdalat.Core\HamyanEdalat.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Amazon.S3" />
|
||||||
|
<Using Include="Amazon.S3.Model" />
|
||||||
|
<Using Include="MediatR" />
|
||||||
|
<Using Include="Microsoft.Extensions.Hosting" />
|
||||||
|
<Using Include="Microsoft.Extensions.Logging" />
|
||||||
|
<Using Include="Microsoft.Extensions.Options" />
|
||||||
|
<Using Include="Refit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace HamyanEdalat.Infrastructure
|
||||||
|
{
|
||||||
|
public class InfrastructureConfig
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace HamyanEdalat.Repository.Abstracts;
|
||||||
|
|
||||||
|
public interface ICurrentUserService : IScopedDependency
|
||||||
|
{
|
||||||
|
string? UserId { get; }
|
||||||
|
string? RoleName { get; }
|
||||||
|
string? UserName { get; }
|
||||||
|
string? DeviceId { get; }
|
||||||
|
bool IsAuthorized { get; }
|
||||||
|
public List<string>? Permissions { get; }
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using ValidationException = HamyanEdalat.Common.Models.Exception.ValidationException;
|
||||||
|
|
||||||
|
namespace HamyanEdalat.Repository.Behaviors;
|
||||||
|
|
||||||
|
public class ValidationBehavior <TRequest,TResponse> : IPipelineBehavior<TRequest,TResponse> where TRequest : notnull
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IValidator<TRequest>> _validators;
|
||||||
|
|
||||||
|
public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
|
||||||
|
{
|
||||||
|
_validators = validators;
|
||||||
|
}
|
||||||
|
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var context = new ValidationContext<TRequest>(request);
|
||||||
|
List<ValidationError> errors = new List<ValidationError>();
|
||||||
|
foreach (IValidator<TRequest> validator in _validators)
|
||||||
|
{
|
||||||
|
var result = await validator.ValidateAsync(context, cancellationToken);
|
||||||
|
if (!result.IsValid)
|
||||||
|
errors.AddRange(result.Errors.Select(v => new ValidationError(v.PropertyName, v.ErrorMessage)).Distinct());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.Any())
|
||||||
|
{
|
||||||
|
throw new ValidationException(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var response = await next();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
namespace HamyanEdalat.Repository.Extensions;
|
||||||
|
|
||||||
|
public class DbContextOptionCustomExtensionsInfo : DbContextOptionsExtensionInfo
|
||||||
|
{
|
||||||
|
public DbContextOptionCustomExtensionsInfo(IDbContextOptionsExtension extension) : base(extension)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsDatabaseProvider { get; }
|
||||||
|
public override string LogFragment { get; } = string.Empty;
|
||||||
|
|
||||||
|
public override int GetServiceProviderHashCode()
|
||||||
|
{
|
||||||
|
return Extension.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DbContextOptionCustomExtensions : IDbContextOptionsExtension
|
||||||
|
{
|
||||||
|
public DbContextOptionCustomExtensions()
|
||||||
|
{
|
||||||
|
Info = new DbContextOptionCustomExtensionsInfo(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Assembly ProjectAssembly { get; set; } = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
public void ApplyServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Validate(IDbContextOptions options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbContextOptionsExtensionInfo Info { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ApplicationContextExtensions
|
||||||
|
{
|
||||||
|
public static DbContextOptionsBuilder UseProjectAssembly(this DbContextOptionsBuilder contextOptions,
|
||||||
|
Assembly projectAssembly)
|
||||||
|
{
|
||||||
|
var extension = new DbContextOptionCustomExtensions
|
||||||
|
{
|
||||||
|
ProjectAssembly = projectAssembly
|
||||||
|
};
|
||||||
|
((IDbContextOptionsBuilderInfrastructure)contextOptions).AddOrUpdateExtension(extension);
|
||||||
|
return contextOptions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
namespace HamyanEdalat.Repository.Extensions;
|
||||||
|
|
||||||
|
public class ModelBuilderQueryFilter
|
||||||
|
{
|
||||||
|
public void AddQueryFilterToModelBuilder(ModelBuilder modelBuilder, Type type)
|
||||||
|
{
|
||||||
|
var method = GetType().GetMethod("RegisterQueryFilter").MakeGenericMethod(type);
|
||||||
|
method.Invoke(this, new object[] { modelBuilder });
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterQueryFilter<TQFilter>(ModelBuilder modelBuilder) where TQFilter : ApiEntity
|
||||||
|
{
|
||||||
|
var tt = typeof(TQFilter);
|
||||||
|
if (tt.BaseType == typeof(ApiEntity))
|
||||||
|
modelBuilder.Entity<TQFilter>().HasQueryFilter(e => e.IsRemoved == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ModelBuilderExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Singularizin table name like Posts to Post or People to Person
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
public static void AddSingularizingTableNameConvention(this ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
var pluralizer = new Pluralizer();
|
||||||
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
|
{
|
||||||
|
var tableName = entityType.GetTableName();
|
||||||
|
entityType.SetTableName(pluralizer.Singularize(tableName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set NEWSEQUENTIALID() sql function for all columns named "Id"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
/// <param name="mustBeIdentity">Set to true if you want only "Identity" guid fields that named "Id"</param>
|
||||||
|
public static void AddSequentialGuidForIdConvention(this ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
|
{
|
||||||
|
var property = entityType.GetProperties()
|
||||||
|
.Where(p => p.Name.Contains("Id", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.ToArray();
|
||||||
|
foreach (var mutableProperty in property)
|
||||||
|
modelBuilder.AddDefaultValueSqlConvention(mutableProperty?.Name, typeof(Guid), "gen_random_uuid()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set DefaultValueSql for sepecific property name and type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
/// <param name="propertyName">Name of property wants to set DefaultValueSql for</param>
|
||||||
|
/// <param name="propertyType">Type of property wants to set DefaultValueSql for </param>
|
||||||
|
/// <param name="defaultValueSql">DefaultValueSql like "NEWSEQUENTIALID()"</param>
|
||||||
|
public static void AddDefaultValueSqlConvention(this ModelBuilder modelBuilder, string propertyName,
|
||||||
|
Type propertyType, string defaultValueSql)
|
||||||
|
{
|
||||||
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
|
{
|
||||||
|
var property = entityType.GetProperties()
|
||||||
|
.SingleOrDefault(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (property != null && property.ClrType == propertyType)
|
||||||
|
property.SetDefaultValueSql(defaultValueSql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set DeleteBehavior.Restrict by default for relations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
public static void AddRestrictDeleteBehaviorConvention(this ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
var cascadeFKs = modelBuilder.Model.GetEntityTypes()
|
||||||
|
.SelectMany(t => t.GetForeignKeys())
|
||||||
|
.Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade);
|
||||||
|
foreach (var fk in cascadeFKs)
|
||||||
|
{
|
||||||
|
fk.DeleteBehavior = DeleteBehavior.Restrict;
|
||||||
|
fk.IsRequired = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dynamicaly load all IEntityTypeConfiguration with Reflection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
/// <param name="assemblies">Assemblies contains Entities</param>
|
||||||
|
public static void RegisterEntityTypeConfiguration(this ModelBuilder modelBuilder, params Assembly[] assemblies)
|
||||||
|
{
|
||||||
|
var applyGenericMethod = typeof(ModelBuilder)
|
||||||
|
.GetMethods()
|
||||||
|
.First(m => m.Name == nameof(ModelBuilder.ApplyConfiguration));
|
||||||
|
|
||||||
|
var types = assemblies.SelectMany(a => a.GetExportedTypes())
|
||||||
|
.Where(c => c.IsClass && !c.IsAbstract && c.IsPublic);
|
||||||
|
|
||||||
|
foreach (var type in types)
|
||||||
|
foreach (var iface in type.GetInterfaces())
|
||||||
|
if (iface.IsConstructedGenericType &&
|
||||||
|
iface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))
|
||||||
|
{
|
||||||
|
var applyConcreteMethod = applyGenericMethod.MakeGenericMethod(iface.GenericTypeArguments[0]);
|
||||||
|
applyConcreteMethod.Invoke(modelBuilder, new[] { Activator.CreateInstance(type) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pluralizing table name like Post to Posts or Person to People
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
public static void AddPluralizingTableNameConvention(this ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
var pluralizer = new Pluralizer();
|
||||||
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
|
if (entityType.BaseType == null)
|
||||||
|
{
|
||||||
|
var tableName = entityType.GetTableName();
|
||||||
|
entityType.SetTableName(pluralizer.Pluralize(tableName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dynamicaly register all Entities that inherit from specific BaseType
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
/// <param name="baseType">Base type that Entities inherit from this</param>
|
||||||
|
/// <param name="assemblies">Assemblies contains Entities</param>
|
||||||
|
public static void RegisterAllEntities<BaseType>(this ModelBuilder modelBuilder,
|
||||||
|
ILogger<ApplicationContext> _logger, params Assembly[] assemblies) where BaseType : ApiEntity
|
||||||
|
{
|
||||||
|
var types = assemblies.SelectMany(a => a.GetExportedTypes())
|
||||||
|
.Where(c => c.IsClass && !c.IsAbstract && c.IsPublic && typeof(BaseType)
|
||||||
|
.IsAssignableFrom(c));
|
||||||
|
var builderQueryFilter = new ModelBuilderQueryFilter();
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity(type);
|
||||||
|
builderQueryFilter.AddQueryFilterToModelBuilder(modelBuilder, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dynamicaly register all Entities that inherit from specific BaseType
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelBuilder"></param>
|
||||||
|
/// <param name="baseType">Base type that Entities inherit from this</param>
|
||||||
|
/// <param name="assemblies">Assemblies contains Entities</param>
|
||||||
|
public static void RegisterAllEntitiesV02<BaseType>(this ModelBuilder builder, ILogger<ApplicationContext> _logger, params Assembly[] assemblies) where BaseType : ApiEntity
|
||||||
|
{
|
||||||
|
var types = assemblies.SelectMany(a => a.GetExportedTypes())
|
||||||
|
.Where(c => c.IsClass && !c.IsAbstract && c.IsPublic && typeof(BaseType)
|
||||||
|
.IsAssignableFrom(c));
|
||||||
|
var builderQueryFilter = new ModelBuilderQueryFilter();
|
||||||
|
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
var stopwatch = new Stopwatch();
|
||||||
|
stopwatch.Start();
|
||||||
|
// On Model Creating
|
||||||
|
var onModelCreatingMethod =
|
||||||
|
type.GetMethods().FirstOrDefault(x => x.Name == "OnModelCreating");
|
||||||
|
|
||||||
|
if (onModelCreatingMethod != null)
|
||||||
|
onModelCreatingMethod.Invoke(type, new object[] { builder });
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// On Base Model Creating
|
||||||
|
if (type.BaseType == null || type.BaseType != typeof(BaseType)) continue;
|
||||||
|
|
||||||
|
var baseOnModelCreatingMethod = type.BaseType.GetMethods()
|
||||||
|
.FirstOrDefault(x => x.Name == "OnModelCreating");
|
||||||
|
|
||||||
|
if (baseOnModelCreatingMethod == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
baseOnModelCreatingMethod.Invoke(typeof(BaseType), new object[] { builder });
|
||||||
|
}
|
||||||
|
|
||||||
|
builderQueryFilter.AddQueryFilterToModelBuilder(builder, type);
|
||||||
|
stopwatch.Stop();
|
||||||
|
_logger.LogInformation($"MODEL BUILDER {type.Name} In : {stopwatch.ElapsedMilliseconds}ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MediatR" Version="12.2.0" />
|
||||||
|
<PackageReference Include="FluentValidation" Version="11.9.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Pluralize.NET" Version="1.0.2" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.2" />
|
||||||
|
<PackageReference Include="StackExchange.Redis" Version="2.7.20" />
|
||||||
|
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="10.2.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\HamyanEdalat.Domain\HamyanEdalat.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="FluentValidation" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Extensions" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models.Api" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models.Entity" />
|
||||||
|
<Using Include="HamyanEdalat.Common.Models.Exception" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.CommandQueries.Commands" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.CommandQueries.Queries" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.LargDto" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.ResponseDtos" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Dtos.SmallDto" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Entities.Blogs" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Entities.Users" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Mappers" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Models.Claims" />
|
||||||
|
<Using Include="HamyanEdalat.Domain.Models.Settings" />
|
||||||
|
<Using Include="HamyanEdalat.Repository.Abstracts" />
|
||||||
|
<Using Include="HamyanEdalat.Repository.Models" />
|
||||||
|
<Using Include="HamyanEdalat.Repository.Repositories.Base.Contracts" />
|
||||||
|
<Using Include="HamyanEdalat.Repository.Services.Abstracts" />
|
||||||
|
<Using Include="Mapster" />
|
||||||
|
<Using Include="MediatR" />
|
||||||
|
<Using Include="Microsoft.AspNetCore.Builder" />
|
||||||
|
<Using Include="Microsoft.AspNetCore.Identity" />
|
||||||
|
<Using Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
|
||||||
|
<Using Include="Microsoft.EntityFrameworkCore" />
|
||||||
|
<Using Include="Microsoft.EntityFrameworkCore.ChangeTracking" />
|
||||||
|
<Using Include="Microsoft.EntityFrameworkCore.Infrastructure" />
|
||||||
|
<Using Include="Microsoft.EntityFrameworkCore.Storage" />
|
||||||
|
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
|
<Using Include="Microsoft.Extensions.Logging" />
|
||||||
|
<Using Include="Microsoft.Extensions.Options" />
|
||||||
|
<Using Include="Pluralize.NET" />
|
||||||
|
<Using Include="System.Diagnostics" />
|
||||||
|
<Using Include="System.Reflection" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace HamyanEdalat.Repository.Handlers.BlogCategories;
|
||||||
|
|
||||||
|
public class CreateBlogCategoryCommandHandler : IRequestHandler<CreateBlogCategoryCommand,bool>
|
||||||
|
{
|
||||||
|
private readonly IRepositoryWrapper _repositoryWrapper;
|
||||||
|
|
||||||
|
public CreateBlogCategoryCommandHandler(IRepositoryWrapper repositoryWrapper)
|
||||||
|
{
|
||||||
|
_repositoryWrapper = repositoryWrapper;
|
||||||
|
}
|
||||||
|
public async Task<bool> Handle(CreateBlogCategoryCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var ent = BlogCategory.Create(request.Name, request.Description);
|
||||||
|
_repositoryWrapper.SetRepository<BlogCategory>()
|
||||||
|
.Add(ent);
|
||||||
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace HamyanEdalat.Repository.Handlers.BlogCategories;
|
||||||
|
|
||||||
|
public class DeleteBlogCategoryCommandHandler : IRequestHandler<DeleteBlogCategoryCommand,bool>
|
||||||
|
{
|
||||||
|
private readonly IRepositoryWrapper _repositoryWrapper;
|
||||||
|
|
||||||
|
public DeleteBlogCategoryCommandHandler(IRepositoryWrapper repositoryWrapper)
|
||||||
|
{
|
||||||
|
_repositoryWrapper = repositoryWrapper;
|
||||||
|
}
|
||||||
|
public async Task<bool> Handle(DeleteBlogCategoryCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var ent = await _repositoryWrapper.SetRepository<BlogCategory>()
|
||||||
|
.TableNoTracking
|
||||||
|
.FirstOrDefaultAsync(bc => bc.Id == request.Id, cancellationToken);
|
||||||
|
if (ent == null)
|
||||||
|
throw new AppException("Blog Category not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
_repositoryWrapper.SetRepository<BlogCategory>()
|
||||||
|
.Delete(ent);
|
||||||
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue