Enhance authentication flow; add user registration completion check and update contract acceptance process
This commit is contained in:
@@ -34,10 +34,11 @@ public static class ConfigureServices
|
|||||||
services.AddHttpContextAccessor();
|
services.AddHttpContextAccessor();
|
||||||
|
|
||||||
// Register custom services
|
// Register custom services
|
||||||
|
services.AddSingleton<UserAuthInfo>();
|
||||||
services.AddScoped<AuthService>();
|
services.AddScoped<AuthService>();
|
||||||
services.AddScoped<AuthDialogService>();
|
services.AddScoped<AuthDialogService>();
|
||||||
// Device detection: very light, dependency-free
|
// Device detection: very light, dependency-free
|
||||||
services.AddScoped<IDeviceDetector, DeviceDetector>();
|
services.AddTransient<IDeviceDetector, DeviceDetector>();
|
||||||
// PDF generation (Chromium only)
|
// PDF generation (Chromium only)
|
||||||
services.AddSingleton<FrontOffice.Main.Utilities.Pdf.IChromiumPdfService, FrontOffice.Main.Utilities.Pdf.ChromiumPdfService>();
|
services.AddSingleton<FrontOffice.Main.Utilities.Pdf.IChromiumPdfService, FrontOffice.Main.Utilities.Pdf.ChromiumPdfService>();
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<PackageReference Include="DateTimeConverterCL" Version="1.0.0" />
|
<PackageReference Include="DateTimeConverterCL" Version="1.0.0" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.Package.Protobuf" Version="0.0.112" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.Package.Protobuf" Version="0.0.112" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.Transaction.Protobuf" Version="0.0.111" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.Transaction.Protobuf" Version="0.0.111" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.User.Protobuf" Version="0.0.115" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.User.Protobuf" Version="0.0.116" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.UserAddress.Protobuf" Version="0.0.114" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.UserAddress.Protobuf" Version="0.0.114" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.UserOrder.Protobuf" Version="0.0.112" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.UserOrder.Protobuf" Version="0.0.112" />
|
||||||
<PackageReference Include="MudBlazor" Version="8.14.0" />
|
<PackageReference Include="MudBlazor" Version="8.14.0" />
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.71.0" />
|
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.71.0" />
|
||||||
<!-- Keep only PuppeteerSharp for Chromium-based PDF generation -->
|
<!-- Keep only PuppeteerSharp for Chromium-based PDF generation -->
|
||||||
<PackageReference Include="PuppeteerSharp" Version="11.0.0" />
|
<PackageReference Include="PuppeteerSharp" Version="11.0.0" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using MudBlazor;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace FrontOffice.Main.Pages;
|
namespace FrontOffice.Main.Pages;
|
||||||
|
|
||||||
public partial class Index
|
public partial class Index
|
||||||
{
|
{
|
||||||
[Inject] private PackageContract.PackageContractClient PackageClient { get; set; } = default!;
|
[Inject] private PackageContract.PackageContractClient PackageClient { get; set; } = default!;
|
||||||
@@ -68,6 +69,7 @@ public partial class Index
|
|||||||
Snackbar.Add("لطفاً ایمیل معتبر وارد کنید.", Severity.Warning);
|
Snackbar.Add("لطفاً ایمیل معتبر وارد کنید.", Severity.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Snackbar.Add("به لیست انتظار «کارا بازار سلامت» اضافه شدید.", Severity.Success);
|
Snackbar.Add("به لیست انتظار «کارا بازار سلامت» اضافه شدید.", Severity.Success);
|
||||||
_email = string.Empty;
|
_email = string.Empty;
|
||||||
}
|
}
|
||||||
@@ -76,14 +78,18 @@ public partial class Index
|
|||||||
{
|
{
|
||||||
Navigation.NavigateTo($"{RouteConstants.Package.Detail}{packageId}");
|
Navigation.NavigateTo($"{RouteConstants.Package.Detail}{packageId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NavigateToRegistrationWizard()
|
private void NavigateToRegistrationWizard()
|
||||||
{
|
{
|
||||||
Navigation.NavigateTo(RouteConstants.Registration.Wizard);
|
Navigation.NavigateTo(RouteConstants.Registration.Wizard);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record Pack(long Id, string Title, string Body, string Image, long Price);
|
private record Pack(long Id, string Title, string Body, string Image, long Price);
|
||||||
|
|
||||||
private record Plan(string Name, string Price, bool Highlight, IEnumerable<string> Features);
|
private record Plan(string Name, string Price, bool Highlight, IEnumerable<string> Features);
|
||||||
|
|
||||||
private record QA(string Q, string A);
|
private record QA(string Q, string A);
|
||||||
|
|
||||||
private readonly List<QA> _faqs = new()
|
private readonly List<QA> _faqs = new()
|
||||||
{
|
{
|
||||||
new("دامنهٔ اختصاصی دارم؛ قابل اتصال است؟", "بله، پشت دامنه و گواهی SSL خودتان مستقر میشود."),
|
new("دامنهٔ اختصاصی دارم؛ قابل اتصال است؟", "بله، پشت دامنه و گواهی SSL خودتان مستقر میشود."),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Google.Protobuf.WellKnownTypes;
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
|
using Blazored.LocalStorage;
|
||||||
|
|
||||||
namespace FrontOffice.Main.Pages;
|
namespace FrontOffice.Main.Pages;
|
||||||
|
|
||||||
@@ -24,9 +25,18 @@ public partial class RegisterWizard
|
|||||||
private MudStepper? _mudStepper;
|
private MudStepper? _mudStepper;
|
||||||
private UpdateUserRequest _updateUserRequest = new();
|
private UpdateUserRequest _updateUserRequest = new();
|
||||||
private bool _isAuthenticated;
|
private bool _isAuthenticated;
|
||||||
|
private CancellationTokenSource? _operationCts;
|
||||||
|
private UserAuthInfo _userAuthInfo;
|
||||||
|
private Guid signGuid = Guid.NewGuid();
|
||||||
|
private const string TokenStorageKey = "auth:token";
|
||||||
|
private readonly DialogOptions _normalWidth = new() { MaxWidth = MaxWidth.ExtraSmall, FullWidth = true };
|
||||||
|
|
||||||
[Inject] private AuthService AuthService { get; set; } = default!;
|
[Inject] private AuthService AuthService { get; set; } = default!;
|
||||||
|
[Inject] private IDeviceDetector _deviceDetector { get; set; } = default!;
|
||||||
[Inject] private IJSRuntime Js { get; set; } = default!;
|
[Inject] private IJSRuntime Js { get; set; } = default!;
|
||||||
|
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
||||||
|
[Inject] private UserContract.UserContractClient UserClient { get; set; } = default!;
|
||||||
|
|
||||||
|
|
||||||
private string _nextButtonText => _activeStep switch
|
private string _nextButtonText => _activeStep switch
|
||||||
{
|
{
|
||||||
@@ -39,13 +49,21 @@ public partial class RegisterWizard
|
|||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
_isAuthenticated = await AuthService.IsAuthenticatedAsync();
|
_isAuthenticated = await AuthService.IsAuthenticatedAsync();
|
||||||
if (_isAuthenticated && _activeStep == 0)
|
if (_isAuthenticated)
|
||||||
|
{
|
||||||
|
_userAuthInfo = await AuthService.GetUserAuthInfo();
|
||||||
|
if (_userAuthInfo.IsSignMainContract)
|
||||||
|
{
|
||||||
|
Navigation.NavigateTo(RouteConstants.Profile.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_activeStep == 0)
|
||||||
{
|
{
|
||||||
await _mudStepper.NextStepAsync();
|
await _mudStepper.NextStepAsync();
|
||||||
_activeStep = 1;
|
_activeStep = 1;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
else if (_isAuthenticated && _activeStep == 1)
|
else if (_activeStep == 1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -75,6 +93,8 @@ public partial class RegisterWizard
|
|||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
await base.OnAfterRenderAsync(firstRender);
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
}
|
}
|
||||||
@@ -98,16 +118,44 @@ public partial class RegisterWizard
|
|||||||
case 0:
|
case 0:
|
||||||
if (_authDialog._currentStep == AuthDialog.AuthStep.Phone)
|
if (_authDialog._currentStep == AuthDialog.AuthStep.Phone)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_isSubmitting = true;
|
||||||
await _authDialog.SendOtpAsync();
|
await _authDialog.SendOtpAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isSubmitting = false;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_isSubmitting = true;
|
||||||
var verifyOtp = await _authDialog.VerifyOtpAsync();
|
var verifyOtp = await _authDialog.VerifyOtpAsync();
|
||||||
if (!verifyOtp)
|
if (!verifyOtp)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
_activeStep = 1;
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isSubmitting = false;
|
||||||
|
}
|
||||||
|
//continus in OnAfterRenderAsync method
|
||||||
|
// await _mudStepper.NextStepAsync();
|
||||||
|
// _activeStep = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -126,7 +174,10 @@ public partial class RegisterWizard
|
|||||||
case 2:
|
case 2:
|
||||||
if (!await ValidateStepAsync(_stepThreeForm))
|
if (!await ValidateStepAsync(_stepThreeForm))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await SubmitAsync();
|
await SubmitAsync();
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,12 +193,66 @@ public partial class RegisterWizard
|
|||||||
|
|
||||||
private async Task SubmitAsync()
|
private async Task SubmitAsync()
|
||||||
{
|
{
|
||||||
|
if (_operationCts == null || _operationCts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
_operationCts = new CancellationTokenSource();
|
||||||
|
}
|
||||||
|
|
||||||
_isSubmitting = true;
|
_isSubmitting = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Delay(800);
|
var parameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "ContentText", "لطفاً کد تأیید ارسال شده را وارد کنید." },
|
||||||
|
{ "ButtonText", "تأیید" },
|
||||||
|
};
|
||||||
|
var options = _deviceDetector.IsMobile()
|
||||||
|
? new DialogOptions() { FullScreen = true}
|
||||||
|
: _normalWidth;
|
||||||
|
var response = await UserClient.CreateNewOtpTokenAsync(new CreateNewOtpTokenRequest()
|
||||||
|
{
|
||||||
|
Mobile = _userAuthInfo.MobileNumber,
|
||||||
|
Purpose = "signContract",
|
||||||
|
SignGuid = signGuid.ToString()
|
||||||
|
}, cancellationToken: _operationCts.Token);
|
||||||
|
if (response?.Success != true)
|
||||||
|
{
|
||||||
|
var errorMessage = string.IsNullOrWhiteSpace(response?.Message)
|
||||||
|
? "ارسال رمز پویا با خطا مواجه شد. لطفاً دوباره تلاش کنید."
|
||||||
|
: response!.Message;
|
||||||
|
Snackbar.Add(errorMessage, Severity.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dialog = await DialogService.ShowAsync<SimpleOtpDialog>("تأیید قرارداد", parameters,options);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
if (result.Canceled || result.Data is not string otpCode || string.IsNullOrWhiteSpace(otpCode))
|
||||||
|
{
|
||||||
|
Snackbar.Add("ورود کد تأیید الزامی است.", Severity.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var acceptContractResponse = await UserClient.AcceptContractAsync(new()
|
||||||
|
{
|
||||||
|
SignGuid = signGuid.ToString(),
|
||||||
|
Code = otpCode,
|
||||||
|
ContractHtml = GetContractHtml(),
|
||||||
|
|
||||||
|
}, cancellationToken: _operationCts.Token);
|
||||||
|
if (!string.IsNullOrWhiteSpace(acceptContractResponse.Token))
|
||||||
|
{
|
||||||
|
await LocalStorage.SetItemAsync(TokenStorageKey, acceptContractResponse.Token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await LocalStorage.RemoveItemAsync(TokenStorageKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_completed = true;
|
_completed = true;
|
||||||
Snackbar.Add("ثبتنام اولیه با موفقیت انجام شد.", Severity.Success);
|
Snackbar.Add("ثبتنام اولیه و تأیید قرارداد با موفقیت انجام شد.", Severity.Success);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
Navigation.NavigateTo(RouteConstants.Profile.Index);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -158,45 +263,8 @@ public partial class RegisterWizard
|
|||||||
private async void DownloadContract()
|
private async void DownloadContract()
|
||||||
{
|
{
|
||||||
//var html = $"<!DOCTYPE html><html><body><h1 style='text-align:center'>قرارداد اولیه کاربر</h1><p>نام: {_model.FirstName ?? "-"} {_model.LastName ?? "-"}</p><p>کد ملی: {_model.NationalCode ?? "-"}</p><p>این یک نسخه نمونه است.</p></body></html>";
|
//var html = $"<!DOCTYPE html><html><body><h1 style='text-align:center'>قرارداد اولیه کاربر</h1><p>نام: {_model.FirstName ?? "-"} {_model.LastName ?? "-"}</p><p>کد ملی: {_model.NationalCode ?? "-"}</p><p>این یک نسخه نمونه است.</p></body></html>";
|
||||||
var html =
|
|
||||||
$"<!DOCTYPE html><html lang='fa' dir='rtl'><head>" +
|
|
||||||
"<meta charset='UTF-8' /><title>قرارداد تعهد و سلب مسئولیت کارابازار</title><style>" +
|
|
||||||
"body { " +
|
|
||||||
" font-family: sans-serif; " +
|
|
||||||
" direction: rtl;text-align: justify; " +
|
|
||||||
" font-size: 13px;line-height: 1.8; " +
|
|
||||||
" margin: 40px;}h1, h2 {text-align: center;margin-bottom: 10px;}" +
|
|
||||||
"h1 {font-size: 18px;}h2 {font-size: 15px;}" +
|
|
||||||
".section-title {font-weight: bold;margin-top: 15px;margin-bottom: 5px;}" +
|
|
||||||
".contract-info, .sign-section {margin-top: 20px;}.field-label {font-weight: bold;}" +
|
|
||||||
".box {border: 1px solid #000;padding: 8px;margin-top: 10px;}.small-text {font-size: 11px;line-height: 1.7;}" +
|
|
||||||
"</style></head><body><h1>قرارداد تعهد و سلب مسئولیت</h1><h2>بین کارابازار و کاربر</h2><div class='contract-info'>" +
|
|
||||||
"<p>این قرارداد تعهد و سلب مسئولیت («قرارداد») در تاریخ " +
|
|
||||||
$"<span class='field-label'>{DateTime.Now.MiladiToJalali()} </span>بین:</p><p>" +
|
|
||||||
"1. شرکت/مجموعه <span class='field-label'>کارابازار</span> (که از این پس «کارابازار» نامیده میشود)،</p><p>2. شخص حقیقی زیر (که از این پس «کاربر» نامیده میشود):</p><div class='box'>" +
|
|
||||||
$"<p><span class='field-label'>نام و نام خانوادگی کاربر:</span> {_model.FirstName } {_model.LastName}</p>" +
|
|
||||||
$"<p><span class='field-label'>شماره ملی:</span> {_model.NationalCode?.PersianToEnglish()}</p>" +
|
|
||||||
$"<p><span class='field-label'>شماره تماس:</span> {_model.NationalCode?.PersianToEnglish() }</p></div>" +
|
|
||||||
"<p>کارابازار و کاربر که در این قرارداد جداگانه «طرف» و مجموعاً «طرفین» نامیده میشوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا مینمایند.</p></div><div><p class='section-title'>ماده ۱ - موضوع قرارداد</p>" +
|
|
||||||
"<p>موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر ازخدمات، باشگاه مشتریان، مزایا، طرحهای همکاری، شبکه معرفی، خرید از فروشگاههای طرفقراردادو هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرمها و شرکتهایهمکار در اختیار کاربر قرار میگیرد، بدون اینکه جزئیات مدل کسبوکار، شیوه تأمین منابع مالی،شبکه همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.</p>" +
|
|
||||||
"<p class='section-title'>ماده ۲ - اقرار و آگاهی کاربر</p><p>۲-۱. کاربر اقرار مینماید که کلیه اطلاعات کلی لازم در خصوص نحوه فعالیت، مزایا، ریسکهای احتمالی," +
|
|
||||||
"سازوکار کلی استفاده از خدمات، و چارچوب کلی همکاری را از مراجع رسمی معرفیشده توسط کارابازاردریافت کرده، سؤالات خود را مطرح نموده و پاسخ مناسب را دریافت نموده است.</p><p>۲-۲. کاربر با امضای این قرارداد اقرار مینماید که:</p><ul><li>با اراده آزاد و بدون هرگونه اجبار، اکراه، فریب یا سوءاستفاده از ناآگاهی وارد این همکاری شده است.</li><li>از احتمال وجود ریسکهای مالی، اعتباری، قانونی و شبکهای مرتبط با فعالیت خود آگاه بوده و آن را میپذیرد.</li>" +
|
|
||||||
"<li>هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در شبکه معرفی، خرید از فروشگاهها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و بهعنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمیشود.</li></ul>" +
|
|
||||||
"<p class='section-title'>ماده ۳ - سلب مسئولیت کارابازار</p><p>۳-۱. کاربر صراحتاً میپذیرد که کارابازار صرفاً در چارچوب قوانین و مقررات حاکم و مطابق قراردادها و تفاهمنامههای خود با شرکای تجاری و پلتفرمهای همکار، خدمات و امکانات مشخصی را در اختیار کاربر قرار میدهد و هیچگونه تعهدی نسبت به:</p><ul><li>تحقق سود یا بازده مالی مشخص،</li><li>ثبات ارزش هرگونه اعتبار، امتیاز، یا منافع غیرنقدی که ممکن است در قالب طرحها به کاربر تخصیص یابد،</li>" +
|
|
||||||
"<li>عملکرد اشخاص ثالث (از جمله پلتفرمها، فروشگاهها، شرکتهای بیمه، ارائهدهندگان خدمات سلامت و هر شخص حقیقی یا حقوقی همکار)،</li><li>تصمیمات و اقدامات کاربر در جذب افراد جدید و ایجاد زیرمجموعه،</li></ul><p>نداشته و نخواهد داشت مگر در حدودی که بهصراحت در قرارداد یا قوانین آمره بر عهده کارابازار گذاشته شده است.</p><p>" +
|
|
||||||
"۳-۲. هرگونه خسارت، دعوی، تهدید، مطالبه، ادعا، شکایت یا پیگیری حقوقی که ناشی از تصمیمات شخصی کاربر،نحوه استفاده وی از تسهیلات و مزایا، جذب دیگران، خرید کالا و خدمات، یا تعاملات او با اشخاص ثالث باشد،مستقیماً متوجه خود کاربر است و کارابازار نسبت به آن هیچگونه مسئولیت مدنی، کیفری، مالی یا قراردادی ندارد," +
|
|
||||||
"مگر در مواردی که طبق قوانین آمره، مسئولیت صریح و غیرقابلاسقاط بر عهده کارابازار قرار گرفته باشد.</p><p>۳-۳. کاربر میپذیرد که هیچگونه ادعایی مبنی بر فریب، اغفال، ارائه اطلاعات نادرست یا وعدههای خارج ازچهارچوب رسمی از سوی کارابازار یا نمایندگان رسمی آن، پس از امضای این قرارداد، از وی مسموع نخواهد بود،مگر آنکه طبق رأی قطعی مرجع قضایی صالح، خلاف آن ثابت شود.</p><p class='section-title'>ماده ۴ - مسئولیت کاربر در قبال تهدید، ادعا و شکایت</p>" +
|
|
||||||
"<p>۴-۱. کاربر متعهد است در صورت طرح هرگونه تهدید، ادعا، مطالبه، شکایت یا پیگیری حقوقی از سوی اشخاص ثالث(از جمله افراد جذبشده توسط کاربر، زیرمجموعهها، خریداران معرفیشده یا سایر اشخاص)، که ناشی از عملکردشخصی کاربر، معرفیهای وی، شیوه تبلیغ، وعدههای خارج از چارچوب رسمی کارابازار، یا نقض قوانین و مقرراتباشد، خود رأساً پاسخگو باشد و کارابازار را از هرگونه مسئولیت و هزینه احتمالی در این خصوص مصون بدارد.</p><p>۴-۲. کاربر میپذیرد که:</p><ul><li>هرگونه تهدید یا ادعای بیجا، غیرمنطقی، غیرمستند یا مغایر با مفاد این قرارداد، متوجه شخص کاربر است.</li>" +
|
|
||||||
"<li>در صورت وارد آمدن خسارت مادی یا معنوی به کارابازار ناشی از چنین تهدیدات یا ادعاهایی، کارابازار حق دارد نسبت به مطالبه خسارت از کاربر، طبق قوانین و از طریق مراجع صالح اقدام نماید.</li></ul>" +
|
|
||||||
"<p class='section-title'>ماده ۵ - محرمانگی و عدم افشای جزئیات کسبوکار</p><p>۵-۱. کاربر میپذیرد که جزئیات فنی، مالی، ساختار شبکه، شیوه توزیع مزایا، قراردادهای داخلی کارابازار باشرکای تجاری و پلتفرمهای همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آنهاتوسط کاربر بدون مجوز کتبی کارابازار، مجاز نمیباشد.</p><p>۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسبوکار در این قرارداد را بهعنوان دلیل بطلان، فسخ یاادعای فریب علیه کارابازار از خود سلب مینماید.</p>" +
|
|
||||||
"<p class='section-title'>ماده ۶ - کد تأیید یکبارمصرف (OTP) و شناسه قرارداد</p><p>۶-۱. به منظور تأیید هویت کاربر و جایگزین کردن امضا در محیط غیرحضوری، برای این قرارداد یک شناسه یکتا(GUID) تولید شده و از طریق سامانه کارابازار، کد تأیید یکبارمصرف (OTP) مرتبط با آن برای کاربر ارسالمیگردد.</p>" +
|
|
||||||
"<p>۶-۲. کاربر با وارد کردن صحیح کد تأیید (OTP) در سامانه، اقرار مینماید که:</p><ul><li>مالک شماره تماس ثبتشده در این قرارداد است یا با اجازه قانونی مالک از آن استفاده میکند،</li><li>از محتوای قرارداد بهطور کامل آگاه است و آن را بدون ابهام و با رضایت کامل میپذیرد،</li><li>شناسه یکتا و OTP ارسالشده، معادل امضای الکترونیکی معتبر وی بر روی این قرارداد است.</li></ul>" +
|
|
||||||
"<p class='section-title'>ماده ۷ - مدت، اصلاح و حاکمیت قانون</p>" +
|
|
||||||
"<p>۷-۱. این قرارداد از تاریخ تأیید نهایی (ثبت OTP) نافذ و لازمالاجرا بوده و تا زمانی که همکاری کاربر باکارابازار ادامه دارد، معتبر خواهد بود؛ مگر آنکه مطابق قوانین یا توافق طرفین، خاتمه یابد.</p><p>۷-۲. هرگونه اصلاح در مفاد این قرارداد صرفاً از طریق اطلاعرسانی رسمی کارابازار و پذیرش کاربر (اعم ازامضای مکتوب، تأیید در سامانه، یا سایر روشهای الکترونیکی مورد تأیید کارابازار) معتبر خواهد بود.</p><p>۷-۳. این قرارداد از هر حیث، تابع قوانین و مقررات حاکم بر جمهوری اسلامی ایران بوده و در صورت بروز اختلاف،مراجع صالح قضایی محل استقرار کارابازار، صلاحیت رسیدگی خواهند داشت؛ مگر آنکه به نحو دیگری بین طرفین توافقشود." +
|
|
||||||
"</p><p class='section-title'>ماده ۸ - اقرار نهایی کاربر</p><p>کاربر با امضای این قرارداد (از طریق ثبت کد تأیید یکبارمصرف OTP متناظر با شناسه یکتا)، صریحاً اعلام مینماید که:" +
|
|
||||||
"</p><ul><li>کلیه مفاد قرارداد را بهدقت مطالعه نموده و آن را درک کرده است،</li>" +
|
|
||||||
"<li>پرسشهای خود را مطرح نموده و پاسخ روشن دریافت کرده است،</li><li>ریسکها، محدودیتها و حدود مسئولیت کارابازار را میپذیرد،</li><li>حق هرگونه ادعای مغایر با مفاد این قرارداد، بهویژه ادعاهای بیاساس، غیرمنطقی یا ناشی از برداشت نادرست شخصی را از خود سلب و اسقاط مینماید؛ مگر در حدودی که قانون بهطور آمره اجازه سلب آن را نداده باشد.</li></ul></div><div class='sign-section'></div><p class='small-text'></p><div class='box'><p><span class='field-label'>شناسه یکتای قرارداد :</span></p><p><span id='contract-guid'>"+Guid.NewGuid()+"</span></p></div></body></html>";
|
|
||||||
|
|
||||||
|
var html = GetContractHtml();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// If HTML is short use GET to simplify (URL length safe)
|
// If HTML is short use GET to simplify (URL length safe)
|
||||||
@@ -227,6 +295,50 @@ public partial class RegisterWizard
|
|||||||
//StateHasChanged();
|
//StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetContractHtml()
|
||||||
|
{
|
||||||
|
var html =
|
||||||
|
$"<!DOCTYPE html><html lang='fa' dir='rtl'><head>" +
|
||||||
|
"<meta charset='UTF-8' /><title>قرارداد تعهد و سلب مسئولیت کارابازار</title><style>" +
|
||||||
|
"body { " +
|
||||||
|
" font-family: sans-serif; " +
|
||||||
|
" direction: rtl;text-align: justify; " +
|
||||||
|
" font-size: 13px;line-height: 1.8; " +
|
||||||
|
" margin: 40px;}h1, h2 {text-align: center;margin-bottom: 10px;}" +
|
||||||
|
"h1 {font-size: 18px;}h2 {font-size: 15px;}" +
|
||||||
|
".section-title {font-weight: bold;margin-top: 15px;margin-bottom: 5px;}" +
|
||||||
|
".contract-info, .sign-section {margin-top: 20px;}.field-label {font-weight: bold;}" +
|
||||||
|
".box {border: 1px solid #000;padding: 8px;margin-top: 10px;}.small-text {font-size: 11px;line-height: 1.7;}" +
|
||||||
|
"</style></head><body><h1>قرارداد تعهد و سلب مسئولیت</h1><h2>بین کارابازار و کاربر</h2><div class='contract-info'>" +
|
||||||
|
"<p>این قرارداد تعهد و سلب مسئولیت («قرارداد») در تاریخ " +
|
||||||
|
$"<span class='field-label'>{DateTime.Now.MiladiToJalali()} </span>بین:</p><p>" +
|
||||||
|
"1. شرکت/مجموعه <span class='field-label'>کارابازار</span> (که از این پس «کارابازار» نامیده میشود)،</p><p>2. شخص حقیقی زیر (که از این پس «کاربر» نامیده میشود):</p><div class='box'>" +
|
||||||
|
$"<p><span class='field-label'>نام و نام خانوادگی کاربر:</span> {_model.FirstName} {_model.LastName}</p>" +
|
||||||
|
$"<p><span class='field-label'>شماره ملی:</span> {_model.NationalCode?.PersianToEnglish()}</p>" +
|
||||||
|
$"<p><span class='field-label'>شماره تماس:</span> {_userAuthInfo.MobileNumber?.PersianToEnglish()}</p></div>" +
|
||||||
|
"<p>کارابازار و کاربر که در این قرارداد جداگانه «طرف» و مجموعاً «طرفین» نامیده میشوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا مینمایند.</p></div><div><p class='section-title'>ماده ۱ - موضوع قرارداد</p>" +
|
||||||
|
"<p>موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر ازخدمات، باشگاه مشتریان، مزایا، طرحهای همکاری، شبکه معرفی، خرید از فروشگاههای طرفقراردادو هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرمها و شرکتهایهمکار در اختیار کاربر قرار میگیرد، بدون اینکه جزئیات مدل کسبوکار، شیوه تأمین منابع مالی،شبکه همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.</p>" +
|
||||||
|
"<p class='section-title'>ماده ۲ - اقرار و آگاهی کاربر</p><p>۲-۱. کاربر اقرار مینماید که کلیه اطلاعات کلی لازم در خصوص نحوه فعالیت، مزایا، ریسکهای احتمالی," +
|
||||||
|
"سازوکار کلی استفاده از خدمات، و چارچوب کلی همکاری را از مراجع رسمی معرفیشده توسط کارابازاردریافت کرده، سؤالات خود را مطرح نموده و پاسخ مناسب را دریافت نموده است.</p><p>۲-۲. کاربر با امضای این قرارداد اقرار مینماید که:</p><ul><li>با اراده آزاد و بدون هرگونه اجبار، اکراه، فریب یا سوءاستفاده از ناآگاهی وارد این همکاری شده است.</li><li>از احتمال وجود ریسکهای مالی، اعتباری، قانونی و شبکهای مرتبط با فعالیت خود آگاه بوده و آن را میپذیرد.</li>" +
|
||||||
|
"<li>هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در شبکه معرفی، خرید از فروشگاهها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و بهعنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمیشود.</li></ul>" +
|
||||||
|
"<p class='section-title'>ماده ۳ - سلب مسئولیت کارابازار</p><p>۳-۱. کاربر صراحتاً میپذیرد که کارابازار صرفاً در چارچوب قوانین و مقررات حاکم و مطابق قراردادها و تفاهمنامههای خود با شرکای تجاری و پلتفرمهای همکار، خدمات و امکانات مشخصی را در اختیار کاربر قرار میدهد و هیچگونه تعهدی نسبت به:</p><ul><li>تحقق سود یا بازده مالی مشخص،</li><li>ثبات ارزش هرگونه اعتبار، امتیاز، یا منافع غیرنقدی که ممکن است در قالب طرحها به کاربر تخصیص یابد،</li>" +
|
||||||
|
"<li>عملکرد اشخاص ثالث (از جمله پلتفرمها، فروشگاهها، شرکتهای بیمه، ارائهدهندگان خدمات سلامت و هر شخص حقیقی یا حقوقی همکار)،</li><li>تصمیمات و اقدامات کاربر در جذب افراد جدید و ایجاد زیرمجموعه،</li></ul><p>نداشته و نخواهد داشت مگر در حدودی که بهصراحت در قرارداد یا قوانین آمره بر عهده کارابازار گذاشته شده است.</p><p>" +
|
||||||
|
"۳-۲. هرگونه خسارت، دعوی، تهدید، مطالبه، ادعا، شکایت یا پیگیری حقوقی که ناشی از تصمیمات شخصی کاربر،نحوه استفاده وی از تسهیلات و مزایا، جذب دیگران، خرید کالا و خدمات، یا تعاملات او با اشخاص ثالث باشد،مستقیماً متوجه خود کاربر است و کارابازار نسبت به آن هیچگونه مسئولیت مدنی، کیفری، مالی یا قراردادی ندارد," +
|
||||||
|
"مگر در مواردی که طبق قوانین آمره، مسئولیت صریح و غیرقابلاسقاط بر عهده کارابازار قرار گرفته باشد.</p><p>۳-۳. کاربر میپذیرد که هیچگونه ادعایی مبنی بر فریب، اغفال، ارائه اطلاعات نادرست یا وعدههای خارج ازچهارچوب رسمی از سوی کارابازار یا نمایندگان رسمی آن، پس از امضای این قرارداد، از وی مسموع نخواهد بود،مگر آنکه طبق رأی قطعی مرجع قضایی صالح، خلاف آن ثابت شود.</p><p class='section-title'>ماده ۴ - مسئولیت کاربر در قبال تهدید، ادعا و شکایت</p>" +
|
||||||
|
"<p>۴-۱. کاربر متعهد است در صورت طرح هرگونه تهدید، ادعا، مطالبه، شکایت یا پیگیری حقوقی از سوی اشخاص ثالث(از جمله افراد جذبشده توسط کاربر، زیرمجموعهها، خریداران معرفیشده یا سایر اشخاص)، که ناشی از عملکردشخصی کاربر، معرفیهای وی، شیوه تبلیغ، وعدههای خارج از چارچوب رسمی کارابازار، یا نقض قوانین و مقرراتباشد، خود رأساً پاسخگو باشد و کارابازار را از هرگونه مسئولیت و هزینه احتمالی در این خصوص مصون بدارد.</p><p>۴-۲. کاربر میپذیرد که:</p><ul><li>هرگونه تهدید یا ادعای بیجا، غیرمنطقی، غیرمستند یا مغایر با مفاد این قرارداد، متوجه شخص کاربر است.</li>" +
|
||||||
|
"<li>در صورت وارد آمدن خسارت مادی یا معنوی به کارابازار ناشی از چنین تهدیدات یا ادعاهایی، کارابازار حق دارد نسبت به مطالبه خسارت از کاربر، طبق قوانین و از طریق مراجع صالح اقدام نماید.</li></ul>" +
|
||||||
|
"<p class='section-title'>ماده ۵ - محرمانگی و عدم افشای جزئیات کسبوکار</p><p>۵-۱. کاربر میپذیرد که جزئیات فنی، مالی، ساختار شبکه، شیوه توزیع مزایا، قراردادهای داخلی کارابازار باشرکای تجاری و پلتفرمهای همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آنهاتوسط کاربر بدون مجوز کتبی کارابازار، مجاز نمیباشد.</p><p>۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسبوکار در این قرارداد را بهعنوان دلیل بطلان، فسخ یاادعای فریب علیه کارابازار از خود سلب مینماید.</p>" +
|
||||||
|
"<p class='section-title'>ماده ۶ - کد تأیید یکبارمصرف (OTP) و شناسه قرارداد</p><p>۶-۱. به منظور تأیید هویت کاربر و جایگزین کردن امضا در محیط غیرحضوری، برای این قرارداد یک شناسه یکتا(GUID) تولید شده و از طریق سامانه کارابازار، کد تأیید یکبارمصرف (OTP) مرتبط با آن برای کاربر ارسالمیگردد.</p>" +
|
||||||
|
"<p>۶-۲. کاربر با وارد کردن صحیح کد تأیید (OTP) در سامانه، اقرار مینماید که:</p><ul><li>مالک شماره تماس ثبتشده در این قرارداد است یا با اجازه قانونی مالک از آن استفاده میکند،</li><li>از محتوای قرارداد بهطور کامل آگاه است و آن را بدون ابهام و با رضایت کامل میپذیرد،</li><li>شناسه یکتا و OTP ارسالشده، معادل امضای الکترونیکی معتبر وی بر روی این قرارداد است.</li></ul>" +
|
||||||
|
"<p class='section-title'>ماده ۷ - مدت، اصلاح و حاکمیت قانون</p>" +
|
||||||
|
"<p>۷-۱. این قرارداد از تاریخ تأیید نهایی (ثبت OTP) نافذ و لازمالاجرا بوده و تا زمانی که همکاری کاربر باکارابازار ادامه دارد، معتبر خواهد بود؛ مگر آنکه مطابق قوانین یا توافق طرفین، خاتمه یابد.</p><p>۷-۲. هرگونه اصلاح در مفاد این قرارداد صرفاً از طریق اطلاعرسانی رسمی کارابازار و پذیرش کاربر (اعم ازامضای مکتوب، تأیید در سامانه، یا سایر روشهای الکترونیکی مورد تأیید کارابازار) معتبر خواهد بود.</p><p>۷-۳. این قرارداد از هر حیث، تابع قوانین و مقررات حاکم بر جمهوری اسلامی ایران بوده و در صورت بروز اختلاف،مراجع صالح قضایی محل استقرار کارابازار، صلاحیت رسیدگی خواهند داشت؛ مگر آنکه به نحو دیگری بین طرفین توافقشود." +
|
||||||
|
"</p><p class='section-title'>ماده ۸ - اقرار نهایی کاربر</p><p>کاربر با امضای این قرارداد (از طریق ثبت کد تأیید یکبارمصرف OTP متناظر با شناسه یکتا)، صریحاً اعلام مینماید که:" +
|
||||||
|
"</p><ul><li>کلیه مفاد قرارداد را بهدقت مطالعه نموده و آن را درک کرده است،</li>" +
|
||||||
|
"<li>پرسشهای خود را مطرح نموده و پاسخ روشن دریافت کرده است،</li><li>ریسکها، محدودیتها و حدود مسئولیت کارابازار را میپذیرد،</li><li>حق هرگونه ادعای مغایر با مفاد این قرارداد، بهویژه ادعاهای بیاساس، غیرمنطقی یا ناشی از برداشت نادرست شخصی را از خود سلب و اسقاط مینماید؛ مگر در حدودی که قانون بهطور آمره اجازه سلب آن را نداده باشد.</li></ul></div><div class='sign-section'></div><p class='small-text'></p><div class='box'><p><span class='field-label'>شناسه یکتای قرارداد :</span></p><p><span id='contract-guid'>" +
|
||||||
|
signGuid + "</span></p></div></body></html>";
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<bool> SavePersonalInfo()
|
private async Task<bool> SavePersonalInfo()
|
||||||
{
|
{
|
||||||
if (_stepTwoForm is null) return false;
|
if (_stepTwoForm is null) return false;
|
||||||
@@ -234,21 +346,14 @@ public partial class RegisterWizard
|
|||||||
await _stepTwoForm.Validate();
|
await _stepTwoForm.Validate();
|
||||||
if (!_stepTwoForm.IsValid) return false;
|
if (!_stepTwoForm.IsValid) return false;
|
||||||
|
|
||||||
|
_isSubmitting = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// _updateUserRequest.AvatarPath="test";
|
|
||||||
// _updateUserRequest.BirthDate=Timestamp.FromDateTime(DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc));
|
|
||||||
// _updateUserRequest.EmailNotifications = true;
|
|
||||||
// _updateUserRequest.PushNotifications = true;
|
|
||||||
// _updateUserRequest.SmsNotifications = true;
|
|
||||||
//
|
|
||||||
_updateUserRequest.FirstName = _model.FirstName;
|
_updateUserRequest.FirstName = _model.FirstName;
|
||||||
_updateUserRequest.LastName = _model.LastName;
|
_updateUserRequest.LastName = _model.LastName;
|
||||||
_updateUserRequest.NationalCode = _model.NationalCode.PersianToEnglish();
|
_updateUserRequest.NationalCode = _model.NationalCode.PersianToEnglish();
|
||||||
Console.WriteLine(_updateUserRequest.FirstName);
|
|
||||||
Console.WriteLine(_updateUserRequest.LastName);
|
|
||||||
Console.WriteLine(_updateUserRequest.NationalCode);
|
|
||||||
|
|
||||||
await UserContract.UpdateUserAsync(request: _updateUserRequest);
|
await UserContract.UpdateUserAsync(request: _updateUserRequest);
|
||||||
Snackbar.Add("اطلاعات شخصی با موفقیت ذخیره شد.", Severity.Success);
|
Snackbar.Add("اطلاعات شخصی با موفقیت ذخیره شد.", Severity.Success);
|
||||||
@@ -261,6 +366,7 @@ public partial class RegisterWizard
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
_isSubmitting = false;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using FrontOffice.BFF.User.Protobuf.Protos.User;
|
using FrontOffice.BFF.User.Protobuf.Protos.User;
|
||||||
using FrontOffice.BFF.User.Protobuf.Validator;
|
using FrontOffice.BFF.User.Protobuf.Validator;
|
||||||
|
using FrontOffice.Main.Utilities;
|
||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
@@ -47,6 +48,7 @@ public partial class AuthDialog : IDisposable
|
|||||||
|
|
||||||
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
||||||
[Inject] private UserContract.UserContractClient UserClient { get; set; } = default!;
|
[Inject] private UserContract.UserContractClient UserClient { get; set; } = default!;
|
||||||
|
[Inject] private AuthService AuthService { get; set; } = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
private IMudDialogInstance MudDialog { get; set; }
|
private IMudDialogInstance MudDialog { get; set; }
|
||||||
@@ -230,6 +232,17 @@ public partial class AuthDialog : IDisposable
|
|||||||
{
|
{
|
||||||
MudDialog?.Close();
|
MudDialog?.Close();
|
||||||
}
|
}
|
||||||
|
if (await AuthService.IsAuthenticatedAsync())
|
||||||
|
{
|
||||||
|
if (!(await AuthService.IsCompleteRegisterAsync()))
|
||||||
|
{
|
||||||
|
Navigation.NavigateTo(RouteConstants.Registration.Wizard);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Navigation.NavigateTo(RouteConstants.Profile.Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
@if (_isAuthenticated)
|
@if (_isAuthenticated)
|
||||||
{
|
{
|
||||||
<MudMenu Icon="@Icons.Material.Filled.Person" Color="Color.Inherit" Size="Size.Medium">
|
<MudMenu Icon="@Icons.Material.Filled.Person" Color="Color.Inherit" Size="Size.Medium">
|
||||||
<MudMenuItem OnClick="NavigateToProfile">پروفایل</MudMenuItem>
|
<MudMenuItem OnClick="NavigateToProfile" Disabled="@(AuthService.IsCompleteRegister())">پروفایل</MudMenuItem>
|
||||||
<MudDivider />
|
<MudDivider />
|
||||||
<MudMenuItem OnClick="Logout">خروج از حساب</MudMenuItem>
|
<MudMenuItem OnClick="Logout">خروج از حساب</MudMenuItem>
|
||||||
</MudMenu>
|
</MudMenu>
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ public partial class MainLayout
|
|||||||
{
|
{
|
||||||
Snackbar.Add(GlobalConstants.SuccessMsg, Severity.Success);
|
Snackbar.Add(GlobalConstants.SuccessMsg, Severity.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
Navigation.NavigateTo(RouteConstants.Main.MainPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NavigateToProfile()
|
private void NavigateToProfile()
|
||||||
|
|||||||
35
src/FrontOffice.Main/Shared/SimpleOtpDialog.razor
Normal file
35
src/FrontOffice.Main/Shared/SimpleOtpDialog.razor
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
@using MudBlazor
|
||||||
|
|
||||||
|
<MudDialog>
|
||||||
|
<DialogContent>
|
||||||
|
<MudText Typo="Typo.body1" Class="mb-3">@ContentText</MudText>
|
||||||
|
<MudTextField @bind-Value="OtpCode"
|
||||||
|
Label="کد تأیید"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
InputType="InputType.Text"
|
||||||
|
MaxLength="6"
|
||||||
|
Immediate="true"
|
||||||
|
Required="true"
|
||||||
|
RequiredError="کد تایید الزامی است"
|
||||||
|
FullWidth="true" />
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton Variant="Variant.Text" OnClick="Cancel">انصراف</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="Submit" Disabled="string.IsNullOrWhiteSpace(OtpCode)">@ButtonText</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[CascadingParameter]
|
||||||
|
private IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public string ContentText { get; set; } = "";
|
||||||
|
[Parameter] public string ButtonText { get; set; } = "تأیید";
|
||||||
|
|
||||||
|
private string? OtpCode { get; set; }
|
||||||
|
|
||||||
|
private void Cancel() => MudDialog.Cancel();
|
||||||
|
|
||||||
|
private void Submit() => MudDialog.Close(DialogResult.Ok(OtpCode));
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
|
||||||
namespace FrontOffice.Main.Utilities;
|
namespace FrontOffice.Main.Utilities;
|
||||||
|
|
||||||
@@ -9,14 +10,16 @@ public class AuthService
|
|||||||
private readonly ILocalStorageService _localStorage;
|
private readonly ILocalStorageService _localStorage;
|
||||||
private readonly NavigationManager _navigation;
|
private readonly NavigationManager _navigation;
|
||||||
private readonly ISnackbar _snackbar;
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly UserAuthInfo _userAuthInfo;
|
||||||
|
|
||||||
private const string TokenStorageKey = "auth:token";
|
private const string TokenStorageKey = "auth:token";
|
||||||
|
|
||||||
public AuthService(ILocalStorageService localStorage, NavigationManager navigation, ISnackbar snackbar)
|
public AuthService(ILocalStorageService localStorage, NavigationManager navigation, ISnackbar snackbar, UserAuthInfo userAuthInfo)
|
||||||
{
|
{
|
||||||
_localStorage = localStorage;
|
_localStorage = localStorage;
|
||||||
_navigation = navigation;
|
_navigation = navigation;
|
||||||
_snackbar = snackbar;
|
_snackbar = snackbar;
|
||||||
|
_userAuthInfo = userAuthInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> IsAuthenticatedAsync()
|
public async Task<bool> IsAuthenticatedAsync()
|
||||||
@@ -29,6 +32,54 @@ public class AuthService
|
|||||||
{
|
{
|
||||||
return await _localStorage.GetItemAsync<string>(TokenStorageKey);
|
return await _localStorage.GetItemAsync<string>(TokenStorageKey);
|
||||||
}
|
}
|
||||||
|
public async Task<bool> IsCompleteRegisterAsync()
|
||||||
|
{
|
||||||
|
await InitUserAuthInfo();
|
||||||
|
if (_userAuthInfo.NationalCode ==null || _userAuthInfo.FirstName == null || _userAuthInfo.LastName == null || !_userAuthInfo.IsSignMainContract)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public bool IsCompleteRegister()
|
||||||
|
{
|
||||||
|
InitUserAuthInfo().GetAwaiter();
|
||||||
|
if (_userAuthInfo.NationalCode ==null || _userAuthInfo.FirstName == null || _userAuthInfo.LastName == null || _userAuthInfo.IsSignMainContract)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public async Task<UserAuthInfo> GetUserAuthInfo()
|
||||||
|
{
|
||||||
|
await InitUserAuthInfo();
|
||||||
|
return _userAuthInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InitUserAuthInfo()
|
||||||
|
{
|
||||||
|
var claims = await GetTokenClaimsAsync();
|
||||||
|
_userAuthInfo.UserClaims= claims;
|
||||||
|
var firstName = claims.FirstOrDefault(c => c.key == "FirstName").value;
|
||||||
|
var lastName = claims.FirstOrDefault(c => c.key == "LastName").value;
|
||||||
|
var nationalCode = claims.FirstOrDefault(c => c.key == "NationalCode").value;
|
||||||
|
var mobileNumber = claims.FirstOrDefault(c => c.key == "MobileNumber").value;
|
||||||
|
var isSignMainContractStr = claims.FirstOrDefault(c => c.key == "IsSignMainContract").value;
|
||||||
|
_userAuthInfo.FirstName = firstName ?? string.Empty;
|
||||||
|
_userAuthInfo.LastName = lastName ?? string.Empty;
|
||||||
|
_userAuthInfo.NationalCode = nationalCode ?? string.Empty;
|
||||||
|
_userAuthInfo.MobileNumber = mobileNumber ?? string.Empty;
|
||||||
|
_userAuthInfo.IsSignMainContract = bool.TryParse(isSignMainContractStr, out var isSignMainContract) && isSignMainContract;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<(string key, string value)>?> GetTokenClaimsAsync()
|
||||||
|
{
|
||||||
|
var token = await GetTokenAsync();
|
||||||
|
if (string.IsNullOrEmpty(token)) return null;
|
||||||
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
var jwtToken = handler.ReadJwtToken(token);
|
||||||
|
return jwtToken.Claims.Select(c => (c.Type, c.Value)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task LogoutAsync()
|
public async Task LogoutAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
11
src/FrontOffice.Main/Utilities/UserAuthInfo.cs
Normal file
11
src/FrontOffice.Main/Utilities/UserAuthInfo.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace FrontOffice.Main.Utilities;
|
||||||
|
|
||||||
|
public class UserAuthInfo
|
||||||
|
{
|
||||||
|
public List<(string key, string value)> UserClaims { get; set; }
|
||||||
|
public string? FirstName { get; set; }
|
||||||
|
public string? LastName { get; set; }
|
||||||
|
public string? NationalCode { get; set; }
|
||||||
|
public string? MobileNumber { get; set; }
|
||||||
|
public bool IsSignMainContract { get; set; }
|
||||||
|
}
|
||||||
219
src/FrontOffice.Main/wwwroot/test.html
Normal file
219
src/FrontOffice.Main/wwwroot/test.html
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fa" dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>قرارداد تعهد و سلب مسئولیت کارابازار</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
direction: rtl;
|
||||||
|
text-align: justify;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.8;
|
||||||
|
margin: 40px;
|
||||||
|
}
|
||||||
|
h1, h2 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.section-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.contract-info, .sign-section {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.field-label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
border: 1px solid #000;
|
||||||
|
padding: 8px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.small-text {
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>قرارداد تعهد و سلب مسئولیت</h1>
|
||||||
|
<h2>بین کارابازار و کاربر</h2>
|
||||||
|
|
||||||
|
<div class="contract-info">
|
||||||
|
<p>
|
||||||
|
این قرارداد تعهد و سلب مسئولیت («قرارداد») در تاریخ
|
||||||
|
<span class="field-label">....... / ....... / ........</span>
|
||||||
|
بین:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
1. شرکت/مجموعه <span class="field-label">کارابازار</span> (که از این پس «کارابازار» نامیده میشود)،
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
2. شخص حقیقی زیر (که از این پس «کاربر» نامیده میشود):
|
||||||
|
</p>
|
||||||
|
<div class="box">
|
||||||
|
<p><span class="field-label">نام و نام خانوادگی کاربر:</span> ..........................................................</p>
|
||||||
|
<p><span class="field-label">شماره ملی:</span> ..........................................................</p>
|
||||||
|
<p><span class="field-label">شماره تماس:</span> ..........................................................</p>
|
||||||
|
<p><span class="field-label">آدرس:</span> ..................................................................................................................</p>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
کارابازار و کاربر که در این قرارداد جداگانه «طرف» و مجموعاً «طرفین» نامیده میشوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا مینمایند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="section-title">ماده ۱ - موضوع قرارداد</p>
|
||||||
|
<p>
|
||||||
|
موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر از
|
||||||
|
خدمات، باشگاه مشتریان، مزایا، طرحهای همکاری، شبکه معرفی، خرید از فروشگاههای طرفقرارداد
|
||||||
|
و هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرمها و شرکتهای
|
||||||
|
همکار در اختیار کاربر قرار میگیرد، بدون اینکه جزئیات مدل کسبوکار، شیوه تأمین منابع مالی،
|
||||||
|
شبکه همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="section-title">ماده ۲ - اقرار و آگاهی کاربر</p>
|
||||||
|
<p>
|
||||||
|
۲-۱. کاربر اقرار مینماید که کلیه اطلاعات کلی لازم در خصوص نحوه فعالیت، مزایا، ریسکهای احتمالی،
|
||||||
|
سازوکار کلی استفاده از خدمات، و چارچوب کلی همکاری را از مراجع رسمی معرفیشده توسط کارابازار
|
||||||
|
دریافت کرده، سؤالات خود را مطرح نموده و پاسخ مناسب را دریافت نموده است.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۲-۲. کاربر با امضای این قرارداد اقرار مینماید که:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>با اراده آزاد و بدون هرگونه اجبار، اکراه، فریب یا سوءاستفاده از ناآگاهی وارد این همکاری شده است.</li>
|
||||||
|
<li>از احتمال وجود ریسکهای مالی، اعتباری، قانونی و شبکهای مرتبط با فعالیت خود آگاه بوده و آن را میپذیرد.</li>
|
||||||
|
<li>هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در شبکه معرفی، خرید از فروشگاهها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و بهعنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمیشود.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p class="section-title">ماده ۳ - سلب مسئولیت کارابازار</p>
|
||||||
|
<p>
|
||||||
|
۳-۱. کاربر صراحتاً میپذیرد که کارابازار صرفاً در چارچوب قوانین و مقررات حاکم و مطابق قراردادها و تفاهمنامههای خود با شرکای تجاری و پلتفرمهای همکار، خدمات و امکانات مشخصی را در اختیار کاربر قرار میدهد و هیچگونه تعهدی نسبت به:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>تحقق سود یا بازده مالی مشخص،</li>
|
||||||
|
<li>ثبات ارزش هرگونه اعتبار، امتیاز، یا منافع غیرنقدی که ممکن است در قالب طرحها به کاربر تخصیص یابد،</li>
|
||||||
|
<li>عملکرد اشخاص ثالث (از جمله پلتفرمها، فروشگاهها، شرکتهای بیمه، ارائهدهندگان خدمات سلامت و هر شخص حقیقی یا حقوقی همکار)،</li>
|
||||||
|
<li>تصمیمات و اقدامات کاربر در جذب افراد جدید و ایجاد زیرمجموعه،</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
نداشته و نخواهد داشت مگر در حدودی که بهصراحت در قرارداد یا قوانین آمره بر عهده کارابازار گذاشته شده است.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۳-۲. هرگونه خسارت، دعوی، تهدید، مطالبه، ادعا، شکایت یا پیگیری حقوقی که ناشی از تصمیمات شخصی کاربر،
|
||||||
|
نحوه استفاده وی از تسهیلات و مزایا، جذب دیگران، خرید کالا و خدمات، یا تعاملات او با اشخاص ثالث باشد،
|
||||||
|
مستقیماً متوجه خود کاربر است و کارابازار نسبت به آن هیچگونه مسئولیت مدنی، کیفری، مالی یا قراردادی ندارد،
|
||||||
|
مگر در مواردی که طبق قوانین آمره، مسئولیت صریح و غیرقابلاسقاط بر عهده کارابازار قرار گرفته باشد.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۳-۳. کاربر میپذیرد که هیچگونه ادعایی مبنی بر فریب، اغفال، ارائه اطلاعات نادرست یا وعدههای خارج از
|
||||||
|
چهارچوب رسمی از سوی کارابازار یا نمایندگان رسمی آن، پس از امضای این قرارداد، از وی مسموع نخواهد بود،
|
||||||
|
مگر آنکه طبق رأی قطعی مرجع قضایی صالح، خلاف آن ثابت شود.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="section-title">ماده ۴ - مسئولیت کاربر در قبال تهدید، ادعا و شکایت</p>
|
||||||
|
<p>
|
||||||
|
۴-۱. کاربر متعهد است در صورت طرح هرگونه تهدید، ادعا، مطالبه، شکایت یا پیگیری حقوقی از سوی اشخاص ثالث
|
||||||
|
(از جمله افراد جذبشده توسط کاربر، زیرمجموعهها، خریداران معرفیشده یا سایر اشخاص)، که ناشی از عملکرد
|
||||||
|
شخصی کاربر، معرفیهای وی، شیوه تبلیغ، وعدههای خارج از چارچوب رسمی کارابازار، یا نقض قوانین و مقررات
|
||||||
|
باشد، خود رأساً پاسخگو باشد و کارابازار را از هرگونه مسئولیت و هزینه احتمالی در این خصوص مصون بدارد.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۴-۲. کاربر میپذیرد که:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>هرگونه تهدید یا ادعای بیجا، غیرمنطقی، غیرمستند یا مغایر با مفاد این قرارداد، متوجه شخص کاربر است.</li>
|
||||||
|
<li>در صورت وارد آمدن خسارت مادی یا معنوی به کارابازار ناشی از چنین تهدیدات یا ادعاهایی، کارابازار حق دارد نسبت به مطالبه خسارت از کاربر، طبق قوانین و از طریق مراجع صالح اقدام نماید.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p class="section-title">ماده ۵ - محرمانگی و عدم افشای جزئیات کسبوکار</p>
|
||||||
|
<p>
|
||||||
|
۵-۱. کاربر میپذیرد که جزئیات فنی، مالی، ساختار شبکه، شیوه توزیع مزایا، قراردادهای داخلی کارابازار با
|
||||||
|
شرکای تجاری و پلتفرمهای همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آنها
|
||||||
|
توسط کاربر بدون مجوز کتبی کارابازار، مجاز نمیباشد.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسبوکار در این قرارداد را بهعنوان دلیل بطلان، فسخ یا
|
||||||
|
ادعای فریب علیه کارابازار از خود سلب مینماید.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="section-title">ماده ۶ - کد تأیید یکبارمصرف (OTP) و شناسه قرارداد</p>
|
||||||
|
<p>
|
||||||
|
۶-۱. به منظور تأیید هویت کاربر و جایگزین کردن امضا در محیط غیرحضوری، برای این قرارداد یک شناسه یکتا
|
||||||
|
(GUID) تولید شده و از طریق سامانه کارابازار، کد تأیید یکبارمصرف (OTP) مرتبط با آن برای کاربر ارسال
|
||||||
|
میگردد.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۶-۲. کاربر با وارد کردن صحیح کد تأیید (OTP) در سامانه، اقرار مینماید که:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>مالک شماره تماس ثبتشده در این قرارداد است یا با اجازه قانونی مالک از آن استفاده میکند،</li>
|
||||||
|
<li>از محتوای قرارداد بهطور کامل آگاه است و آن را بدون ابهام و با رضایت کامل میپذیرد،</li>
|
||||||
|
<li>شناسه یکتا و OTP ارسالشده، معادل امضای الکترونیکی معتبر وی بر روی این قرارداد است.</li>
|
||||||
|
</ul>
|
||||||
|
<div class="box">
|
||||||
|
<p><span class="field-label">شناسه یکتای قرارداد (GUID):</span></p>
|
||||||
|
<p><span id="contract-guid">[GUID_HERE]</span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="section-title">ماده ۷ - مدت، اصلاح و حاکمیت قانون</p>
|
||||||
|
<p>
|
||||||
|
۷-۱. این قرارداد از تاریخ تأیید نهایی (ثبت OTP) نافذ و لازمالاجرا بوده و تا زمانی که همکاری کاربر با
|
||||||
|
کارابازار ادامه دارد، معتبر خواهد بود؛ مگر آنکه مطابق قوانین یا توافق طرفین، خاتمه یابد.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۷-۲. هرگونه اصلاح در مفاد این قرارداد صرفاً از طریق اطلاعرسانی رسمی کارابازار و پذیرش کاربر (اعم از
|
||||||
|
امضای مکتوب، تأیید در سامانه، یا سایر روشهای الکترونیکی مورد تأیید کارابازار) معتبر خواهد بود.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
۷-۳. این قرارداد از هر حیث، تابع قوانین و مقررات حاکم بر جمهوری اسلامی ایران بوده و در صورت بروز اختلاف،
|
||||||
|
مراجع صالح قضایی محل استقرار کارابازار، صلاحیت رسیدگی خواهند داشت؛ مگر آنکه به نحو دیگری بین طرفین توافق
|
||||||
|
شود.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="section-title">ماده ۸ - اقرار نهایی کاربر</p>
|
||||||
|
<p>
|
||||||
|
کاربر با امضای این قرارداد (از طریق ثبت کد تأیید یکبارمصرف OTP متناظر با شناسه یکتا)، صریحاً اعلام مینماید که:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>کلیه مفاد قرارداد را بهدقت مطالعه نموده و آن را درک کرده است،</li>
|
||||||
|
<li>پرسشهای خود را مطرح نموده و پاسخ روشن دریافت کرده است،</li>
|
||||||
|
<li>ریسکها، محدودیتها و حدود مسئولیت کارابازار را میپذیرد،</li>
|
||||||
|
<li>حق هرگونه ادعای مغایر با مفاد این قرارداد، بهویژه ادعاهای بیاساس، غیرمنطقی یا ناشی از برداشت نادرست شخصی را از خود سلب و اسقاط مینماید؛ مگر در حدودی که قانون بهطور آمره اجازه سلب آن را نداده باشد.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sign-section">
|
||||||
|
<div class="box">
|
||||||
|
<p class="field-label">اطلاعات و تأیید کاربر:</p>
|
||||||
|
<p>نام و نام خانوادگی: ..........................................................</p>
|
||||||
|
<p>شماره ملی: ..........................................................</p>
|
||||||
|
<p>تاریخ: ....... / ....... / ........</p>
|
||||||
|
<p>امضا / تأیید الکترونیکی (OTP متناظر با GUID فوق):</p>
|
||||||
|
<p>..........................................................</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small-text">
|
||||||
|
توضیح: این متن در حکم یک نمونه قرارداد تعهد و سلب مسئولیت است و جایگزین مشاوره حقوقی تخصصی نیست.
|
||||||
|
پیشنهاد میشود برای انطباق کامل با قوانین و نیازهای خاص کسبوکار، متن توسط مشاور حقوقی یا وکیل بررسی و در صورت لزوم اصلاح گردد.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
Reference in New Issue
Block a user