files tree made better.
This commit is contained in:
parent
ffbf032480
commit
ccc91bbf19
1630 changed files with 18209 additions and 41860 deletions
28
src/Yavsc/Startup/BundleConfig.cs
Normal file
28
src/Yavsc/Startup/BundleConfig.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
using System.Web.Optimization;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
public class BundleConfig
|
||||
{
|
||||
public static void RegisterBundles(BundleCollection bundles)
|
||||
{
|
||||
bundles.Add(new ScriptBundle("~/bundles/bootjq").Include(
|
||||
"~/bower_components/bootstrap/dist/js",
|
||||
"~/bower_components/jquery/dist/js",
|
||||
"~/bower_components/jquery.validation/dist/js",
|
||||
"~/bower_components/jquery-validation-unobtrusive/dist/js",
|
||||
"~/bower_components/bootstrap-datepicker/dist/js"));
|
||||
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
|
||||
));
|
||||
bundles.Add(new ScriptBundle("~/bundles/markdown").Include(
|
||||
"~/bower_components/dropzone/dist/min/dropzone-amd-module.min.js",
|
||||
"~/bower_components/dropzone/dist/min/dropzone.min.js"
|
||||
));
|
||||
bundles.Add(new StyleBundle("~/Content/markdown").Include(
|
||||
"~/bower_components/dropzone/dist/min/basic.min.css",
|
||||
"~/bower_components/dropzone/dist/min/dropzone.min.css"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Yavsc/Startup/Startup.DataProtection.cs
Normal file
40
src/Yavsc/Startup/Startup.DataProtection.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Microsoft.AspNet.DataProtection.Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
public partial class Startup
|
||||
{
|
||||
public void ConfigureProtectionServices(IServiceCollection services)
|
||||
{
|
||||
|
||||
services.AddDataProtection();
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IApplicationDiscriminator),
|
||||
typeof(SystemWebApplicationDiscriminator)));
|
||||
|
||||
services.ConfigureDataProtection(configure =>
|
||||
{
|
||||
configure.SetApplicationName(Configuration["Site:Title"]);
|
||||
configure.SetDefaultKeyLifetime(TimeSpan.FromDays(45));
|
||||
configure.PersistKeysToFileSystem(
|
||||
new DirectoryInfo(Configuration["DataProtection:Keys:Dir"]));
|
||||
});
|
||||
|
||||
}
|
||||
private sealed class SystemWebApplicationDiscriminator : IApplicationDiscriminator
|
||||
{
|
||||
private readonly Lazy<string> _lazyDiscriminator = new Lazy<string>(GetAppDiscriminatorCore);
|
||||
|
||||
public string Discriminator => _lazyDiscriminator.Value;
|
||||
|
||||
private static string GetAppDiscriminatorCore()
|
||||
{
|
||||
return HttpRuntime.AppDomainAppId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
src/Yavsc/Startup/Startup.FileServer.cs
Normal file
89
src/Yavsc/Startup/Startup.FileServer.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
using System.IO;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.FileProviders;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.StaticFiles;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Yavsc.Abstract.FileSystem;
|
||||
using Yavsc.ViewModels.Auth;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
public partial class Startup
|
||||
{
|
||||
public static FileServerOptions UserFilesOptions { get; private set; }
|
||||
public static FileServerOptions GitOptions { get; private set; }
|
||||
|
||||
public static FileServerOptions AvatarsOptions { get; set; }
|
||||
public void ConfigureFileServerApp(IApplicationBuilder app,
|
||||
SiteSettings siteSettings, IHostingEnvironment env, IAuthorizationService authorizationService)
|
||||
{
|
||||
var userFilesDirInfo = new DirectoryInfo( siteSettings.Blog );
|
||||
AbstractFileSystemHelpers.UserFilesDirName = userFilesDirInfo.FullName;
|
||||
|
||||
if (!userFilesDirInfo.Exists) userFilesDirInfo.Create();
|
||||
|
||||
UserFilesOptions = new FileServerOptions()
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(AbstractFileSystemHelpers.UserFilesDirName),
|
||||
RequestPath = new PathString(Constants.UserFilesPath),
|
||||
EnableDirectoryBrowsing = env.IsDevelopment(),
|
||||
};
|
||||
UserFilesOptions.EnableDefaultFiles=true;
|
||||
UserFilesOptions.StaticFileOptions.ServeUnknownFileTypes=true;
|
||||
|
||||
/* TODO needs a better design, at implementation time (don't use database, but in memory data)
|
||||
UserFilesOptions.StaticFileOptions.OnPrepareResponse += async context =>
|
||||
{
|
||||
var uname = context.Context.User.GetUserName();
|
||||
var path = context.Context.Request.Path;
|
||||
var result = await authorizationService.AuthorizeAsync(context.Context.User, new ViewFileContext
|
||||
{ UserName = uname, File = context.File, Path = path } , new ViewRequirement());
|
||||
};
|
||||
*/
|
||||
var avatarsDirInfo = new DirectoryInfo(Startup.SiteSetup.Avatars);
|
||||
if (!avatarsDirInfo.Exists) avatarsDirInfo.Create();
|
||||
AvatarsDirName = avatarsDirInfo.FullName;
|
||||
|
||||
AvatarsOptions = new FileServerOptions()
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(AvatarsDirName),
|
||||
RequestPath = new PathString(Constants.AvatarsPath),
|
||||
EnableDirectoryBrowsing = env.IsDevelopment()
|
||||
};
|
||||
|
||||
|
||||
var gitdirinfo = new DirectoryInfo(Startup.SiteSetup.GitRepository);
|
||||
GitDirName = gitdirinfo.FullName;
|
||||
if (!gitdirinfo.Exists) gitdirinfo.Create();
|
||||
GitOptions = new FileServerOptions()
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(GitDirName),
|
||||
RequestPath = new PathString(Constants.GitPath),
|
||||
EnableDirectoryBrowsing = env.IsDevelopment(),
|
||||
};
|
||||
GitOptions.DefaultFilesOptions.DefaultFileNames.Add("index.md");
|
||||
GitOptions.StaticFileOptions.ServeUnknownFileTypes = true;
|
||||
logger.LogInformation( $"{GitDirName}");
|
||||
GitOptions.StaticFileOptions.OnPrepareResponse+= OnPrepareGitRepoResponse;
|
||||
|
||||
app.UseFileServer(UserFilesOptions);
|
||||
|
||||
app.UseFileServer(AvatarsOptions);
|
||||
|
||||
app.UseFileServer(GitOptions);
|
||||
app.UseStaticFiles();
|
||||
}
|
||||
|
||||
static void OnPrepareGitRepoResponse(StaticFileResponseContext context)
|
||||
{
|
||||
if (context.File.Name.EndsWith(".ansi.log"))
|
||||
{
|
||||
context.Context.Response.Redirect("/Git"+context.Context.Request.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
229
src/Yavsc/Startup/Startup.OAuth.cs
Normal file
229
src/Yavsc/Startup/Startup.OAuth.cs
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
using System;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.Authentication;
|
||||
using Microsoft.AspNet.Authentication.Cookies;
|
||||
using Microsoft.AspNet.Authentication.Facebook;
|
||||
using Microsoft.AspNet.Authentication.Twitter;
|
||||
using Microsoft.AspNet.Authentication.JwtBearer;
|
||||
using Microsoft.AspNet.Authentication.OAuth;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.EntityFramework;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Microsoft.Extensions.WebEncoders;
|
||||
using OAuth.AspNet.AuthServer;
|
||||
using OAuth.AspNet.Tokens;
|
||||
using Google.Apis.Util.Store;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Google.Apis.Auth.OAuth2.Responses;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
using Auth;
|
||||
using Extensions;
|
||||
using Models;
|
||||
using Helpers.Google;
|
||||
|
||||
public partial class Startup
|
||||
{
|
||||
public static CookieAuthenticationOptions ExternalCookieAppOptions { get; private set; }
|
||||
|
||||
public static IdentityOptions IdentityAppOptions { get; set; }
|
||||
public static FacebookOptions FacebookAppOptions { get; private set; }
|
||||
|
||||
public static TwitterOptions TwitterAppOptions { get; private set; }
|
||||
public static OAuthAuthorizationServerOptions OAuthServerAppOptions { get; private set; }
|
||||
|
||||
|
||||
public static YavscGoogleOptions YavscGoogleAppOptions { get; private set; }
|
||||
public static MonoDataProtectionProvider ProtectionProvider { get; private set; }
|
||||
|
||||
// public static CookieAuthenticationOptions BearerCookieOptions { get; private set; }
|
||||
|
||||
private void ConfigureOAuthServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<SharedAuthenticationOptions>(options => options.SignInScheme = Constants.ApplicationAuthenticationSheme);
|
||||
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<OAuth2AppSettings>), typeof(OptionsManager<OAuth2AppSettings>)));
|
||||
// used by the YavscGoogleOAuth middelware (TODO drop it)
|
||||
services.AddTransient<Microsoft.Extensions.WebEncoders.UrlEncoder, UrlEncoder>();
|
||||
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.SignInScheme = Constants.ExternalAuthenticationSheme;
|
||||
});
|
||||
|
||||
ProtectionProvider = new MonoDataProtectionProvider(Configuration["Site:Title"]); ;
|
||||
services.AddInstance<MonoDataProtectionProvider>
|
||||
(ProtectionProvider);
|
||||
|
||||
services.AddIdentity<ApplicationUser, IdentityRole>(
|
||||
option =>
|
||||
{
|
||||
IdentityAppOptions = option;
|
||||
option.User.AllowedUserNameCharacters += " ";
|
||||
option.User.RequireUniqueEmail = true;
|
||||
// option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme;
|
||||
option.Cookies.ApplicationCookie.LoginPath = "/signin";
|
||||
// option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme;
|
||||
/*
|
||||
option.Cookies.ApplicationCookie.DataProtectionProvider = protector;
|
||||
option.Cookies.ApplicationCookie.LoginPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
option.Cookies.ApplicationCookie.AccessDeniedPath = new PathString(Constants.AccessDeniedPath.Substring(1));
|
||||
option.Cookies.ApplicationCookie.AutomaticAuthenticate = true;
|
||||
option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme;
|
||||
option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme;
|
||||
option.Cookies.TwoFactorRememberMeCookie.ExpireTimeSpan = TimeSpan.FromDays(30);
|
||||
option.Cookies.TwoFactorRememberMeCookie.DataProtectionProvider = protector;
|
||||
option.Cookies.ExternalCookieAuthenticationScheme = Constants.ExternalAuthenticationSheme;
|
||||
option.Cookies.ExternalCookie.AutomaticAuthenticate = true;
|
||||
option.Cookies.ExternalCookie.AuthenticationScheme = Constants.ExternalAuthenticationSheme;
|
||||
option.Cookies.ExternalCookie.DataProtectionProvider = protector;
|
||||
*/
|
||||
}
|
||||
).AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddTokenProvider<EmailTokenProvider<ApplicationUser>>(Constants.DefaultFactor)
|
||||
// .AddTokenProvider<UserTokenProvider>(Constants.DefaultFactor)
|
||||
// .AddTokenProvider<UserTokenProvider>(Constants.SMSFactor)
|
||||
// .AddTokenProvider<UserTokenProvider>(Constants.EMailFactor)
|
||||
// .AddTokenProvider<UserTokenProvider>(Constants.AppFactor)
|
||||
// .AddDefaultTokenProviders()
|
||||
;
|
||||
}
|
||||
private void ConfigureOAuthApp(IApplicationBuilder app,
|
||||
SiteSettings settingsOptions, ILogger logger)
|
||||
{
|
||||
|
||||
app.UseIdentity();
|
||||
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"),
|
||||
branch =>
|
||||
{
|
||||
branch.UseJwtBearerAuthentication(
|
||||
options =>
|
||||
{
|
||||
options.AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.SecurityTokenValidators.Clear();
|
||||
options.SecurityTokenValidators.Add(new TicketDataFormatTokenValidator(
|
||||
ProtectionProvider
|
||||
));
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
app.UseWhen(context => !context.Request.Path.StartsWithSegments("/api"),
|
||||
branch =>
|
||||
{
|
||||
// External authentication shared cookie:
|
||||
branch.UseCookieAuthentication(options =>
|
||||
{
|
||||
ExternalCookieAppOptions = options;
|
||||
options.AuthenticationScheme = Constants.ExternalAuthenticationSheme;
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
options.LoginPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
// TODO implement an access denied page
|
||||
options.AccessDeniedPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
});
|
||||
|
||||
|
||||
|
||||
YavscGoogleAppOptions = new YavscGoogleOptions
|
||||
{
|
||||
ClientId = GoogleWebClientConfiguration ["web:client_id"],
|
||||
ClientSecret = GoogleWebClientConfiguration ["web:client_secret"],
|
||||
AccessType = "offline",
|
||||
Scope = { "profile", "https://www.googleapis.com/auth/plus.login",
|
||||
"https://www.googleapis.com/auth/admin.directory.resource.calendar",
|
||||
"https://www.googleapis.com/auth/calendar",
|
||||
"https://www.googleapis.com/auth/calendar.events"},
|
||||
SaveTokensAsClaims = true,
|
||||
UserInformationEndpoint = "https://www.googleapis.com/plus/v1/people/me",
|
||||
Events = new OAuthEvents
|
||||
{
|
||||
OnCreatingTicket = async context =>
|
||||
{
|
||||
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
|
||||
.CreateScope())
|
||||
{
|
||||
var gcontext = context as GoogleOAuthCreatingTicketContext;
|
||||
context.Identity.AddClaim(new Claim(YavscClaimTypes.GoogleUserId, gcontext.GoogleUserId));
|
||||
var dbContext = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
|
||||
|
||||
var store = serviceScope.ServiceProvider.GetService<IDataStore>();
|
||||
await store.StoreAsync(gcontext.GoogleUserId, new TokenResponse {
|
||||
AccessToken = gcontext.TokenResponse.AccessToken,
|
||||
RefreshToken = gcontext.TokenResponse.RefreshToken,
|
||||
TokenType = gcontext.TokenResponse.TokenType,
|
||||
ExpiresInSeconds = int.Parse(gcontext.TokenResponse.ExpiresIn),
|
||||
IssuedUtc = DateTime.Now
|
||||
});
|
||||
await dbContext.StoreTokenAsync (gcontext.GoogleUserId,
|
||||
gcontext.TokenResponse.Response,
|
||||
gcontext.TokenResponse.AccessToken,
|
||||
gcontext.TokenResponse.TokenType,
|
||||
gcontext.TokenResponse.RefreshToken,
|
||||
gcontext.TokenResponse.ExpiresIn);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
branch.UseMiddleware<Yavsc.Auth.GoogleMiddleware>(YavscGoogleAppOptions);
|
||||
/* FIXME 403
|
||||
|
||||
branch.UseTwitterAuthentication(options=>
|
||||
{
|
||||
TwitterAppOptions = options;
|
||||
options.ConsumerKey = Configuration["Authentication:Twitter:ClientId"];
|
||||
options.ConsumerSecret = Configuration["Authentication:Twitter:ClientSecret"];
|
||||
}); */
|
||||
|
||||
|
||||
branch.UseOAuthAuthorizationServer(
|
||||
|
||||
options =>
|
||||
{
|
||||
OAuthServerAppOptions = options;
|
||||
options.AuthorizeEndpointPath = new PathString(Constants.AuthorizePath.Substring(1));
|
||||
options.TokenEndpointPath = new PathString(Constants.TokenPath.Substring(1));
|
||||
options.ApplicationCanDisplayErrors = true;
|
||||
options.AllowInsecureHttp = true;
|
||||
options.AuthenticationScheme = OAuthDefaults.AuthenticationType;
|
||||
options.TokenDataProtector = ProtectionProvider.CreateProtector("Bearer protection");
|
||||
|
||||
options.Provider = new OAuthAuthorizationServerProvider
|
||||
{
|
||||
OnValidateClientRedirectUri = ValidateClientRedirectUri,
|
||||
OnValidateClientAuthentication = ValidateClientAuthentication,
|
||||
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
|
||||
OnGrantClientCredentials = GrantClientCredetails
|
||||
};
|
||||
|
||||
options.AuthorizationCodeProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateAuthenticationCode,
|
||||
OnReceive = ReceiveAuthenticationCode,
|
||||
};
|
||||
|
||||
options.RefreshTokenProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateRefreshToken,
|
||||
OnReceive = ReceiveRefreshToken,
|
||||
};
|
||||
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.AutomaticChallenge = true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Environment.SetEnvironmentVariable ("GOOGLE_APPLICATION_CREDENTIALS", "google-secret.json");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
169
src/Yavsc/Startup/Startup.OAuthHelpers.cs
Normal file
169
src/Yavsc/Startup/Startup.OAuthHelpers.cs
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OAuth.AspNet.AuthServer;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.Models.Auth;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
public partial class Startup
|
||||
{
|
||||
private Client GetApplication(string clientId)
|
||||
{
|
||||
if (_dbContext==null)
|
||||
logger.LogError("no db!");
|
||||
Client app = _dbContext.Applications.FirstOrDefault(x => x.Id == clientId);
|
||||
if (app==null)
|
||||
logger.LogError("no app!");
|
||||
return app;
|
||||
}
|
||||
private readonly ConcurrentDictionary<string, string> _authenticationCodes = new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
|
||||
|
||||
private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
|
||||
{
|
||||
if (context == null) throw new InvalidOperationException("context == null");
|
||||
var app = GetApplication(context.ClientId);
|
||||
if (app == null) return Task.FromResult(0);
|
||||
Startup.logger.LogInformation($"ValidateClientRedirectUri: Validated ({app.RedirectUri})");
|
||||
context.Validated(app.RedirectUri);
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
|
||||
{
|
||||
string clientId, clientSecret;
|
||||
|
||||
if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
|
||||
context.TryGetFormCredentials(out clientId, out clientSecret))
|
||||
{
|
||||
logger.LogInformation($"ValidateClientAuthentication: Got id: ({clientId} secret: {clientSecret})");
|
||||
var client = GetApplication(clientId);
|
||||
if (client==null) {
|
||||
context.SetError("invalid_clientId", "Client secret is invalid.");
|
||||
return Task.FromResult<object>(null);
|
||||
} else
|
||||
if (client.Type == ApplicationTypes.NativeConfidential)
|
||||
{
|
||||
logger.LogInformation($"NativeConfidential key");
|
||||
if (string.IsNullOrWhiteSpace(clientSecret))
|
||||
{
|
||||
logger.LogInformation($"invalid_clientId: Client secret should be sent.");
|
||||
context.SetError("invalid_clientId", "Client secret should be sent.");
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (client.Secret != Helper.GetHash(clientSecret))
|
||||
// TODO store a hash in db, not the pass
|
||||
if (client.Secret != clientSecret)
|
||||
{
|
||||
context.SetError("invalid_clientId", "Client secret is invalid.");
|
||||
logger.LogInformation($"invalid_clientId: Client secret is invalid.");
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!client.Active)
|
||||
{
|
||||
context.SetError("invalid_clientId", "Client is inactive.");
|
||||
logger.LogInformation($"invalid_clientId: Client is inactive.");
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
if (client != null && client.Secret == clientSecret)
|
||||
{
|
||||
logger.LogInformation($"\\o/ ValidateClientAuthentication: Validated ({clientId})");
|
||||
context.Validated();
|
||||
}
|
||||
else logger.LogInformation($":'( ValidateClientAuthentication: KO ({clientId})");
|
||||
}
|
||||
else logger.LogWarning($"ValidateClientAuthentication: neither Basic nor Form credential were found");
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
UserManager<ApplicationUser> _usermanager;
|
||||
|
||||
private async Task<Task> GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
|
||||
{
|
||||
logger.LogWarning($"GrantResourceOwnerCredentials task ... {context.UserName}");
|
||||
|
||||
ApplicationUser user = null;
|
||||
user = await _usermanager.FindByNameAsync(context.UserName);
|
||||
if (await _usermanager.CheckPasswordAsync(user, context.Password))
|
||||
{
|
||||
|
||||
var claims = new List<Claim>(
|
||||
context.Scope.Select(x => new Claim("urn:oauth:scope", x))
|
||||
);
|
||||
claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id));
|
||||
claims.Add(new Claim(ClaimTypes.Email, user.Email));
|
||||
claims.AddRange((await _usermanager.GetRolesAsync(user)).Select(
|
||||
r => new Claim(ClaimTypes.Role, r)
|
||||
));
|
||||
ClaimsPrincipal principal = new ClaimsPrincipal(
|
||||
new ClaimsIdentity(
|
||||
new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType),
|
||||
claims)
|
||||
);
|
||||
// TODO set a NameIdentifier, roles and scopes claims
|
||||
context.HttpContext.User = principal;
|
||||
|
||||
context.Validated(principal);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context)
|
||||
{
|
||||
ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x))));
|
||||
|
||||
context.Validated(principal);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
|
||||
{
|
||||
logger.LogInformation("CreateAuthenticationCode");
|
||||
context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
|
||||
_authenticationCodes[context.Token] = context.SerializeTicket();
|
||||
}
|
||||
|
||||
private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
|
||||
{
|
||||
string value;
|
||||
if (_authenticationCodes.TryRemove(context.Token, out value))
|
||||
{
|
||||
context.DeserializeTicket(value);
|
||||
logger.LogInformation("ReceiveAuthenticationCode: Success");
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateRefreshToken(AuthenticationTokenCreateContext context)
|
||||
{
|
||||
var uid = context.Ticket.Principal.GetUserId();
|
||||
logger.LogInformation($"CreateRefreshToken for {uid}");
|
||||
foreach (var c in context.Ticket.Principal.Claims)
|
||||
logger.LogInformation($"| User claim: {c.Type} {c.Value}");
|
||||
|
||||
context.SetToken(context.SerializeTicket());
|
||||
}
|
||||
|
||||
private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
|
||||
{
|
||||
var uid = context.Ticket.Principal.GetUserId();
|
||||
logger.LogInformation($"ReceiveRefreshToken for {uid}");
|
||||
foreach (var c in context.Ticket.Principal.Claims)
|
||||
logger.LogInformation($"| User claim: {c.Type} {c.Value}");
|
||||
context.DeserializeTicket(context.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/Yavsc/Startup/Startup.SanityChecks.cs
Normal file
53
src/Yavsc/Startup/Startup.SanityChecks.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Google.Apis.Auth.OAuth2;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
// ensures we may count on :
|
||||
// * Google credentials
|
||||
// * an AppData folder
|
||||
public partial class Startup
|
||||
{
|
||||
public void CheckServices(IServiceCollection services)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void CheckApp(IApplicationBuilder app,
|
||||
SiteSettings siteSettings, IHostingEnvironment env,
|
||||
ILoggerFactory loggerFactory
|
||||
)
|
||||
{
|
||||
|
||||
var logger = loggerFactory.CreateLogger<Startup>();
|
||||
|
||||
var appData = Environment.GetEnvironmentVariable("APPDATA");
|
||||
if (appData == null)
|
||||
{
|
||||
logger.LogWarning("AppData was not found in environment variables");
|
||||
if (SiteSetup.DataDir == null) {
|
||||
SiteSetup.DataDir = "AppData"+env.EnvironmentName;
|
||||
logger.LogInformation("Using: "+SiteSetup.DataDir);
|
||||
} else logger.LogInformation("Using value from settings: "+SiteSetup.DataDir);
|
||||
DirectoryInfo di = new DirectoryInfo(SiteSetup.DataDir);
|
||||
if (!di.Exists)
|
||||
{
|
||||
di.Create();
|
||||
logger.LogWarning("Created dir : "+di.FullName);
|
||||
}
|
||||
else logger.LogInformation("Using existing directory: "+di.Name);
|
||||
SiteSetup.DataDir = Path.Combine(Directory.GetCurrentDirectory(),di.Name);
|
||||
Environment.SetEnvironmentVariable("APPDATA", SiteSetup.DataDir);
|
||||
logger.LogWarning("It has been set to : "+Environment.GetEnvironmentVariable("APPDATA"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/Yavsc/Startup/Startup.WebSockets.cs
Normal file
15
src/Yavsc/Startup/Startup.WebSockets.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
public partial class Startup
|
||||
{
|
||||
public void ConfigureWebSocketsApp(IApplicationBuilder app,
|
||||
SiteSettings siteSettings, IHostingEnvironment env)
|
||||
{
|
||||
app.UseWebSockets();
|
||||
app.UseSignalR("/api/signalr");
|
||||
}
|
||||
}
|
||||
}
|
||||
109
src/Yavsc/Startup/Startup.Workflow.cs
Normal file
109
src/Yavsc/Startup/Startup.Workflow.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
using Microsoft.Data.Entity;
|
||||
using Models;
|
||||
using Yavsc.Abstract.Workflow;
|
||||
using Yavsc.Billing;
|
||||
using Yavsc.Models.Billing;
|
||||
using Yavsc.Models.Haircut;
|
||||
using Yavsc.Models.Workflow;
|
||||
using Yavsc.Services;
|
||||
|
||||
public partial class Startup
|
||||
{
|
||||
/// <summary>
|
||||
/// Lists Available user profile classes,
|
||||
/// populated at startup, using reflexion.
|
||||
/// </summary>
|
||||
public static List<Type> ProfileTypes = new List<Type>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Lists available command forms.
|
||||
/// This is hard coded.
|
||||
/// </summary>
|
||||
public static readonly string[] Forms = new string[] { "Profiles", "HairCut" };
|
||||
|
||||
private void ConfigureWorkflow(IApplicationBuilder app, SiteSettings settings, ILogger logger)
|
||||
{
|
||||
// System.AppDomain.CurrentDomain.ResourceResolve += OnYavscResourceResolve;
|
||||
|
||||
try {
|
||||
foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
foreach (var c in a.GetTypes())
|
||||
{
|
||||
if (c.IsClass && !c.IsAbstract &&
|
||||
c.GetInterface("ISpecializationSettings") != null)
|
||||
{
|
||||
ProfileTypes.Add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex.TargetSite.Name);
|
||||
}
|
||||
|
||||
|
||||
foreach (var propinfo in typeof(ApplicationDbContext).GetProperties())
|
||||
{
|
||||
foreach (var attr in propinfo.CustomAttributes)
|
||||
{
|
||||
// something like a DbSet?
|
||||
if (attr.AttributeType == typeof(Yavsc.Attributes.ActivitySettingsAttribute))
|
||||
{
|
||||
// TODO swith () case {}
|
||||
if (typeof(IQueryable<ISpecializationSettings>).IsAssignableFrom(propinfo.PropertyType))
|
||||
{// double-bingo
|
||||
logger.LogVerbose($"Pro: {propinfo.Name}");
|
||||
BillingService.UserSettings.Add(propinfo);
|
||||
}
|
||||
else
|
||||
// Design time error
|
||||
{
|
||||
var msg =
|
||||
$@"La propriété {propinfo.Name} du contexte de la
|
||||
base de donnée porte l'attribut [ActivitySetting],
|
||||
mais n'implemente pas l'interface IQueryable<ISpecializationSettings>
|
||||
({propinfo.MemberType.GetType()})";
|
||||
logger.LogCritical(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegisterBilling<HairCutQuery>(BillingCodes.Brush, new Func<ApplicationDbContext,long,IDecidableQuery>
|
||||
( ( db, id) =>
|
||||
{
|
||||
var query = db.HairCutQueries.Include(q=>q.Prestation).Include(q=>q.Regularisation).Single(q=>q.Id == id) ;
|
||||
query.SelectedProfile = db.BrusherProfile.Single(b=>b.UserId == query.PerformerId);
|
||||
return query;
|
||||
})) ;
|
||||
|
||||
RegisterBilling<HairMultiCutQuery>(BillingCodes.MBrush,new Func<ApplicationDbContext,long,IDecidableQuery>
|
||||
( (db, id) => db.HairMultiCutQueries.Include(q=>q.Regularisation).Single(q=>q.Id == id)));
|
||||
RegisterBilling<RdvQuery>(BillingCodes.Rdv, new Func<ApplicationDbContext,long,IDecidableQuery>
|
||||
( (db, id) => db.RdvQueries.Include(q=>q.Regularisation).Single(q=>q.Id == id)));
|
||||
}
|
||||
public static System.Reflection.Assembly OnYavscResourceResolve(object sender, ResolveEventArgs ev)
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies()[0];
|
||||
}
|
||||
|
||||
public static void RegisterBilling<T>(string code, Func<ApplicationDbContext,long,IDecidableQuery> getter) where T : IBillable
|
||||
{
|
||||
BillingService.Billing.Add(code,getter) ;
|
||||
BillingService.GlobalBillingMap.Add(typeof(T).Name,code);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
412
src/Yavsc/Startup/Startup.cs
Executable file
412
src/Yavsc/Startup/Startup.cs
Executable file
|
|
@ -0,0 +1,412 @@
|
|||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Web.Optimization;
|
||||
using Microsoft.AspNet.Authentication;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Diagnostics;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Localization;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Formatters;
|
||||
using Google.Apis.Util.Store;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Models;
|
||||
using PayPal.Manager;
|
||||
using Services;
|
||||
using ViewModels.Auth.Handlers;
|
||||
using Yavsc.Abstract.FileSystem;
|
||||
using static System.Environment;
|
||||
|
||||
public partial class Startup
|
||||
{
|
||||
public static string AvatarsDirName { private set; get; }
|
||||
public static string GitDirName { private set; get; }
|
||||
public static string Authority { get; private set; }
|
||||
public static string Temp { get; set; }
|
||||
public static SiteSettings SiteSetup { get; private set; }
|
||||
public static GoogleServiceAccount GServiceAccount { get; private set; }
|
||||
|
||||
public static string HostingFullName { get; set; }
|
||||
|
||||
public static PayPalSettings PayPalSettings { get; private set; }
|
||||
private static ILogger logger;
|
||||
|
||||
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
|
||||
{
|
||||
var devtag = env.IsDevelopment()?"D":"";
|
||||
var prodtag = env.IsProduction()?"P":"";
|
||||
var stagetag = env.IsStaging()?"S":"";
|
||||
|
||||
HostingFullName = $"{appEnv.RuntimeFramework.FullName} [{env.EnvironmentName}:{prodtag}{devtag}{stagetag}]";
|
||||
// Set up configuration sources.
|
||||
var builder = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
|
||||
builder.AddUserSecrets();
|
||||
BundleTable.EnableOptimizations = false;
|
||||
}
|
||||
|
||||
BundleConfig.RegisterBundles(BundleTable.Bundles);
|
||||
|
||||
builder.AddEnvironmentVariables();
|
||||
Configuration = builder.Build();
|
||||
|
||||
var auth = Configuration["Site:Authority"];
|
||||
var cxstr = Configuration["Data:DefaultConnection:ConnectionString"];
|
||||
ConnectionString = cxstr;
|
||||
|
||||
AppDomain.CurrentDomain.SetData(Constants.YavscConnectionStringEnvName, ConnectionString);
|
||||
|
||||
var googleClientFile = Configuration["Authentication:Google:GoogleWebClientJson"];
|
||||
var googleServiceAccountJsonFile = Configuration["Authentication:Google:GoogleServiceAccountJson"];
|
||||
GoogleWebClientConfiguration = new ConfigurationBuilder().AddJsonFile(googleClientFile).Build();
|
||||
var safile = new FileInfo(googleServiceAccountJsonFile);
|
||||
GServiceAccount = JsonConvert.DeserializeObject<GoogleServiceAccount>(safile.OpenText().ReadToEnd());
|
||||
}
|
||||
|
||||
public static string ConnectionString { get; set; }
|
||||
public static GoogleAuthSettings GoogleSettings { get; set; }
|
||||
public IConfigurationRoot Configuration { get; set; }
|
||||
public static IConfigurationRoot GoogleWebClientConfiguration { get; set; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
|
||||
// Database connection
|
||||
|
||||
services.AddOptions();
|
||||
var siteSettings = Configuration.GetSection("Site");
|
||||
services.Configure<SiteSettings>(siteSettings);
|
||||
var smtpSettings = Configuration.GetSection("Smtp");
|
||||
services.Configure<SmtpSettings>(smtpSettings);
|
||||
var googleSettings = Configuration.GetSection("Authentication").GetSection("Google");
|
||||
services.Configure<GoogleAuthSettings>(googleSettings);
|
||||
var cinfoSettings = Configuration.GetSection("Authentication").GetSection("Societeinfo");
|
||||
services.Configure<CompanyInfoSettings>(cinfoSettings);
|
||||
var oauthFacebookSettings = Configuration.GetSection("Authentication").GetSection("Facebook");
|
||||
services.Configure<FacebookOAuth2AppSettings>(oauthFacebookSettings);
|
||||
var paypalSettings = Configuration.GetSection("Authentication").GetSection("PayPal");
|
||||
services.Configure<PayPalSettings>(paypalSettings);
|
||||
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SiteSettings>), typeof(OptionsManager<SiteSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SmtpSettings>), typeof(OptionsManager<SmtpSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<GoogleAuthSettings>), typeof(OptionsManager<GoogleAuthSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<CompanyInfoSettings>), typeof(OptionsManager<CompanyInfoSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<RequestLocalizationOptions>), typeof(OptionsManager<RequestLocalizationOptions>)));
|
||||
|
||||
services.Configure<RequestLocalizationOptions>(options =>
|
||||
{
|
||||
var supportedCultures = new[]
|
||||
{
|
||||
new CultureInfo("en"),
|
||||
new CultureInfo("fr"),
|
||||
new CultureInfo("pt")
|
||||
};
|
||||
|
||||
var supportedUICultures = new[]
|
||||
{
|
||||
new CultureInfo("fr"),
|
||||
new CultureInfo("en"),
|
||||
new CultureInfo("pt")
|
||||
};
|
||||
|
||||
// You must explicitly state which cultures your application supports.
|
||||
// These are the cultures the app supports for formatting numbers, dates, etc.
|
||||
options.SupportedCultures = supportedCultures;
|
||||
|
||||
// These are the cultures the app supports for UI strings, i.e. we have localized resources for.
|
||||
options.SupportedUICultures = supportedUICultures;
|
||||
|
||||
// You can change which providers are configured to determine the culture for requests, or even add a custom
|
||||
// provider with your own logic. The providers will be asked in order to provide a culture for each request,
|
||||
// and the first to provide a non-null result that is in the configured supported cultures list will be used.
|
||||
// By default, the following built-in providers are configured:
|
||||
// - QueryStringRequestCultureProvider, sets culture via "culture" and "ui-culture" query string values, useful for testing
|
||||
// - CookieRequestCultureProvider, sets culture via "ASPNET_CULTURE" cookie
|
||||
// - AcceptLanguageHeaderRequestCultureProvider, sets culture via the "Accept-Language" request header
|
||||
|
||||
//options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
|
||||
//{
|
||||
// // My custom request culture logic
|
||||
// return new ProviderCultureResult("fr");
|
||||
//}));
|
||||
|
||||
options.RequestCultureProviders = new List<IRequestCultureProvider>
|
||||
{
|
||||
new QueryStringRequestCultureProvider { Options = options },
|
||||
new CookieRequestCultureProvider { Options = options, CookieName="ASPNET_CULTURE" },
|
||||
new AcceptLanguageHeaderRequestCultureProvider { Options = options }
|
||||
};
|
||||
});
|
||||
|
||||
// DataProtection
|
||||
ConfigureProtectionServices(services);
|
||||
|
||||
|
||||
// Add framework services.
|
||||
services.AddEntityFramework()
|
||||
.AddNpgsql()
|
||||
.AddDbContext<ApplicationDbContext>(
|
||||
db => db.UseNpgsql(ConnectionString)
|
||||
);
|
||||
|
||||
ConfigureOAuthServices(services);
|
||||
|
||||
services.AddCors(
|
||||
|
||||
options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy", builder =>
|
||||
{
|
||||
builder.WithOrigins("*");
|
||||
});
|
||||
}
|
||||
|
||||
);
|
||||
// Add memory cache services
|
||||
services.AddCaching();
|
||||
|
||||
// Add session related services.
|
||||
services.AddSession();
|
||||
|
||||
// Add the system clock service
|
||||
services.AddSingleton<ISystemClock, SystemClock>();
|
||||
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
|
||||
options.AddPolicy("AdministratorOnly", policy =>
|
||||
{
|
||||
policy.RequireClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", Constants.AdminGroupName);
|
||||
});
|
||||
|
||||
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
|
||||
options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
|
||||
.AddAuthenticationSchemes("yavsc")
|
||||
.RequireAuthenticatedUser().Build());
|
||||
// options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId", "123", "456"));
|
||||
// options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement()));
|
||||
options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
|
||||
});
|
||||
|
||||
services.AddSingleton<IAuthorizationHandler, HasBadgeHandler>();
|
||||
services.AddSingleton<IAuthorizationHandler, HasTemporaryPassHandler>();
|
||||
services.AddSingleton<IAuthorizationHandler, BlogEditHandler>();
|
||||
services.AddSingleton<IAuthorizationHandler, BlogViewHandler>();
|
||||
services.AddSingleton<IAuthorizationHandler, BillEditHandler>();
|
||||
services.AddSingleton<IAuthorizationHandler, BillViewHandler>();
|
||||
services.AddSingleton<IAuthorizationHandler, PostUserFileHandler>();
|
||||
services.AddSingleton<IAuthorizationHandler, ViewFileHandler>();
|
||||
|
||||
services.AddMvc(config =>
|
||||
{
|
||||
var policy = new AuthorizationPolicyBuilder()
|
||||
.RequireAuthenticatedUser()
|
||||
.Build();
|
||||
config.Filters.Add(new AuthorizeFilter(policy));
|
||||
config.Filters.Add(new ProducesAttribute("application/json"));
|
||||
// config.ModelBinders.Insert(0,new MyDateTimeModelBinder());
|
||||
// config.ModelBinders.Insert(0,new MyDecimalModelBinder());
|
||||
config.OutputFormatters.Add(new PdfFormatter());
|
||||
|
||||
}).AddFormatterMappings(
|
||||
config => config.SetMediaTypeMappingForFormat("text/pdf",
|
||||
new MediaTypeHeaderValue("text/pdf"))
|
||||
).AddFormatterMappings(
|
||||
config => config.SetMediaTypeMappingForFormat("text/x-tex",
|
||||
new MediaTypeHeaderValue("text/x-tex"))
|
||||
)
|
||||
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix,
|
||||
options =>
|
||||
{
|
||||
options.ResourcesPath = "Resources";
|
||||
}).AddDataAnnotationsLocalization();
|
||||
|
||||
// services.AddScoped<LanguageActionFilter>();
|
||||
|
||||
// Inject ticket formatting
|
||||
services.AddTransient(typeof(ISecureDataFormat<>), typeof(SecureDataFormat<>));
|
||||
services.AddTransient<Microsoft.AspNet.Authentication.ISecureDataFormat<AuthenticationTicket>, Microsoft.AspNet.Authentication.SecureDataFormat<AuthenticationTicket>>();
|
||||
services.AddTransient<ISecureDataFormat<AuthenticationTicket>, TicketDataFormat>();
|
||||
|
||||
// Add application services.
|
||||
services.AddTransient<IEmailSender, MailSender>();
|
||||
services.AddTransient<IGoogleCloudMessageSender, GCMSender>();
|
||||
services.AddTransient<IBillingService, BillingService>();
|
||||
services.AddTransient<IDataStore, FileDataStore>( (sp) => new FileDataStore("googledatastore",false) );
|
||||
services.AddTransient<ICalendarManager, CalendarManager>();
|
||||
|
||||
// TODO for SMS: services.AddTransient<ISmsSender, AuthMessageSender>();
|
||||
|
||||
services.AddLocalization(options =>
|
||||
{
|
||||
options.ResourcesPath = "Resources";
|
||||
});
|
||||
CheckServices(services);
|
||||
}
|
||||
static ApplicationDbContext _dbContext;
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(
|
||||
IApplicationBuilder app, IHostingEnvironment env,
|
||||
ApplicationDbContext dbContext, IOptions<SiteSettings> siteSettings,
|
||||
IOptions<RequestLocalizationOptions> localizationOptions,
|
||||
IOptions<OAuth2AppSettings> oauth2SettingsContainer,
|
||||
IAuthorizationService authorizationService,
|
||||
IOptions<PayPalSettings> payPalSettings,
|
||||
IOptions<GoogleAuthSettings> googleSettings,
|
||||
IStringLocalizer<Yavsc.Resources.YavscLocalisation> localizer,
|
||||
UserManager<ApplicationUser> usermanager,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_usermanager = usermanager;
|
||||
GoogleSettings = googleSettings.Value;
|
||||
ResourcesHelpers.GlobalLocalizer = localizer;
|
||||
SiteSetup = siteSettings.Value;
|
||||
Authority = siteSettings.Value.Authority;
|
||||
var blogsDir = siteSettings.Value.Blog;
|
||||
if (blogsDir==null) throw new Exception ("blogsDir is not set.");
|
||||
var billsDir = siteSettings.Value.Bills;
|
||||
if (billsDir==null) throw new Exception ("billsDir is not set.");
|
||||
|
||||
AbstractFileSystemHelpers.UserFilesDirName = new DirectoryInfo(blogsDir).FullName;
|
||||
AbstractFileSystemHelpers.UserBillsDirName = new DirectoryInfo(billsDir).FullName;
|
||||
Temp = siteSettings.Value.TempDir;
|
||||
PayPalSettings = payPalSettings.Value;
|
||||
|
||||
// TODO implement an installation & upgrade procedure
|
||||
// Create required directories
|
||||
foreach (string dir in new string[] { AbstractFileSystemHelpers.UserFilesDirName, AbstractFileSystemHelpers.UserBillsDirName, SiteSetup.TempDir })
|
||||
{
|
||||
if (dir==null) throw new Exception (nameof(dir));
|
||||
|
||||
DirectoryInfo di = new DirectoryInfo(dir);
|
||||
if (!di.Exists) di.Create();
|
||||
}
|
||||
|
||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
loggerFactory.AddDebug();
|
||||
logger = loggerFactory.CreateLogger<Startup>();
|
||||
app.UseStatusCodePagesWithReExecute("/Home/Status/{0}");
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
var logenvvar = Environment.GetEnvironmentVariable("ASPNET_LOG_LEVEL");
|
||||
if (logenvvar!=null)
|
||||
switch (logenvvar) {
|
||||
case "info":
|
||||
loggerFactory.MinimumLevel = LogLevel.Information;
|
||||
break;
|
||||
case "warn":
|
||||
loggerFactory.MinimumLevel = LogLevel.Warning;
|
||||
break;
|
||||
case "err":
|
||||
loggerFactory.MinimumLevel = LogLevel.Error;
|
||||
break;
|
||||
case "debug":
|
||||
default:
|
||||
loggerFactory.MinimumLevel = LogLevel.Debug;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseRuntimeInfoPage();
|
||||
var epo = new ErrorPageOptions();
|
||||
epo.SourceCodeLineCount = 20;
|
||||
app.UseDeveloperExceptionPage(epo);
|
||||
app.UseDatabaseErrorPage(
|
||||
x =>
|
||||
{
|
||||
x.EnableAll();
|
||||
x.ShowExceptionDetails = true;
|
||||
}
|
||||
);
|
||||
app.UseWelcomePage("/welcome");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
|
||||
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
try
|
||||
{
|
||||
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
|
||||
.CreateScope())
|
||||
{
|
||||
serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
|
||||
.Database.Migrate();
|
||||
}
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
if (ex.InnerException is InvalidOperationException)
|
||||
// nothing to do ?
|
||||
{
|
||||
// TODO (or not) Hit the developper
|
||||
}
|
||||
else throw ex;
|
||||
}
|
||||
}
|
||||
// before fixing the security protocol, let beleive our lib it's done with it.
|
||||
var cxmgr = ConnectionManager.Instance;
|
||||
// then, fix it.
|
||||
ServicePointManager.SecurityProtocol = (SecurityProtocolType) 0xC00; // Tls12, required by PayPal
|
||||
|
||||
app.UseIISPlatformHandler(options =>
|
||||
{
|
||||
options.AuthenticationDescriptions.Clear();
|
||||
options.AutomaticAuthentication = false;
|
||||
});
|
||||
|
||||
ConfigureOAuthApp(app, SiteSetup, logger);
|
||||
ConfigureFileServerApp(app, SiteSetup, env, authorizationService);
|
||||
ConfigureWebSocketsApp(app, SiteSetup, env);
|
||||
ConfigureWorkflow(app, SiteSetup, logger);
|
||||
app.UseRequestLocalization(localizationOptions.Value, (RequestCulture) new RequestCulture((string)"en-US"));
|
||||
app.UseSession();
|
||||
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
routes.MapRoute(
|
||||
name: "default",
|
||||
template: "{controller=Home}/{action=Index}/{id?}");
|
||||
});
|
||||
logger.LogInformation("LocalApplicationData: "+Environment.GetFolderPath(SpecialFolder.LocalApplicationData, SpecialFolderOption.DoNotVerify));
|
||||
|
||||
CheckApp(app, SiteSetup, env, loggerFactory);
|
||||
}
|
||||
|
||||
// Entry point for the application.
|
||||
public static void Main(string[] args) => Microsoft.AspNet.Hosting.WebApplication.Run<Startup>(args);
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
Loading…
Add table
Add a link
Reference in a new issue