diff --git a/GanjooRazor/GanjooRazor.csproj b/GanjooRazor/GanjooRazor.csproj
index ea3dca9f..52211c15 100644
--- a/GanjooRazor/GanjooRazor.csproj
+++ b/GanjooRazor/GanjooRazor.csproj
@@ -4,16 +4,6 @@
net5.0-windows
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
diff --git a/GanjooRazor/Pages/Index.cshtml.cs b/GanjooRazor/Pages/Index.cshtml.cs
index b857a99a..c0efadcc 100644
--- a/GanjooRazor/Pages/Index.cshtml.cs
+++ b/GanjooRazor/Pages/Index.cshtml.cs
@@ -479,7 +479,7 @@ namespace GanjooRazor.Pages
if(!_memoryCache.TryGetValue(cacheKey, out List poets))
{
var resPoets = await _ganjoorService.GetPoets(true, false);
- if(!string.IsNullOrEmpty(resPoets.ExceptionString))
+ if(string.IsNullOrEmpty(resPoets.ExceptionString))
{
poets = new List(resPoets.Result);
_memoryCache.Set(cacheKey, poets);
@@ -518,7 +518,7 @@ namespace GanjooRazor.Pages
if (!IsHomePage)
{
var pageRes = await _ganjoorService.GetPageByUrl(Request.Path, true);
- if(!string.IsNullOrEmpty(pageRes.ExceptionString))
+ if(string.IsNullOrEmpty(pageRes.ExceptionString))
{
if(pageRes.Result == null)
{
diff --git a/GanjooRazor/Startup.cs b/GanjooRazor/Startup.cs
index 537a77d1..2463187e 100644
--- a/GanjooRazor/Startup.cs
+++ b/GanjooRazor/Startup.cs
@@ -1,9 +1,30 @@
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.IdentityModel.Tokens;
+using RMuseum.DbContext;
+using RMuseum.Models.Auth.Memory;
+using RMuseum.Services;
+using RMuseum.Services.Implementation;
+using RMuseum.Services.Implementationa;
+using RSecurityBackend.Authorization;
+using RSecurityBackend.DbContext;
+using RSecurityBackend.Models.Auth.Db;
+using RSecurityBackend.Models.Auth.Memory;
+using RSecurityBackend.Models.Mail;
+using RSecurityBackend.Services;
+using RSecurityBackend.Services.Implementation;
+using RSecurityBackend.Utilities;
+using System;
+using System.Text;
using System.Text.Encodings.Web;
using System.Text.Unicode;
+using System.Threading.Tasks;
namespace GanjooRazor
{
@@ -18,6 +39,9 @@ namespace GanjooRazor
public void ConfigureServices(IServiceCollection services)
{
+ services.AddHttpClient();
+
+
services.AddSingleton(
HtmlEncoder.Create(allowedRanges: new[] { UnicodeRanges.BasicLatin,
UnicodeRanges.Arabic }));
@@ -26,6 +50,159 @@ namespace GanjooRazor
{
options.Conventions.AddPageRoute("/index", "{*url}");
});
+
+ services.AddDbContext();
+
+ Audit.Core.Configuration.JsonSettings.ContractResolver = AuditNetEnvironmentSkippingContractResolver.Instance;
+ Audit.Core.Configuration.DataProvider = new RAuditDataProvider(Configuration.GetConnectionString("DefaultConnection"));
+
+ services.AddIdentityCore(
+ options =>
+ {
+ // Password settings.
+ options.Password.RequireDigit = true;
+ options.Password.RequireLowercase = true;
+ options.Password.RequireNonAlphanumeric = false;
+ options.Password.RequireUppercase = false;
+ options.Password.RequiredLength = 6;
+ options.Password.RequiredUniqueChars = 1;
+
+ // Lockout settings.
+ options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
+ options.Lockout.MaxFailedAccessAttempts = 5;
+ options.Lockout.AllowedForNewUsers = true;
+
+ // User settings.
+ options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
+ options.User.RequireUniqueEmail = false;
+ }
+ ).AddErrorDescriber();
+
+
+ new IdentityBuilder(typeof(RAppUser), typeof(RAppRole), services)
+ .AddRoleManager>()
+ .AddSignInManager>()
+ .AddEntityFrameworkStores()
+ .AddErrorDescriber();
+
+ services.AddAuthentication(options =>
+ {
+ options.DefaultScheme = "bearer";
+ }).AddJwtBearer("bearer", options =>
+ {
+ options.TokenValidationParameters = new TokenValidationParameters
+ {
+ ValidateAudience = false,
+ ValidAudience = "Everyone",
+ ValidateIssuer = true,
+ ValidIssuer = "Ganjoor",
+
+ ValidateIssuerSigningKey = true,
+ IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes($"{Configuration.GetSection("Security")["Secret"]}")),
+
+ ValidateLifetime = true, //validate the expiration and not before values in the token
+
+ ClockSkew = TimeSpan.Zero
+ };
+
+ options.Events = new JwtBearerEvents
+ {
+ OnAuthenticationFailed = context =>
+ {
+ if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
+ {
+ context.Response.Headers.Add("Token-Expired", "true");
+ }
+ return Task.CompletedTask;
+ }
+ };
+
+ });
+
+ services.AddAuthorization(options =>
+ {
+ //this is the default policy to make sure the use session has not yet been deleted by him/her from another client
+ //or by an admin (Authorize with no policy should fail on deleted sessions)
+ var defPolicy = new AuthorizationPolicyBuilder();
+ defPolicy.Requirements.Add(new UserGroupPermissionRequirement("null", "null"));
+ options.DefaultPolicy = defPolicy.Build();
+
+
+ foreach (SecurableItem Item in RMuseumSecurableItem.Items)
+ {
+ foreach (SecurableItemOperation Operation in Item.Operations)
+ {
+ options.AddPolicy($"{Item.ShortName}:{Operation.ShortName}", policy => policy.Requirements.Add(new UserGroupPermissionRequirement(Item.ShortName, Operation.ShortName)));
+ }
+ }
+ });
+
+ services.AddMemoryCache();
+
+
+
+ //security context maps to main db context
+ services.AddTransient, RMuseumDbContext>();
+
+ //captcha service
+ services.AddTransient();
+
+
+ //generic image file service
+ services.AddTransient();
+
+ //app user services
+ services.AddTransient();
+
+ //user groups services
+ services.AddTransient();
+
+ //audit service
+ services.AddTransient();
+
+ //user permission checker
+ services.AddTransient();
+
+ //secret generator
+ services.AddTransient();
+
+ // email service
+ services.AddTransient();
+ services.Configure(Configuration);
+
+ //picture file service
+ services.AddTransient();
+
+ //messaging service
+ services.AddTransient();
+
+ //artifact service
+ services.AddTransient();
+
+ //audio service
+ services.AddTransient();
+
+ //ganjoor service
+ services.AddTransient();
+
+ //music catalogue service
+ services.AddTransient();
+
+ //long running job service
+ services.AddTransient();
+
+ //upload limit for IIS
+ services.Configure(options =>
+ {
+ options.MaxRequestBodySize = int.Parse(Configuration.GetSection("IIS")["UploadLimit"]);
+ });
+
+
+ services.AddHostedService();
+ services.AddSingleton();
+
+
+
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -39,6 +216,8 @@ namespace GanjooRazor
app.UseRouting();
+ app.UseAuthentication();
+
app.UseAuthorization();
app.UseEndpoints(endpoints =>
diff --git a/GanjooRazor/appsettings.json b/GanjooRazor/appsettings.json
index 78465e88..3b0efb71 100644
--- a/GanjooRazor/appsettings.json
+++ b/GanjooRazor/appsettings.json
@@ -7,6 +7,9 @@
}
},
"AllowedHosts": "*",
+ "GoogleAnalyticsCode": "",
+ "APIRoot": "https://ganjgah.ir",
+ "GlobalAPIRoot": "https://ganjgah.ir",
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=museum;Trusted_Connection=True;MultipleActiveResultSets=true"
},