add project layers
parent
35f591ed23
commit
3f80e1f6f1
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"mapster.tool": {
|
||||
"version": "8.4.0",
|
||||
"commands": [
|
||||
"dotnet-mapster"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"PostgresServer": "User ID=postgres;Password=root;Host=localhost;Port=5432;Database=iGarsonDB;",
|
||||
"Postgres": "Host=pg-0;Username=vesmmehAgent;Password=g05CTjK358Vx3Eoc9satsWyVwo+15UmsA2dnCrZRUYh1pLTe;Database=NetinaShopDB;Application Name=NetinaShopApi",
|
||||
"MartenDB": "Host=pg-0;Username=vesmmehAgent;Password=g05CTjK358Vx3Eoc9satsWyVwo+15UmsA2dnCrZRUYh1pLTe;Database=NetinaShopMartenDB;"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "None",
|
||||
"Microsoft.Hosting.Lifetime": "Information",
|
||||
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||
}
|
||||
},
|
||||
"SiteSettings": {
|
||||
"BaseUrl": "http://192.168.88.251:32770",
|
||||
"AdminPanelBaseUrl": "https://admin.vesmook.com",
|
||||
"KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B",
|
||||
"UserSetting": {
|
||||
"Username": "09214802813",
|
||||
"Email": "avvampier@gmail.com",
|
||||
"Password": "55k6bXxIWT5M487L",
|
||||
"Phone": "09214802813",
|
||||
"RoleName": "RootAdmin",
|
||||
"FirstName": "همه کاره",
|
||||
"LastName": "سیستم"
|
||||
},
|
||||
"ManagerUser": {
|
||||
"Username": "hivakil",
|
||||
"Email": "info@hivakil.io",
|
||||
"Password": "tiyiH+TOMgV4jo+9",
|
||||
"Phone": "09211111111",
|
||||
"RoleName": "Manager",
|
||||
"FirstName": "ادمین",
|
||||
"LastName": "سایت"
|
||||
},
|
||||
"JwtSettings": {
|
||||
"SecretKey": "YAEMAMZAMAN_KHODET_NEGAHDAR_IN_KEY_BASH_lF49ZpaQfER8Gx0A6q3uzC0QZ0jx9byNIV6z7nGoMBM2ewAUgsqM8eLSiRJM1+uA==_YA_HUSEIN_SEYED_SHOHADA_BE_OMID_KHODET_4xFN/ld8qJKNU8rrKfRdy4Fmni2KrWquTDBjtSR6T8fnUT+ii6crtL8pSO8KnRhC_YA_ALI_MADADI_kxT9SwJ1nVeTt8ejij2FOSpqkRNwJVV9nQ4zGsrvaYM=",
|
||||
"Issuer": "HiVakil",
|
||||
"Audience": "HiVakil",
|
||||
"ExpireAddDay": "15"
|
||||
}
|
||||
},
|
||||
"IpRateLimiting": {
|
||||
"EnableEndpointRateLimiting": false,
|
||||
"StackBlockedRequests": false,
|
||||
"RealIpHeader": "X-Real-IP",
|
||||
"ClientIdHeader": "X-ClientId",
|
||||
"HttpStatusCode": 429,
|
||||
"IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ],
|
||||
"EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],
|
||||
"ClientWhitelist": [ "dev-id-1", "dev-id-2" ],
|
||||
"GeneralRules": [
|
||||
{
|
||||
"Endpoint": "*",
|
||||
"Period": "1m",
|
||||
"Limit": 60
|
||||
},
|
||||
{
|
||||
"Endpoint": "*",
|
||||
"Period": "15m",
|
||||
"Limit": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"PostgresServer": "User ID=postgres;Password=root;Host=localhost;Port=5432;Database=iGarsonDB;",
|
||||
"Postgres": "Host=pg-0,pg-1;Username=igarsonAgent;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=NetinaShopDB;Load Balance Hosts=true;Target Session Attributes=primary;Application Name=iGLS",
|
||||
"MartenDB": "Host=pg-0,pg-1;Username=igarsonAgent;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=NetinaShopMartenDB;"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "None",
|
||||
"Microsoft.Hosting.Lifetime": "Information",
|
||||
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||
}
|
||||
},
|
||||
"SiteSettings": {
|
||||
"BaseUrl": "http://192.168.88.251:32770",
|
||||
"AdminPanelBaseUrl": "https://admin.vesmook.com",
|
||||
"KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B",
|
||||
"StorageSetting": {
|
||||
"AccessKey": "",
|
||||
"SecretKey": ""
|
||||
},
|
||||
"UserSetting": {
|
||||
"Username": "09214802813",
|
||||
"Email": "avvampier@gmail.com",
|
||||
"Password": "55k6bXxIWT5M487L",
|
||||
"Phone": "09214802813",
|
||||
"RoleName": "RootAdmin",
|
||||
"FirstName": "همه کاره",
|
||||
"LastName": "سیستم"
|
||||
},
|
||||
"ManagerUser": {
|
||||
"Username": "hivakil",
|
||||
"Email": "info@hivakil.io",
|
||||
"Password": "tiyiH+TOMgV4jo+9",
|
||||
"Phone": "09211111111",
|
||||
"RoleName": "Manager",
|
||||
"FirstName": "ادمین",
|
||||
"LastName": "سایت"
|
||||
},
|
||||
"JwtSettings": {
|
||||
"SecretKey": "YAEMAMZAMAN_KHODET_NEGAHDAR_IN_KEY_BASH_lF49ZpaQfER8Gx0A6q3uzC0QZ0jx9byNIV6z7nGoMBM2ewAUgsqM8eLSiRJM1+uA==_YA_HUSEIN_SEYED_SHOHADA_BE_OMID_KHODET_4xFN/ld8qJKNU8rrKfRdy4Fmni2KrWquTDBjtSR6T8fnUT+ii6crtL8pSO8KnRhC_YA_ALI_MADADI_kxT9SwJ1nVeTt8ejij2FOSpqkRNwJVV9nQ4zGsrvaYM=",
|
||||
"Issuer": "HiVakil",
|
||||
"Audience": "HiVakil",
|
||||
"ExpireAddDay": "15"
|
||||
}
|
||||
},
|
||||
"IpRateLimiting": {
|
||||
"EnableEndpointRateLimiting": false,
|
||||
"StackBlockedRequests": false,
|
||||
"RealIpHeader": "X-Real-IP",
|
||||
"ClientIdHeader": "X-ClientId",
|
||||
"HttpStatusCode": 429,
|
||||
"IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ],
|
||||
"EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],
|
||||
"ClientWhitelist": [ "dev-id-1", "dev-id-2" ],
|
||||
"GeneralRules": [
|
||||
{
|
||||
"Endpoint": "*",
|
||||
"Period": "1m",
|
||||
"Limit": 60
|
||||
},
|
||||
{
|
||||
"Endpoint": "*",
|
||||
"Period": "15m",
|
||||
"Limit": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -4,5 +4,6 @@
|
|||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -9,9 +9,9 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
namespace HiVakil.Common
|
||||
{
|
||||
public class CommonConfig
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace HiVakil.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 HiVakil.Common.Extensions;
|
||||
|
||||
public static class BoolExtensions
|
||||
{
|
||||
public static string ToPersianString(this bool value)
|
||||
{
|
||||
return value ? "بله" : "خیر";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using HiVakil.Common.Models.Entity;
|
||||
|
||||
namespace HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.Common.Models.Api
|
||||
{
|
||||
public class AppSettings
|
||||
{
|
||||
public bool Seeded { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
namespace HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.Common.Models.Api;
|
||||
|
||||
namespace HiVakil.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 HiVakil.Common.Models.Api;
|
||||
|
||||
namespace HiVakil.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 HiVakil.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 HiVakil.Common.Models
|
||||
{
|
||||
public interface IScopedDependency
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
using System.ComponentModel;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.CompilerServices;
|
||||
using HiVakil.Common.Models.Exception;
|
||||
|
||||
namespace HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.Core.Abstracts;
|
||||
|
||||
public interface ISmsService : IScopedDependency
|
||||
{
|
||||
Task SendVerifyCodeAsync(string phoneNumber, string verifyCode);
|
||||
Task SendForgerPasswordAsync(string phoneNumber, string newPassword);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace HiVakil.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 HiVakil.Core.Abstracts;
|
||||
|
||||
public interface IUploadFileService : IScopedDependency
|
||||
{
|
||||
Task<FileUploadResponse> UploadImageAsync(FileUploadRequest uploadRequest);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace HiVakil.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,130 @@
|
|||
namespace HiVakil.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 HiVakil.Core
|
||||
{
|
||||
public class CoreConfig
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
namespace HiVakil.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 HiVakil.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 HiVakil.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 HiVakil.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,59 @@
|
|||
<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="..\HiVakil.Repository\HiVakil.Repository.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="HiVakil.Common.Extensions" />
|
||||
<Using Include="HiVakil.Common.Models" />
|
||||
<Using Include="HiVakil.Common.Models.Api" />
|
||||
<Using Include="HiVakil.Common.Models.Exception" />
|
||||
<Using Include="HiVakil.Core.Abstracts" />
|
||||
<Using Include="HiVakil.Core.BaseServices.Abstracts" />
|
||||
<Using Include="HiVakil.Core.CoreServices.Abstracts" />
|
||||
<Using Include="HiVakil.Core.EntityServices.Abstracts" />
|
||||
<Using Include="HiVakil.Domain.Dtos.RequestDto" />
|
||||
<Using Include="HiVakil.Domain.Dtos.ResponseDto" />
|
||||
<Using Include="HiVakil.Domain.Dtos.SmallDtos" />
|
||||
<Using Include="HiVakil.Domain.Entities.Users" />
|
||||
<Using Include="HiVakil.Domain.Enums" />
|
||||
<Using Include="HiVakil.Domain.Mappers" />
|
||||
<Using Include="HiVakil.Domain.Models.Claims" />
|
||||
<Using Include="HiVakil.Domain.Models.Settings" />
|
||||
<Using Include="HiVakil.Repository.Abstracts" />
|
||||
<Using Include="HiVakil.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="NetinaShop.Domain.Dtos.RequestDtos" />
|
||||
<Using Include="Newtonsoft.Json" />
|
||||
<Using Include="System.IdentityModel.Tokens.Jwt" />
|
||||
<Using Include="System.Security.Claims" />
|
||||
<Using Include="System.Text" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,126 @@
|
|||
namespace HiVakil.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,18 @@
|
|||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
|
||||
namespace HiVakil.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,7 @@
|
|||
namespace HiVakil.Domain
|
||||
{
|
||||
public class DomainConfig
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace NetinaShop.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 HiVakil.Domain.Dtos.RequestDto;
|
||||
|
||||
public class SignUpRequestDto
|
||||
{
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
namespace HiVakil.Domain.Dtos.RequestDto;
|
||||
|
||||
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,8 @@
|
|||
namespace HiVakil.Domain.Dtos.ResponseDto;
|
||||
|
||||
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 HiVakil.Domain.Dtos.ResponseDto;
|
||||
|
||||
public class VerifyCodeResponseDto
|
||||
{
|
||||
public SignUpStatus SignUpStatus { get; set; }
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
namespace HiVakil.Domain.Dtos.SmallDtos;
|
||||
|
||||
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,24 @@
|
|||
namespace HiVakil.Domain.Dtos.SmallDtos;
|
||||
|
||||
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,28 @@
|
|||
namespace HiVakil.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 HiVakil.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,18 @@
|
|||
using HiVakil.Domain.Enums;
|
||||
|
||||
namespace HiVakil.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 DateTime BirthDate { get; set; }
|
||||
public Gender Gender { get; set; }
|
||||
public SignUpStatus SignUpStatus { get; set; }
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace HiVakil.Domain.Enums;
|
||||
|
||||
public enum Gender
|
||||
{
|
||||
[Display(Name = "مرد")]
|
||||
Male,
|
||||
[Display(Name = "بانو")]
|
||||
Female
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace HiVakil.Domain.Enums;
|
||||
|
||||
public enum SignUpStatus
|
||||
{
|
||||
StartSignOn = 0,
|
||||
PhoneNumberVerified = 1,
|
||||
SignUpCompleted = 10,
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace HiVakil.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,78 @@
|
|||
<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 HiVakil.Domain.Mappers -o Mappers" />
|
||||
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll" -n HiVakil.Domain.Mappers -o Mappers" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\HiVakil.Common\HiVakil.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="HiVakil.Common.Extensions" />
|
||||
<Using Include="HiVakil.Common.Models.Entity" />
|
||||
<Using Include="HiVakil.Common.Models.Mapper" />
|
||||
<Using Include="HiVakil.Domain.Dtos.SmallDtos" />
|
||||
<Using Include="HiVakil.Domain.Entities.StorageFiles" />
|
||||
<Using Include="HiVakil.Domain.Entities.Users" />
|
||||
<Using Include="HiVakil.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>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Dtos\ResponseDto\" />
|
||||
<Folder Include="Dtos\SmallDtos\" />
|
||||
<Folder Include="Entities\StorageFiles\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using HiVakil.Domain.Dtos.SmallDtos;
|
||||
using HiVakil.Domain.Entities.Users;
|
||||
|
||||
namespace HiVakil.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,85 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using HiVakil.Domain.Dtos.SmallDtos;
|
||||
using HiVakil.Domain.Entities.StorageFiles;
|
||||
|
||||
namespace HiVakil.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,253 @@
|
|||
namespace HiVakil.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 ManageBrands { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت برند ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageBrands,
|
||||
};
|
||||
public static ClaimDto ViewBrands { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده برند ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewBrands,
|
||||
};
|
||||
|
||||
public static ClaimDto ManageCategories { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت دسته بندی ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageCategories,
|
||||
};
|
||||
public static ClaimDto ViewCategories { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده دسته بندی ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewCategories,
|
||||
};
|
||||
|
||||
public static ClaimDto ManageDiscounts { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت تخفیف ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageDiscounts,
|
||||
};
|
||||
public static ClaimDto ViewDiscounts { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده تخفیف ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewDiscounts,
|
||||
};
|
||||
|
||||
public static ClaimDto ManageOrders { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت فروش ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageOrders,
|
||||
};
|
||||
public static ClaimDto ViewAllOrders { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده فروش ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewAllOrders,
|
||||
};
|
||||
public static ClaimDto ViewMineOrders { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده فروش های خود",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewMineOrders,
|
||||
};
|
||||
public static ClaimDto CreateOrder { get; } = new ClaimDto
|
||||
{
|
||||
Title = "ثبت سفارش",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.CreateOrder,
|
||||
};
|
||||
|
||||
public static ClaimDto ManageProducts { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت محصولات",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageProducts,
|
||||
};
|
||||
public static ClaimDto ViewProducts { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده محصولات",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewProducts,
|
||||
};
|
||||
|
||||
public static ClaimDto ManageReview { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت کامنت ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageReview,
|
||||
};
|
||||
public static ClaimDto ViewAllReviews { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده کامنت ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewAllReviews,
|
||||
};
|
||||
public static ClaimDto ViewMineReviews { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده کامنت های خود",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewMineReviews,
|
||||
};
|
||||
public static ClaimDto AddReview { get; } = new ClaimDto
|
||||
{
|
||||
Title = "ثبت کامنت جدید",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.AddReview,
|
||||
};
|
||||
public static ClaimDto ConfirmReview { get; } = new ClaimDto
|
||||
{
|
||||
Title = "تائید کامنت ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ConfirmReview,
|
||||
};
|
||||
|
||||
public static ClaimDto ViewWarehouses { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده انبار ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewWarehouses,
|
||||
};
|
||||
public static ClaimDto ManageWarehouses { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت انبار ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageWarehouses,
|
||||
};
|
||||
|
||||
public static ClaimDto ViewShipping { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده روش های ارسال",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewShipping,
|
||||
};
|
||||
public static ClaimDto ManageShipping { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت روش های ارسال",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageShipping,
|
||||
};
|
||||
|
||||
public static ClaimDto ManageUsers { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت کاربران",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageUsers,
|
||||
};
|
||||
public static ClaimDto ViewUsers { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده کاربران",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewUsers,
|
||||
};
|
||||
|
||||
public static ClaimDto ManageFiles { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مدیریت فایل ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ManageFiles,
|
||||
};
|
||||
public static ClaimDto ViewFiles { get; } = new ClaimDto
|
||||
{
|
||||
Title = "مشاهده فایل ها",
|
||||
Type = CustomClaimType.Permission,
|
||||
Value = ApplicationPermission.ViewFiles,
|
||||
};
|
||||
|
||||
public static List<ClaimDto> AllClaimDtos = new List<ClaimDto>
|
||||
{
|
||||
ManageBlogs,
|
||||
ViewBlogs,
|
||||
ManageBrands,
|
||||
ViewBrands,
|
||||
ManageCategories,
|
||||
ViewCategories,
|
||||
ManageDiscounts,
|
||||
ViewDiscounts,
|
||||
ManageOrders,
|
||||
ViewAllOrders,
|
||||
ViewMineOrders,
|
||||
CreateOrder,
|
||||
ManageProducts,
|
||||
ViewProducts,
|
||||
ManageReview,
|
||||
AddReview,
|
||||
ConfirmReview,
|
||||
ViewAllReviews,
|
||||
ViewMineReviews,
|
||||
ManageWarehouses,
|
||||
ViewWarehouses,
|
||||
ManageShipping,
|
||||
ViewShipping,
|
||||
ManageUsers,
|
||||
ViewUsers,
|
||||
ManageFiles,
|
||||
ViewFiles
|
||||
};
|
||||
|
||||
public static List<Claim> AllClaims = new List<Claim>
|
||||
{
|
||||
ManageBlogs.GetClaim,
|
||||
ViewBlogs.GetClaim,
|
||||
ManageBrands.GetClaim,
|
||||
ViewBrands.GetClaim,
|
||||
ManageCategories.GetClaim,
|
||||
ViewCategories.GetClaim,
|
||||
ManageDiscounts.GetClaim,
|
||||
ViewDiscounts.GetClaim,
|
||||
ManageOrders.GetClaim,
|
||||
ViewAllOrders.GetClaim,
|
||||
ViewMineOrders.GetClaim,
|
||||
CreateOrder.GetClaim,
|
||||
ManageProducts.GetClaim,
|
||||
ViewProducts.GetClaim,
|
||||
ManageReview.GetClaim,
|
||||
AddReview.GetClaim,
|
||||
ConfirmReview.GetClaim,
|
||||
ViewAllReviews.GetClaim,
|
||||
ViewMineReviews.GetClaim,
|
||||
ManageWarehouses.GetClaim,
|
||||
ViewWarehouses.GetClaim,
|
||||
ManageShipping.GetClaim,
|
||||
ViewShipping.GetClaim,
|
||||
ManageUsers.GetClaim,
|
||||
ViewUsers.GetClaim,
|
||||
ManageFiles.GetClaim,
|
||||
ViewFiles.GetClaim
|
||||
};
|
||||
|
||||
public static List<Claim> CustomerClaims = new List<Claim>
|
||||
{
|
||||
ViewBlogs.GetClaim,
|
||||
ViewBrands.GetClaim,
|
||||
ViewCategories.GetClaim,
|
||||
ViewMineOrders.GetClaim,
|
||||
CreateOrder.GetClaim,
|
||||
ViewProducts.GetClaim,
|
||||
AddReview.GetClaim,
|
||||
ViewMineReviews.GetClaim,
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
namespace HiVakil.Domain.Models.Claims;
|
||||
|
||||
public static class ApplicationPermission
|
||||
{
|
||||
public const string ManageBlogs = nameof(ManageBlogs);
|
||||
public const string ViewBlogs = nameof(ManageBlogs);
|
||||
|
||||
public const string ManageBrands = nameof(ManageBrands);
|
||||
public const string ViewBrands = nameof(ViewBrands);
|
||||
|
||||
public const string ManageCategories = nameof(ManageCategories);
|
||||
public const string ViewCategories = nameof(ViewCategories);
|
||||
|
||||
public const string ManageDiscounts = nameof(ManageDiscounts);
|
||||
public const string ViewDiscounts = nameof(ViewDiscounts);
|
||||
|
||||
public const string ManageOrders = nameof(ManageOrders);
|
||||
public const string ViewAllOrders = nameof(ViewAllOrders);
|
||||
public const string ViewMineOrders = nameof(ViewMineOrders);
|
||||
public const string CreateOrder = nameof(CreateOrder);
|
||||
|
||||
public const string ManageProducts = nameof(ManageProducts);
|
||||
public const string ViewProducts = nameof(ViewProducts);
|
||||
|
||||
public const string ManageReview = nameof(AddReview);
|
||||
public const string AddReview = nameof(AddReview);
|
||||
public const string ConfirmReview = nameof(ConfirmReview);
|
||||
public const string ViewAllReviews = nameof(ViewAllReviews);
|
||||
public const string ViewMineReviews = nameof(ViewMineReviews);
|
||||
|
||||
public const string ManageWarehouses = nameof(ManageWarehouses);
|
||||
public const string ViewWarehouses = nameof(ViewWarehouses);
|
||||
|
||||
public const string ManageShipping = nameof(ManageShipping);
|
||||
public const string ViewShipping = nameof(ViewShipping);
|
||||
|
||||
public const string ManageUsers = nameof(ManageUsers);
|
||||
public const string ViewUsers = nameof(ViewUsers);
|
||||
|
||||
public const string ManageFiles = nameof(ManageFiles);
|
||||
public const string ViewFiles = nameof(ViewFiles);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
namespace HiVakil.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 HiVakil.Domain.Models.Claims
|
||||
{
|
||||
public static class CustomClaimType
|
||||
{
|
||||
public static string Permission { get; } = "Permission";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
namespace HiVakil.Domain.Models.Settings;
|
||||
|
||||
public class SiteSettings
|
||||
{
|
||||
public JwtSettings JwtSettings { get; set; } = new JwtSettings();
|
||||
public string BaseUrl { get; set; } = string.Empty;
|
||||
public RedisSettings MasterRedisConfiguration { get; set; } = new RedisSettings();
|
||||
public StorageSetting StorageSetting { get; set; } = new StorageSetting();
|
||||
public UserSetting RootUser { get; set; } = new UserSetting();
|
||||
public UserSetting ManagerUser { get; set; } = new UserSetting();
|
||||
public string KaveNegarApiKey { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class StorageSetting
|
||||
{
|
||||
public string AccessKey { get; set; } = string.Empty;
|
||||
public string SecretKey { get; set; } = string.Empty;
|
||||
}
|
||||
public class RedisSettings
|
||||
{
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string ServiceName { get; set; } = string.Empty;
|
||||
public string Host { get; set; } = string.Empty;
|
||||
public int Port { get; set; }
|
||||
}
|
||||
|
||||
|
||||
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,45 @@
|
|||
<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="..\HiVakil.Core\HiVakil.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Amazon.S3" />
|
||||
<Using Include="Amazon.S3.Model" />
|
||||
<Using Include="HiVakil.Common.Extensions" />
|
||||
<Using Include="HiVakil.Common.Models" />
|
||||
<Using Include="HiVakil.Common.Models.Api" />
|
||||
<Using Include="HiVakil.Common.Models.Exception" />
|
||||
<Using Include="HiVakil.Core.Abstracts" />
|
||||
<Using Include="HiVakil.Core.Utilities" />
|
||||
<Using Include="HiVakil.Domain.Dtos.SmallDtos" />
|
||||
<Using Include="HiVakil.Domain.Enums" />
|
||||
<Using Include="HiVakil.Domain.Models.Settings" />
|
||||
<Using Include="HiVakil.Infrastructure.Models" />
|
||||
<Using Include="HiVakil.Infrastructure.Models.RestApi.KaveNegar" />
|
||||
<Using Include="HiVakil.Infrastructure.Models.RestApi.Zarinpal" />
|
||||
<Using Include="HiVakil.Infrastructure.RestServices" />
|
||||
<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 HiVakil.Infrastructure
|
||||
{
|
||||
public class InfrastructureConfig
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace HiVakil.Infrastructure.Models;
|
||||
|
||||
public static class DirectoryAddress
|
||||
{
|
||||
private static string _baseDire = $"{Directory.GetCurrentDirectory()}/wwwroot";
|
||||
public static string Logs = $"{_baseDire}/logs";
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace HiVakil.Infrastructure.Models;
|
||||
|
||||
public static class RestAddress
|
||||
{
|
||||
public static string BaseKaveNegar => "https://api.kavenegar.com/v1/";
|
||||
public static string BaseZarinpal => "https://api.zarinpal.com/pg";
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace HiVakil.Infrastructure.Models.RestApi.KaveNegar;
|
||||
|
||||
public class KaveNegarResponse
|
||||
{
|
||||
public KaveNegarReturn Return { get; set; }
|
||||
public KaveNegarResponseEntry[] entries { get; set; }
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace HiVakil.Infrastructure.Models.RestApi.KaveNegar;
|
||||
|
||||
public class KaveNegarResponseEntry
|
||||
{
|
||||
public int messageid { get; set; }
|
||||
public string message { get; set; }
|
||||
public int status { get; set; }
|
||||
public string statustext { get; set; }
|
||||
public string sender { get; set; }
|
||||
public string receptor { get; set; }
|
||||
public int date { get; set; }
|
||||
public int cost { get; set; }
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace HiVakil.Infrastructure.Models.RestApi.KaveNegar;
|
||||
|
||||
public class KaveNegarReturn
|
||||
{
|
||||
public int status { get; set; }
|
||||
public string message { get; set; }
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
namespace HiVakil.Infrastructure.Models.RestApi.Zarinpal;
|
||||
|
||||
public class ZarinaplPaymentLinkRequest
|
||||
{
|
||||
public string merchant_id { get; set; } = string.Empty;
|
||||
public int amount { get; set; }
|
||||
public string callback_url { get; set; } = string.Empty;
|
||||
public string description { get; set; } = string.Empty;
|
||||
public ZarinaplPaymentLinkRequestMetadata metadata { get; set; } = new();
|
||||
|
||||
}
|
||||
|
||||
public class ZarinaplPaymentLinkRequestMetadata
|
||||
{
|
||||
public string mobile { get; set; } = string.Empty;
|
||||
public string email { get; set; } = string.Empty;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
namespace HiVakil.Infrastructure.Models.RestApi.Zarinpal;
|
||||
|
||||
public class ZarinaplPaymentLinkResponse
|
||||
{
|
||||
public ZarinaplPaymentLinkResponseData data { get; set; }
|
||||
public List<object> errors { get; set; }
|
||||
}
|
||||
|
||||
public class ZarinaplPaymentLinkResponseData
|
||||
{
|
||||
public int code { get; set; }
|
||||
public string message { get; set; } = string.Empty;
|
||||
public string authority { get; set; } = string.Empty;
|
||||
public string fee_type { get; set; } = string.Empty;
|
||||
public int fee { get; set; }
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
namespace HiVakil.Infrastructure.Models.RestApi.Zarinpal;
|
||||
|
||||
public class ZarinaplPaymentVerifyResponse
|
||||
{
|
||||
|
||||
public ZarinaplPaymentVerifyResponseData data { get; set; }
|
||||
public List<object> errors { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class ZarinaplPaymentVerifyResponseData
|
||||
{
|
||||
public int code { get; set; }
|
||||
public string message { get; set; } = string.Empty;
|
||||
public string card_hash { get; set; } = string.Empty;
|
||||
public string card_pan { get; set; } = string.Empty;
|
||||
public int ref_id { get; set; }
|
||||
public string fee_type { get; set; } = string.Empty;
|
||||
public int fee { get; set; }
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace HiVakil.Infrastructure.Models.RestApi.Zarinpal;
|
||||
|
||||
public class ZarinaplVerifyPaymentRequest
|
||||
{
|
||||
public string merchant_id { get; set; } = string.Empty;
|
||||
public int amount { get; set; }
|
||||
public string authority { get; set; } = string.Empty;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace HiVakil.Infrastructure.RestServices;
|
||||
|
||||
public interface IKaveNegarRestApi
|
||||
{
|
||||
|
||||
[Post("/{apiKey}/verify/lookup.json")]
|
||||
Task<KaveNegarResponse> SendLookUp(string apiKey, [Query] string receptor, [Query] string token, [Query] string token2, [Query] string token10, [Query] string token20, [Query] string template);
|
||||
[Post("/{apiKey}/sms/send.json")]
|
||||
Task<KaveNegarResponse> SendSms(string apiKey, [Query] string receptor, [Query] string message, [Query] string sender);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
namespace HiVakil.Infrastructure.RestServices;
|
||||
|
||||
public interface IRestApiWrapper : IScopedDependency
|
||||
{
|
||||
IKaveNegarRestApi KaveNegarRestApi { get; }
|
||||
IZarinpalRestApi ZarinpalRestApi { get; }
|
||||
}
|
||||
|
||||
public class RestApiWrapper : IRestApiWrapper
|
||||
{
|
||||
public IKaveNegarRestApi KaveNegarRestApi => RestService.For<IKaveNegarRestApi>(RestAddress.BaseKaveNegar);
|
||||
public IZarinpalRestApi ZarinpalRestApi => RestService.For<IZarinpalRestApi>(RestAddress.BaseZarinpal);
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using HiVakil.Infrastructure.Models.RestApi.Zarinpal;
|
||||
|
||||
namespace HiVakil.Infrastructure.RestServices;
|
||||
|
||||
public interface IZarinpalRestApi
|
||||
{
|
||||
|
||||
[Post("/v4/payment/request.json")]
|
||||
Task<ZarinaplPaymentLinkResponse> GetPaymentLinkAsync([Body] ZarinaplPaymentLinkRequest request);
|
||||
[Post("/v4/payment/verify.json")]
|
||||
Task<ZarinaplPaymentVerifyResponse> VerifyPaymentAsync([Body] ZarinaplVerifyPaymentRequest request);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
namespace HiVakil.Infrastructure.Services;
|
||||
|
||||
public class SmsService : ISmsService
|
||||
{
|
||||
private readonly IRestApiWrapper _restApiWrapper;
|
||||
private readonly ILogger<SmsService> _logger;
|
||||
private readonly IHostEnvironment _environment;
|
||||
private readonly SiteSettings _siteSettings;
|
||||
public SmsService(
|
||||
IRestApiWrapper restApiWrapper,
|
||||
IOptionsSnapshot<SiteSettings> optionsSnapshot,
|
||||
ILogger<SmsService> logger,
|
||||
IHostEnvironment environment)
|
||||
{
|
||||
_restApiWrapper = restApiWrapper;
|
||||
_logger = logger;
|
||||
_environment = environment;
|
||||
_siteSettings = optionsSnapshot.Value;
|
||||
}
|
||||
public async Task SendForgerPasswordAsync(string phoneNumber, string newPassword)
|
||||
{
|
||||
var rest = await _restApiWrapper.KaveNegarRestApi.SendLookUp(_siteSettings.KaveNegarApiKey, phoneNumber, newPassword, null, null, null, "forgetPassword");
|
||||
|
||||
if (rest.Return.status != 200)
|
||||
throw new BaseApiException(ApiResultStatusCode.SendSmsError, rest.Return.message);
|
||||
}
|
||||
|
||||
public async Task SendVerifyCodeAsync(string phoneNumber, string verifyCode)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var rest = await _restApiWrapper.KaveNegarRestApi.SendLookUp(_siteSettings.KaveNegarApiKey, phoneNumber,
|
||||
verifyCode, null, null, null, "login");
|
||||
|
||||
if (rest.Return.status != 200 && _environment.IsProduction())
|
||||
throw new BaseApiException(ApiResultStatusCode.SendSmsError, rest.Return.message);
|
||||
}
|
||||
catch (ApiException apiException)
|
||||
{
|
||||
if (_environment.IsProduction())
|
||||
throw ;
|
||||
else
|
||||
_logger.LogError(apiException.Message);
|
||||
}
|
||||
catch (Exception apiException)
|
||||
{
|
||||
if (_environment.IsProduction())
|
||||
throw;
|
||||
else
|
||||
_logger.LogError(apiException.Message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
namespace HiVakil.Infrastructure.Services;
|
||||
|
||||
public class StorageService : IStorageService
|
||||
{
|
||||
private IAmazonS3? _s3Client;
|
||||
private string _bucketName = "vesmeh-content";
|
||||
private readonly StorageSetting _storageSettings;
|
||||
|
||||
public StorageService(IOptionsSnapshot<SiteSettings> snapshot)
|
||||
{
|
||||
_storageSettings = snapshot.Value.StorageSetting;
|
||||
}
|
||||
private IAmazonS3 GetClientAsync()
|
||||
{
|
||||
var awsCredentials = new Amazon.Runtime.BasicAWSCredentials(_storageSettings.AccessKey, _storageSettings.SecretKey);
|
||||
var config = new AmazonS3Config { ServiceURL = "https://s3.ir-thr-at1.arvanstorage.ir" };
|
||||
_s3Client = new AmazonS3Client(awsCredentials, config);
|
||||
return _s3Client;
|
||||
}
|
||||
|
||||
public async Task<string> UploadObjectFromFileAsync(string fileName, string filePath, string contentType, byte[] fileBytes)
|
||||
{
|
||||
using var memorySteam = new MemoryStream(fileBytes);
|
||||
|
||||
var client = GetClientAsync();
|
||||
|
||||
var fileEx = fileName.Split('.').Last();
|
||||
fileName = fileName.Split('.').First();
|
||||
|
||||
fileName = fileName + "_" + StringExtensions.GetId(5) + "_" + DateTime.Today.ToString("yyyy-MM-dd-HH-mm-ss") + "." + fileEx;
|
||||
|
||||
var putRequest = new PutObjectRequest
|
||||
{
|
||||
BucketName = _bucketName,
|
||||
Key = Path.Combine(filePath, fileName),
|
||||
ContentType = contentType,
|
||||
InputStream = memorySteam,
|
||||
CannedACL = S3CannedACL.PublicRead
|
||||
};
|
||||
|
||||
putRequest.Metadata.Add("x-amz-meta-title", fileName);
|
||||
|
||||
PutObjectResponse response = await client.PutObjectAsync(putRequest);
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public async Task<string> UploadObjectFromFileAsync(string fileName, string filePath, string contentType, Stream fileStream , bool fixName = true)
|
||||
{
|
||||
|
||||
var client = GetClientAsync();
|
||||
|
||||
if (fixName)
|
||||
{
|
||||
var fileEx = fileName.Split('.').Last();
|
||||
fileName = fileName.Split('.').First();
|
||||
|
||||
fileName = fileName + "_" + StringExtensions.GetId(5) + "_" + DateTimeExtensions.DateTimeToUnixTimeStamp(DateTime.Now) + "." + fileEx;
|
||||
}
|
||||
|
||||
var putRequest = new PutObjectRequest
|
||||
{
|
||||
BucketName = _bucketName,
|
||||
Key = Path.Combine(filePath, fileName),
|
||||
ContentType = contentType,
|
||||
InputStream = fileStream,
|
||||
CannedACL = S3CannedACL.PublicRead
|
||||
};
|
||||
|
||||
//putRequest.Metadata.Add("x-amz-meta-title", fileName);
|
||||
|
||||
PutObjectResponse response = await client.PutObjectAsync(putRequest);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public async Task<List<StorageFileSDto>> GetStorageFiles(StorageFileType fileType)
|
||||
{
|
||||
var client = GetClientAsync();
|
||||
ListObjectsRequest request = new() { BucketName = _bucketName};
|
||||
switch (fileType)
|
||||
{
|
||||
case StorageFileType.Image:
|
||||
request.Prefix = "Images/Med";
|
||||
break;
|
||||
case StorageFileType.Video:
|
||||
request.Prefix = "Videos";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
var files = new List<StorageFileSDto>();
|
||||
do
|
||||
{
|
||||
ListObjectsResponse response = await client.ListObjectsAsync(request);
|
||||
|
||||
// Process the response.
|
||||
foreach (var s3Object in response.S3Objects.Where(s=>s.Size>0))
|
||||
{
|
||||
files.Add(new StorageFileSDto
|
||||
{
|
||||
FileLocation = s3Object.Key,
|
||||
FileName = s3Object.Key.Split('/').Last()
|
||||
});
|
||||
}
|
||||
|
||||
// If the response is truncated, set the marker to get the next
|
||||
// set of keys.
|
||||
if (response.IsTruncated)
|
||||
{
|
||||
request.Marker = response.NextMarker;
|
||||
}
|
||||
else
|
||||
{
|
||||
request = null;
|
||||
}
|
||||
} while (request != null);
|
||||
|
||||
return files.OrderByDescending(o=>o.CreatedAt).ToList();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
namespace HiVakil.Infrastructure.Services;
|
||||
|
||||
public class UploadFileService : IUploadFileService
|
||||
{
|
||||
private readonly IStorageService _storageService;
|
||||
|
||||
public UploadFileService(IStorageService storageService)
|
||||
{
|
||||
_storageService = storageService;
|
||||
}
|
||||
public async Task<FileUploadResponse> UploadImageAsync(FileUploadRequest uploadRequest)
|
||||
{
|
||||
var bytes = Convert.FromBase64String(uploadRequest.StringBaseFile);
|
||||
using var originalMedFileStream = new MemoryStream(bytes);
|
||||
using var originalThumbFileStream = new MemoryStream(bytes);
|
||||
using var thumbnailFileStream = new MemoryStream();
|
||||
using var mediumFileStream = new MemoryStream();
|
||||
|
||||
await uploadRequest.ImageResize(originalMedFileStream, mediumFileStream, 1280);
|
||||
await uploadRequest.ImageResize(originalThumbFileStream, thumbnailFileStream, 200);
|
||||
var medFileName = await _storageService.UploadObjectFromFileAsync(uploadRequest.FileName, $"{uploadRequest.FileUploadType.ToDisplay()}/Med", uploadRequest.ContentType, mediumFileStream);
|
||||
await _storageService.UploadObjectFromFileAsync(medFileName, $"{uploadRequest.FileUploadType.ToDisplay()}/Thumb", uploadRequest.ContentType, thumbnailFileStream, false);
|
||||
var response = new FileUploadResponse
|
||||
{
|
||||
FileName = medFileName,
|
||||
FileLocation = $"{uploadRequest.FileUploadType.ToDisplay()}/Med/{medFileName}",
|
||||
FileUrl = $"https://storage.vesmook.com/{uploadRequest.FileUploadType.ToDisplay()}/Med/{medFileName}"
|
||||
};
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
namespace HiVakil.Infrastructure.Services;
|
||||
|
||||
public class ZarinpalService : IPaymentService
|
||||
{
|
||||
private readonly IRestApiWrapper _restApiWrapper;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly SiteSettings _siteSettings;
|
||||
public ZarinpalService(IRestApiWrapper restApiWrapper,
|
||||
IOptionsSnapshot<SiteSettings> snapshot,
|
||||
IMediator mediator)
|
||||
{
|
||||
_restApiWrapper = restApiWrapper;
|
||||
_mediator = mediator;
|
||||
_siteSettings = snapshot.Value;
|
||||
}
|
||||
public async Task<string> GetPaymentLinkAsync(double amount,string factorNumber, Guid orderId, Guid userId, string phoneNumber , string fullName , CancellationToken cancellationToken = default)
|
||||
{
|
||||
var request = new ZarinaplPaymentLinkRequest
|
||||
{
|
||||
description = $"پرداخت {amount.ToString("N0")} ریال توسط {fullName} با شماره تماس {phoneNumber} برای سفارش با شماره {factorNumber}",
|
||||
amount = (int)amount,
|
||||
callback_url = Path.Combine(_siteSettings.BaseUrl, "api", "accounting", "pay", "verify"),
|
||||
//merchant_id = "4292b845-b510-4d1d-8ee2-097499b198e5",
|
||||
metadata = new ZarinaplPaymentLinkRequestMetadata { mobile = phoneNumber }
|
||||
};
|
||||
var response = await _restApiWrapper.ZarinpalRestApi.GetPaymentLinkAsync(request);
|
||||
if (response.data.code != 100)
|
||||
throw new AppException($"Exception in get link from zarinpal | {response.data.message}");
|
||||
|
||||
|
||||
string link = $"https://www.zarinpal.com/pg/StartPay/{response.data.authority}";
|
||||
return link;
|
||||
}
|
||||
|
||||
public async Task<Tuple<string,string>> VerifyPaymentAsync(string authority, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
namespace HiVakil.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 = HiVakil.Common.Models.Exception.ValidationException;
|
||||
|
||||
namespace HiVakil.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 HiVakil.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 HiVakil.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,68 @@
|
|||
<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="..\HiVakil.Domain\HiVakil.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="FluentValidation" />
|
||||
<Using Include="HiVakil.Common.Extensions" />
|
||||
<Using Include="HiVakil.Common.Models" />
|
||||
<Using Include="HiVakil.Common.Models.Api" />
|
||||
<Using Include="HiVakil.Common.Models.Entity" />
|
||||
<Using Include="HiVakil.Common.Models.Exception" />
|
||||
<Using Include="HiVakil.Domain.Entities.Users" />
|
||||
<Using Include="HiVakil.Domain.Enums" />
|
||||
<Using Include="HiVakil.Domain.Models.Claims" />
|
||||
<Using Include="HiVakil.Domain.Models.Settings" />
|
||||
<Using Include="HiVakil.Repository.Abstracts" />
|
||||
<Using Include="HiVakil.Repository.Extensions" />
|
||||
<Using Include="HiVakil.Repository.Models" />
|
||||
<Using Include="HiVakil.Repository.Repositories.Base.Contracts" />
|
||||
<Using Include="HiVakil.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>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue