more services from Web API
This commit is contained in:
@ -1,346 +0,0 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Yavsc.Abstract.Chat;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.ViewModels.Chat;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Connexion Manager
|
||||
/// </summary>
|
||||
public class HubConnectionManager : IConnexionManager
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private Action<string, string> _errorHandler;
|
||||
|
||||
/// <summary>
|
||||
/// by cx id
|
||||
/// </summary>
|
||||
/// <typeparam name="string"></typeparam>
|
||||
/// <typeparam name="string"></typeparam>
|
||||
/// <returns></returns>
|
||||
|
||||
static readonly ConcurrentDictionary<string, string> ChatUserNames = new ConcurrentDictionary<string, string>();
|
||||
/// <summary>
|
||||
/// by user name
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
static readonly ConcurrentDictionary<string, List<string>> ChatCxIds = new ConcurrentDictionary<string, List<string>>();
|
||||
|
||||
/// <summary>
|
||||
/// by user name,
|
||||
/// the list of its chat rooms
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
static readonly ConcurrentDictionary<string, List<string>> ChatRoomPresence = new ConcurrentDictionary<string, List<string>>();
|
||||
static readonly ConcurrentDictionary<string, bool> _isCop = new ConcurrentDictionary<string, bool>();
|
||||
|
||||
public static ConcurrentDictionary<string, ChatRoomInfo> Channels = new ConcurrentDictionary<string, ChatRoomInfo>();
|
||||
readonly ApplicationDbContext _dbContext;
|
||||
readonly IStringLocalizer _localizer;
|
||||
|
||||
public HubConnectionManager(IServiceScopeFactory ssf )
|
||||
{
|
||||
|
||||
var scope = ssf.CreateScope();
|
||||
_dbContext = scope.ServiceProvider.GetService<ApplicationDbContext>();
|
||||
var loggerFactory = scope.ServiceProvider.GetService<ILoggerFactory>();
|
||||
_logger = loggerFactory.CreateLogger<HubConnectionManager>();
|
||||
var stringLocFactory = scope.ServiceProvider.GetService<IStringLocalizerFactory>();
|
||||
_localizer = stringLocFactory.Create(typeof(HubConnectionManager));
|
||||
}
|
||||
|
||||
public void SetUserName(string cxId, string userName)
|
||||
{
|
||||
string oldUname;
|
||||
if (ChatUserNames.TryGetValue(cxId, out oldUname))
|
||||
{
|
||||
// this is a rename
|
||||
if (oldUname == userName) return;
|
||||
ChatCxIds[userName] = ChatCxIds[oldUname];
|
||||
ChatCxIds[oldUname] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is a connexion
|
||||
ChatCxIds[userName] = new List<string>() { cxId };
|
||||
}
|
||||
ChatUserNames[cxId] = userName;
|
||||
}
|
||||
// Username must have been set before calling this method.
|
||||
public void OnConnected(string cxId, bool isCop)
|
||||
{
|
||||
var username = ChatUserNames[cxId];
|
||||
if (!IsConnected(username))
|
||||
ChatRoomPresence[username] = new List<string>();
|
||||
_isCop[username] = isCop;
|
||||
}
|
||||
|
||||
public bool IsConnected(string candidate)
|
||||
{
|
||||
return ChatRoomPresence.ContainsKey(candidate)
|
||||
&& ChatRoomPresence[candidate] != null;
|
||||
}
|
||||
|
||||
public bool IsPresent(string roomName, string userName)
|
||||
{
|
||||
return ChatRoomPresence[userName].Contains(roomName);
|
||||
}
|
||||
|
||||
public bool IsCop(string userName)
|
||||
{
|
||||
return _isCop[userName];
|
||||
}
|
||||
|
||||
public void OnDisctonnected(string connectionId)
|
||||
{
|
||||
string uname;
|
||||
|
||||
if (!ChatUserNames.TryRemove(connectionId, out uname))
|
||||
_logger.LogError($"Could not get removed user name for cx {connectionId}");
|
||||
else
|
||||
{
|
||||
List<string> cxIds;
|
||||
if (ChatCxIds.TryGetValue(uname, out cxIds))
|
||||
{
|
||||
cxIds.Remove(connectionId);
|
||||
foreach (var room in ChatRoomPresence[uname])
|
||||
{
|
||||
Part(connectionId, room, "connexion aborted");
|
||||
}
|
||||
}
|
||||
else
|
||||
_logger.LogError($"Could not remove user cx {connectionId}");
|
||||
|
||||
ChatRoomPresence[uname] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Part(string cxId, string roomName, string reason)
|
||||
{
|
||||
ChatRoomInfo chanInfo;
|
||||
var userName = ChatUserNames[cxId];
|
||||
if (Channels.TryGetValue(roomName, out chanInfo))
|
||||
{
|
||||
if (!chanInfo.Users.Contains(cxId))
|
||||
{
|
||||
// TODO NotifyErrorToCaller(roomName, "you didn't join.");
|
||||
return false;
|
||||
}
|
||||
// FIXME only remove cx, not username,
|
||||
// as long as he might be connected
|
||||
// from another device, to the same room
|
||||
chanInfo.Users.Remove(cxId);
|
||||
if (chanInfo.Users.Count == 0)
|
||||
{
|
||||
ChatRoomInfo deadchanInfo;
|
||||
if (Channels.TryRemove(roomName, out deadchanInfo))
|
||||
{
|
||||
var room = _dbContext.ChatRoom.FirstOrDefault(r => r.Name == roomName);
|
||||
room.LatestJoinPart = DateTime.Now;
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
// TODO NotifyErrorToCallerInRoom(roomName, $"user could not part: no such room");
|
||||
}
|
||||
}
|
||||
|
||||
public ChatRoomInfo Join(string roomName, string cxId)
|
||||
{
|
||||
var userName = ChatUserNames[cxId];
|
||||
|
||||
_logger.LogInformation($"Join: {userName}=>{roomName}");
|
||||
ChatRoomInfo chanInfo;
|
||||
// if channel already is open
|
||||
if (Channels.ContainsKey(roomName))
|
||||
{
|
||||
if (Channels.TryGetValue(roomName, out chanInfo))
|
||||
{
|
||||
if (IsPresent(roomName, userName))
|
||||
{
|
||||
// TODO implement some unique connection sharing protocol
|
||||
// between all terminals from a single user.
|
||||
return chanInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsCop(userName))
|
||||
{
|
||||
chanInfo.Ops.Add(cxId);
|
||||
}
|
||||
else{
|
||||
chanInfo.Users.Add(cxId);
|
||||
}
|
||||
_logger.LogInformation($"existing room joint: {userName}=>{roomName}");
|
||||
if (!ChatRoomPresence[userName].Contains(roomName))
|
||||
ChatRoomPresence[userName].Add(roomName);
|
||||
return chanInfo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string msg = "room seemd to be avaible ... but we could get no info on it.";
|
||||
_errorHandler(roomName, msg);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// room was closed.
|
||||
var room = _dbContext.ChatRoom.FirstOrDefault(r => r.Name == roomName);
|
||||
chanInfo = new ChatRoomInfo();
|
||||
|
||||
|
||||
if (room != null)
|
||||
{
|
||||
chanInfo.Topic = room.Topic;
|
||||
chanInfo.Name = room.Name;
|
||||
chanInfo.Users.Add(cxId);
|
||||
}
|
||||
else
|
||||
{ // a first join, we create it.
|
||||
chanInfo.Name = roomName;
|
||||
chanInfo.Topic = _localizer.GetString(ChatHubConstants.JustCreatedBy)+userName;
|
||||
chanInfo.Ops.Add(cxId);
|
||||
}
|
||||
|
||||
if (Channels.TryAdd(roomName, chanInfo))
|
||||
{
|
||||
ChatRoomPresence[userName].Add(roomName);
|
||||
_logger.LogInformation("new room joint");
|
||||
return (chanInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
string msg = "Chan create failed unexpectly...";
|
||||
_errorHandler(roomName, msg);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Op(string roomName, string userName)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Deop(string roomName, string userName)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Hop(string roomName, string userName)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Dehop(string roomName, string userName)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetUserName(string cxId)
|
||||
{
|
||||
return ChatUserNames[cxId];
|
||||
}
|
||||
|
||||
public bool TryGetChanInfo(string room, out ChatRoomInfo chanInfo)
|
||||
{
|
||||
return Channels.TryGetValue(room, out chanInfo);
|
||||
}
|
||||
|
||||
public IEnumerable<ChannelShortInfo> ListChannels(string pattern)
|
||||
{
|
||||
if (pattern != null)
|
||||
return Channels.Where(c => c.Key.Contains(pattern))
|
||||
.OrderByDescending(c => c.Value.Users.Count).Select(c => new ChannelShortInfo { RoomName = c.Key, Topic = c.Value.Topic }).Take(10);
|
||||
|
||||
return Channels
|
||||
.OrderByDescending(c => c.Value.Users.Count).Select(c => new ChannelShortInfo { RoomName = c.Key, Topic = c.Value.Topic }).Take(10);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetConnexionIds(string userName)
|
||||
{
|
||||
return ChatCxIds.ContainsKey(userName) ? ChatCxIds[userName] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// set on error as string couple action
|
||||
/// </summary>
|
||||
/// <param name="errorHandler"></param>
|
||||
public void SetErrorHandler(Action<string, string> errorHandler)
|
||||
{
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public bool Kick(string cxId, string userName, string roomName, string reason)
|
||||
{
|
||||
ChatRoomInfo chanInfo;
|
||||
if (!Channels.ContainsKey(roomName))
|
||||
{
|
||||
_errorHandler(roomName, _localizer.GetString(ChatHubConstants.LabNoSuchChan).ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Channels.TryGetValue(roomName, out chanInfo))
|
||||
{
|
||||
_errorHandler(roomName, _localizer.GetString(ChatHubConstants.LabNoSuchChan).ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
var kickerName = GetUserName(cxId);
|
||||
if (!chanInfo.Ops.Contains(cxId))
|
||||
if (!chanInfo.Hops.Contains(cxId))
|
||||
{
|
||||
_errorHandler(roomName, _localizer.GetString(ChatHubConstants.LabYouNotOp).ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsPresent(roomName, userName))
|
||||
{
|
||||
_errorHandler(roomName, _localizer.GetString(ChatHubConstants.LabNoSuchUser).ToString());
|
||||
return false;
|
||||
}
|
||||
var ucxs = GetConnexionIds(userName);
|
||||
if (chanInfo.Hops.Contains(cxId))
|
||||
if (chanInfo.Ops.Any(c => ucxs.Contains(c)))
|
||||
{
|
||||
_errorHandler(roomName, _localizer.GetString(ChatHubConstants.HopWontKickOp).ToString());
|
||||
return false;
|
||||
}
|
||||
if (IsCop(userName))
|
||||
{
|
||||
_errorHandler(roomName, _localizer.GetString(ChatHubConstants.NoKickOnCop).ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// all good, time to kick :-)
|
||||
foreach (var ucx in ucxs) {
|
||||
if (chanInfo.Users.Contains(ucx))
|
||||
chanInfo.Users.Remove(ucx);
|
||||
|
||||
else if (chanInfo.Ops.Contains(ucx))
|
||||
chanInfo.Ops.Remove(ucx);
|
||||
|
||||
else if (chanInfo.Hops.Contains(ucx))
|
||||
chanInfo.Hops.Remove(ucx);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Yavsc;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.Services;
|
||||
|
||||
|
||||
public class DiskUsageTracker : IDiskUsageTracker
|
||||
{
|
||||
public class DUTInfo
|
||||
{
|
||||
public DUTInfo()
|
||||
{
|
||||
Creation = DateTime.Now;
|
||||
}
|
||||
public long Usage { get; set; }
|
||||
public long Quota { get; set; }
|
||||
public readonly DateTime Creation;
|
||||
}
|
||||
|
||||
readonly Dictionary<string, DUTInfo> DiskUsage;
|
||||
readonly ApplicationDbContext context;
|
||||
readonly int ulistLength;
|
||||
public DiskUsageTracker(IOptions<SiteSettings> options, ApplicationDbContext context)
|
||||
{
|
||||
ulistLength = options.Value.DUUserListLen;
|
||||
DiskUsage = new Dictionary<string, DUTInfo>();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
readonly static object userInfoLock = new object();
|
||||
|
||||
DUTInfo GetInfo(string username)
|
||||
{
|
||||
lock (userInfoLock)
|
||||
{
|
||||
if (!DiskUsage.ContainsKey(username))
|
||||
{
|
||||
var user = context.Users.SingleOrDefault(u => u.UserName == username);
|
||||
if (user == null) throw new Exception($"Not an user : {username}");
|
||||
DUTInfo usage = new DUTInfo
|
||||
{
|
||||
Usage = user.DiskUsage,
|
||||
Quota = user.DiskQuota
|
||||
};
|
||||
DiskUsage.Add(username, usage);
|
||||
if (DiskUsage.Count > ulistLength)
|
||||
{
|
||||
// remove the oldest
|
||||
var oldestts = DateTime.Now;
|
||||
DUTInfo oinfo = null;
|
||||
string ouname = null;
|
||||
foreach (var diskusage in DiskUsage)
|
||||
{
|
||||
if (oldestts > usage.Creation)
|
||||
{
|
||||
oldestts = diskusage.Value.Creation;
|
||||
ouname = diskusage.Key;
|
||||
oinfo = diskusage.Value;
|
||||
}
|
||||
}
|
||||
var ouser = context.Users.SingleOrDefault(u => u.UserName == ouname);
|
||||
ouser.DiskUsage = oinfo.Usage;
|
||||
context.SaveChanges();
|
||||
DiskUsage.Remove(ouname);
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
return DiskUsage[username];
|
||||
}
|
||||
}
|
||||
public bool GetSpace(string userName, long space)
|
||||
{
|
||||
var info = GetInfo(userName);
|
||||
if (info.Quota < info.Usage + space) return false;
|
||||
info.Usage += space;
|
||||
#pragma warning disable CS4014
|
||||
SaveUserUsage(userName,info.Usage);
|
||||
#pragma warning restore CS4014
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Release(string userName, long space)
|
||||
{
|
||||
var info = GetInfo(userName);
|
||||
info.Usage -= space;
|
||||
#pragma warning disable CS4014
|
||||
SaveUserUsage(userName,info.Usage);
|
||||
#pragma warning restore CS4014
|
||||
}
|
||||
|
||||
async Task SaveUserUsage(string username, long usage)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var ouser = context.Users.SingleOrDefault(u => u.UserName == username);
|
||||
ouser.DiskUsage = usage;
|
||||
context.SaveChanges();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
using System.Text;
|
||||
// // EMailer.cs
|
||||
// /*
|
||||
// paul 26/06/2018 12:18 20182018 6 26
|
||||
// */
|
||||
using Yavsc.Templates;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
|
||||
using Yavsc.Models;
|
||||
using Yavsc.Services;
|
||||
using System.Reflection;
|
||||
using Yavsc.Abstract.Templates;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using RazorEngine.Configuration;
|
||||
using Yavsc.Interface;
|
||||
|
||||
namespace Yavsc.Lib
|
||||
{
|
||||
public class EMailer
|
||||
{
|
||||
const string DefaultBaseClassName = "ATemplate";
|
||||
const string DefaultBaseClass = nameof(UserOrientedTemplate);
|
||||
ISet<string> Namespaces = new System.Collections.Generic.HashSet<string> {
|
||||
"System",
|
||||
"Yavsc.Templates" ,
|
||||
"Yavsc.Models",
|
||||
"Yavsc.Models.Identity"};
|
||||
|
||||
readonly IStringLocalizer<EMailer> stringLocalizer;
|
||||
readonly ApplicationDbContext dbContext;
|
||||
|
||||
readonly ILogger logger;
|
||||
|
||||
public EMailer(ApplicationDbContext context,
|
||||
IStringLocalizer<EMailer> localizer,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
stringLocalizer = localizer;
|
||||
|
||||
logger = loggerFactory.CreateLogger<EMailer>();
|
||||
|
||||
|
||||
var templateServiceConfig = new TemplateServiceConfiguration()
|
||||
{
|
||||
BaseTemplateType = typeof(UserOrientedTemplate),
|
||||
Language = RazorEngine.Language.CSharp,
|
||||
Namespaces = Namespaces
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public void SendMonthlyEmail(string templateCode, string baseclassName = DefaultBaseClassName)
|
||||
{
|
||||
string className = "Generated" + baseclassName;
|
||||
|
||||
string subtemp = stringLocalizer["MonthlySubjectTemplate"].Value;
|
||||
|
||||
logger.LogInformation($"Generating {subtemp}[{className}]");
|
||||
|
||||
|
||||
var templateInfo = dbContext.MailingTemplate.FirstOrDefault(t => t.Id == templateCode);
|
||||
var templatekey = RazorEngine.Engine.Razor.GetKey(templateInfo.Id);
|
||||
|
||||
|
||||
logger.LogInformation($"Using code: {templateCode}, subject: {subtemp} ");
|
||||
logger.LogInformation("And body:\n" + templateInfo.Body);
|
||||
using (StringReader reader = new StringReader(templateInfo.Body))
|
||||
{
|
||||
|
||||
// Generate code for the template
|
||||
using (var rzcode = new MemoryStream())
|
||||
{
|
||||
using (var writter = new StreamWriter(rzcode))
|
||||
{
|
||||
RazorEngine.Engine.Razor.Run(templatekey, writter);
|
||||
rzcode.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(Encoding.Default.GetString(rzcode.ToArray()));
|
||||
|
||||
|
||||
logger.LogInformation("CSharp parsed");
|
||||
List<MetadataReference> references = new List<MetadataReference>();
|
||||
|
||||
foreach (var type in new Type[] {
|
||||
typeof(object),
|
||||
typeof(Enumerable),
|
||||
typeof(IdentityUser),
|
||||
typeof(ApplicationUser),
|
||||
typeof(Template),
|
||||
typeof(UserOrientedTemplate),
|
||||
typeof(System.Threading.Tasks.TaskExtensions)
|
||||
})
|
||||
{
|
||||
var location = type.Assembly.Location;
|
||||
if (!string.IsNullOrWhiteSpace(location))
|
||||
{
|
||||
references.Add(
|
||||
MetadataReference.CreateFromFile(location)
|
||||
);
|
||||
logger.LogInformation($"Assembly for {type.Name} found at {location}");
|
||||
}
|
||||
else logger.LogWarning($"Assembly Not found for {type.Name}");
|
||||
}
|
||||
|
||||
logger.LogInformation("Compilation creation ...");
|
||||
|
||||
var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
|
||||
.WithAllowUnsafe(true).WithOptimizationLevel(OptimizationLevel.Debug)
|
||||
.WithOutputKind(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.AnyCpu)
|
||||
.WithUsings("Yavsc.Templates")
|
||||
;
|
||||
string assemblyName = "EMailSenderTemplate";
|
||||
CSharpCompilation compilation = CSharpCompilation.Create(
|
||||
assemblyName,
|
||||
syntaxTrees: new[] { syntaxTree },
|
||||
references: references,
|
||||
options: compilationOptions
|
||||
);
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
logger.LogInformation("Emitting result ...");
|
||||
EmitResult result = compilation.Emit(ms);
|
||||
foreach (Diagnostic diagnostic in result.Diagnostics.Where(diagnostic =>
|
||||
diagnostic.Severity < DiagnosticSeverity.Error && !diagnostic.IsWarningAsError))
|
||||
{
|
||||
logger.LogWarning("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
|
||||
logger.LogWarning("{0}: {1}", diagnostic.Id, diagnostic.Location.GetLineSpan());
|
||||
}
|
||||
if (!result.Success)
|
||||
{
|
||||
|
||||
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
|
||||
diagnostic.IsWarningAsError ||
|
||||
diagnostic.Severity == DiagnosticSeverity.Error);
|
||||
foreach (Diagnostic diagnostic in failures)
|
||||
{
|
||||
logger.LogCritical("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
|
||||
logger.LogCritical("{0}: {1}", diagnostic.Id, diagnostic.Location.GetLineSpan());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
Assembly assembly = Assembly.Load(ms.ToArray());
|
||||
|
||||
Type type = assembly.GetType(Namespaces + "." + className);
|
||||
var generatedtemplate = (UserOrientedTemplate)Activator.CreateInstance(type);
|
||||
foreach (var user in dbContext.ApplicationUser.Where(
|
||||
u => u.AllowMonthlyEmail
|
||||
))
|
||||
{
|
||||
logger.LogInformation("Generation for " + user.UserName);
|
||||
generatedtemplate.Init();
|
||||
generatedtemplate.User = user;
|
||||
generatedtemplate.ExecuteAsync();
|
||||
logger.LogInformation(generatedtemplate.GeneratedText);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Options;
|
||||
using rules;
|
||||
using Yavsc.Helpers;
|
||||
using Yavsc.Models;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
public class FileSystemAuthManager : IFileSystemAuthManager
|
||||
{
|
||||
class BelongsToCircle : UserMatch
|
||||
{
|
||||
public override bool Match(string userId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class OutOfCircle : UserMatch
|
||||
{
|
||||
public override bool Match(string userId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly UserMatch Out = new OutOfCircle();
|
||||
private readonly UserMatch In = new BelongsToCircle();
|
||||
|
||||
private readonly ApplicationDbContext _dbContext;
|
||||
|
||||
private readonly SiteSettings SiteSettings;
|
||||
|
||||
private readonly string aclfileName;
|
||||
|
||||
readonly RuleSetParser ruleSetParser;
|
||||
|
||||
public FileSystemAuthManager(ApplicationDbContext dbContext, IOptions<SiteSettings> sitesOptions)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
SiteSettings = sitesOptions.Value;
|
||||
aclfileName = SiteSettings.AccessListFileName;
|
||||
ruleSetParser = new RuleSetParser(false);
|
||||
}
|
||||
|
||||
public FileAccessRight GetFilePathAccess(ClaimsPrincipal user, IFileInfo file)
|
||||
{
|
||||
var parts = file.PhysicalPath.Split(Path.DirectorySeparatorChar);
|
||||
var cwd = Environment.CurrentDirectory.Split(Path.DirectorySeparatorChar).Length;
|
||||
|
||||
|
||||
// below 3 parts behind cwd, no file name.
|
||||
if (parts.Length < cwd + 3) return FileAccessRight.None;
|
||||
|
||||
var fileDir = string.Join("/", parts.Take(parts.Length - 1));
|
||||
var fileName = parts[parts.Length - 1];
|
||||
|
||||
var cusername = user.GetUserName();
|
||||
|
||||
var funame = parts[cwd+1];
|
||||
if (funame == cusername)
|
||||
{
|
||||
return FileAccessRight.Read | FileAccessRight.Write;
|
||||
}
|
||||
|
||||
if (aclfileName == fileName)
|
||||
return FileAccessRight.None;
|
||||
|
||||
ruleSetParser.Reset();
|
||||
var cuserid = user.GetUserId();
|
||||
|
||||
var fuserid = _dbContext.Users.SingleOrDefault(u => u.UserName == funame).Id;
|
||||
|
||||
if (string.IsNullOrEmpty(fuserid)) return FileAccessRight.None;
|
||||
|
||||
var circles = _dbContext.Circle.Include(mb => mb.Members).Where(c => c.OwnerId == fuserid).ToArray();
|
||||
foreach (var circle in circles)
|
||||
{
|
||||
if (circle.Members.Any(m => m.MemberId == cuserid))
|
||||
ruleSetParser.Definitions.Add(circle.Name, In);
|
||||
else ruleSetParser.Definitions.Add(circle.Name, Out);
|
||||
}
|
||||
|
||||
for (int dirlevel = parts.Length - 1; dirlevel > cwd + 1; dirlevel--)
|
||||
{
|
||||
fileDir = string.Join(Path.DirectorySeparatorChar.ToString(), parts.Take(dirlevel));
|
||||
var aclfin = Path.Combine(fileDir, aclfileName);
|
||||
var aclfi = new FileInfo(aclfin);
|
||||
if (!aclfi.Exists) continue;
|
||||
ruleSetParser.ParseFile(aclfi.FullName);
|
||||
}
|
||||
|
||||
if (ruleSetParser.Rules.Allow(cusername))
|
||||
{
|
||||
return FileAccessRight.Read;
|
||||
}
|
||||
return FileAccessRight.None;
|
||||
// TODO default user scoped file access policy
|
||||
|
||||
}
|
||||
|
||||
public string NormalizePath(string path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetAccess(long circleId, string normalizedFullPath, FileAccessRight access)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,270 +0,0 @@
|
||||
//
|
||||
// CalendarApi.cs
|
||||
//
|
||||
// Author:
|
||||
// Paul Schneider <paulschneider@free.fr>
|
||||
//
|
||||
// Copyright (c) 2015 - 2017 Paul Schneider
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Google.Apis.Auth.OAuth2;
|
||||
using Google.Apis.Calendar.v3;
|
||||
using Google.Apis.Calendar.v3.Data;
|
||||
using Google.Apis.Services;
|
||||
using Google.Apis.Auth.OAuth2.Responses;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
using Microsoft.Extensions.Options;
|
||||
using Yavsc.Models.Calendar;
|
||||
using Yavsc.Server.Helpers;
|
||||
using Yavsc.Server.Models.Calendar;
|
||||
using Yavsc.ViewModels.Calendar;
|
||||
|
||||
/// <summary>
|
||||
/// Google Calendar API client.
|
||||
/// </summary>
|
||||
public class CalendarManager : ICalendarManager
|
||||
{
|
||||
public class ExpiredTokenException : Exception { }
|
||||
protected static string[] scopesCalendar =
|
||||
{ "https://www.googleapis.com/auth/calendar",
|
||||
"https://www.googleapis.com/auth/calendar.events"
|
||||
};
|
||||
readonly ILogger _logger;
|
||||
readonly string _client_id;
|
||||
readonly string _client_secret;
|
||||
|
||||
public CalendarManager(ILoggerFactory loggerFactory, IOptions<GoogleAuthSettings> googleAuthSettings)
|
||||
{
|
||||
_client_id = googleAuthSettings.Value.ClientId;
|
||||
_client_secret = googleAuthSettings.Value.ClientSecret;
|
||||
_logger = loggerFactory.CreateLogger<CalendarManager>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The get cal list URI.
|
||||
/// </summary>
|
||||
protected static string getCalListUri = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
|
||||
/// <summary>
|
||||
/// The get cal entries URI.
|
||||
/// </summary>
|
||||
protected static string getCalEntriesUri = "https://www.googleapis.com/calendar/v3/calendars/{0}/events";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the calendar list.
|
||||
/// </summary>
|
||||
/// <returns>The calendars.</returns>
|
||||
/// <param name="userId">Yavsc user id</param>
|
||||
public async Task<CalendarList> GetCalendarsAsync(string pageToken)
|
||||
{
|
||||
var service = await CreateUserCalendarServiceAsync();
|
||||
#if Debug
|
||||
if (service==null) throw new Exception("Could not get service");
|
||||
#endif
|
||||
_logger.LogInformation("Got a service");
|
||||
|
||||
#if Debug
|
||||
if (service.CalendarList==null) throw new Exception("Could not get calendar list");
|
||||
#endif
|
||||
CalendarListResource.ListRequest calListReq = service.CalendarList.List();
|
||||
|
||||
#if Debug
|
||||
if (calListReq==null) throw new Exception ("list is null");
|
||||
#endif
|
||||
|
||||
calListReq.PageToken = pageToken;
|
||||
return calListReq.Execute();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a calendar event list, between the given dates.
|
||||
/// </summary>
|
||||
/// <returns>The calendar.</returns>
|
||||
/// <param name="calid">Calendar identifier.</param>
|
||||
/// <param name="mindate">Mindate.</param>
|
||||
/// <param name="maxdate">Maxdate.</param>
|
||||
/// <param name="cred">credential string.</param>
|
||||
public async Task<Events> GetCalendarAsync(string calid, DateTime minDate, DateTime maxDate, string pageToken)
|
||||
{
|
||||
var service = await GetServiceAsync();
|
||||
|
||||
var listRequest = service.Events.List(calid);
|
||||
listRequest.PageToken = pageToken;
|
||||
listRequest.TimeMin = minDate;
|
||||
listRequest.TimeMax = maxDate;
|
||||
listRequest.SingleEvents = true;
|
||||
return await listRequest.ExecuteAsync();
|
||||
}
|
||||
public async Task<DateTimeChooserViewModel> CreateViewModelAsync(
|
||||
string inputId,
|
||||
string calid, DateTime mindate, DateTime maxdate)
|
||||
{
|
||||
if (calid == null)
|
||||
return new DateTimeChooserViewModel
|
||||
{
|
||||
InputId = inputId,
|
||||
MinDate = mindate,
|
||||
MaxDate = maxdate
|
||||
};
|
||||
|
||||
var eventList = await GetCalendarAsync(calid, mindate, maxdate, null);
|
||||
List<Period> free = new List<Period>();
|
||||
List<Period> busy = new List<Period>();
|
||||
|
||||
foreach (var ev in eventList.Items)
|
||||
{
|
||||
if (ev.Start.DateTime.HasValue && ev.End.DateTime.HasValue)
|
||||
{
|
||||
DateTime start = ev.Start.DateTime.Value;
|
||||
DateTime end = ev.End.DateTime.Value;
|
||||
|
||||
if (ev.Transparency == "transparent")
|
||||
{
|
||||
|
||||
free.Add(new Period { Start = start, End = end });
|
||||
}
|
||||
else busy.Add(new Period { Start = start, End = end });
|
||||
}
|
||||
}
|
||||
|
||||
return new DateTimeChooserViewModel
|
||||
{
|
||||
InputId = inputId,
|
||||
MinDate = mindate,
|
||||
MaxDate = maxdate,
|
||||
Free = free.ToArray(),
|
||||
Busy = busy.ToArray(),
|
||||
FreeDates = free.SelectMany(p => new string[] { p.Start.ToString("dd/MM/yyyy HH:mm"), p.End.ToString("dd/MM/yyyy HH:mm") }).Distinct().ToArray(),
|
||||
BusyDates = busy.SelectMany(p => new string[] { p.Start.ToString("dd/MM/yyyy HH:mm"), p.End.ToString("dd/MM/yyyy HH:mm") }).Distinct().ToArray()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a event in a calendar
|
||||
/// <c>calendar.events.insert</c>
|
||||
/// </summary>
|
||||
/// <param name="calid"></param>
|
||||
/// <param name="startDate"></param>
|
||||
/// <param name="lengthInSeconds"></param>
|
||||
/// <param name="summary"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <param name="location"></param>
|
||||
/// <param name="available"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<Event> CreateEventAsync(string userId, string calid, DateTime startDate, int lengthInSeconds, string summary, string description, string location, bool available)
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(calid))
|
||||
throw new Exception("the calendar identifier is not specified");
|
||||
|
||||
var service = await GetServiceAsync();
|
||||
Event ev = new Event
|
||||
{
|
||||
Start = new EventDateTime { DateTime = startDate },
|
||||
End = new EventDateTime { DateTime = startDate.AddSeconds(lengthInSeconds) },
|
||||
Summary = summary,
|
||||
Description = description
|
||||
};
|
||||
var insert = service.Events.Insert(ev, calid);
|
||||
var inserted = await insert.ExecuteAsync();
|
||||
|
||||
return inserted;
|
||||
}
|
||||
CalendarService _service = null;
|
||||
public async Task<CalendarService> GetServiceAsync()
|
||||
{
|
||||
if (_service == null)
|
||||
{
|
||||
GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync();
|
||||
var baseClientService = new BaseClientService.Initializer()
|
||||
{
|
||||
HttpClientInitializer = credential
|
||||
};
|
||||
if (credential.IsCreateScopedRequired)
|
||||
{
|
||||
credential = credential.CreateScoped(scopesCalendar);
|
||||
}/*
|
||||
var credential = await GoogleHelpers.GetCredentialForApi(new string [] { scopeCalendar });
|
||||
if (credential.IsCreateScopedRequired)
|
||||
{
|
||||
credential = credential.CreateScoped(scopeCalendar);
|
||||
}
|
||||
_service = new CalendarService(new BaseClientService.Initializer()
|
||||
{
|
||||
HttpClientInitializer = credential,
|
||||
ApplicationName = "Yavsc"
|
||||
});
|
||||
}*/
|
||||
_service = new CalendarService(new BaseClientService.Initializer()
|
||||
{
|
||||
HttpClientInitializer = credential,
|
||||
ApplicationName = "Yavsc"
|
||||
});
|
||||
}
|
||||
return _service;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates Google User Credential
|
||||
/// </summary>
|
||||
/// <param name="userId">Yavsc use id</param>
|
||||
/// <returns></returns>
|
||||
public async Task<CalendarService> CreateUserCalendarServiceAsync()
|
||||
{
|
||||
GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync();
|
||||
|
||||
if (credential.IsCreateScopedRequired)
|
||||
{
|
||||
credential = credential.CreateScoped(scopesCalendar);
|
||||
}
|
||||
|
||||
|
||||
var service = new CalendarService(new BaseClientService.Initializer()
|
||||
{
|
||||
HttpClientInitializer = credential,
|
||||
ApplicationName = "yavsc-001"
|
||||
});
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
public async Task<TokenResponse> RefreshToken(TokenResponse oldResponse)
|
||||
{
|
||||
string ep = " https://www.googleapis.com/oauth2/v4/token";
|
||||
_logger.LogInformation($"rt:{oldResponse.RefreshToken}");
|
||||
// refresh_token client_id client_secret grant_type=refresh_token
|
||||
try
|
||||
{
|
||||
using (var m = new SimpleJsonPostMethod(ep))
|
||||
{
|
||||
return await m.Invoke<TokenResponse>(
|
||||
new
|
||||
{
|
||||
refresh_token = oldResponse.RefreshToken,
|
||||
client_id = _client_id,
|
||||
client_secret = _client_secret,
|
||||
grant_type = "refresh_token"
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Quelque chose s'est mal passé à l'envoi", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
|
||||
using System.Security.Claims;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
[Flags]
|
||||
public enum FileAccessRight {
|
||||
None = 0,
|
||||
|
||||
Read = 1,
|
||||
Write = 2
|
||||
}
|
||||
|
||||
public interface IFileSystemAuthManager {
|
||||
string NormalizePath (string path);
|
||||
|
||||
/// <summary>
|
||||
/// A full path starts with a slash,
|
||||
/// continues with a user name,
|
||||
/// and returns true by the helper fonction :
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="normalizedFullPath"></param>
|
||||
/// <returns></returns>
|
||||
FileAccessRight GetFilePathAccess(ClaimsPrincipal user, IFileInfo file);
|
||||
|
||||
void SetAccess (long circleId, string normalizedFullPath, FileAccessRight access);
|
||||
|
||||
}
|
||||
}
|
@ -1,200 +0,0 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net.WebSockets;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.ViewModels.Streaming;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
|
||||
public class LiveProcessor : ILiveProcessor
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ConcurrentDictionary<string, LiveCastHandler> Casters { get; } = new ConcurrentDictionary<string, LiveCastHandler>();
|
||||
|
||||
public LiveProcessor(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<LiveProcessor>();
|
||||
}
|
||||
|
||||
public async Task<bool> AcceptStream(HttpContext context, ApplicationUser user, string destDir, string fileName)
|
||||
{
|
||||
// TODO defer request handling
|
||||
string uname = user.UserName;
|
||||
LiveCastHandler liveHandler = null;
|
||||
if (Casters.ContainsKey(uname))
|
||||
{
|
||||
_logger.LogWarning($"Casters.ContainsKey({uname})");
|
||||
liveHandler = Casters[uname];
|
||||
if (liveHandler.Socket.State == WebSocketState.Open || liveHandler.Socket.State == WebSocketState.Connecting)
|
||||
{
|
||||
_logger.LogWarning($"Closing cx");
|
||||
// FIXME loosed connexion should be detected & disposed else where
|
||||
await liveHandler.Socket.CloseAsync(WebSocketCloseStatus.EndpointUnavailable, "one by user", CancellationToken.None);
|
||||
|
||||
}
|
||||
if (!liveHandler.TokenSource.IsCancellationRequested)
|
||||
{
|
||||
liveHandler.TokenSource.Cancel();
|
||||
}
|
||||
liveHandler.Socket.Dispose();
|
||||
liveHandler.Socket = await context.WebSockets.AcceptWebSocketAsync();
|
||||
liveHandler.TokenSource = new CancellationTokenSource();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation($"new caster");
|
||||
// Accept the socket
|
||||
liveHandler = new LiveCastHandler { Socket = await context.WebSockets.AcceptWebSocketAsync() };
|
||||
}
|
||||
_logger.LogInformation("Accepted web socket");
|
||||
// Dispatch the flow
|
||||
|
||||
try
|
||||
{
|
||||
if (liveHandler.Socket != null && liveHandler.Socket.State == WebSocketState.Open)
|
||||
{
|
||||
Casters[uname] = liveHandler;
|
||||
// TODO: Handle the socket here.
|
||||
// Find receivers: others in the chat room
|
||||
// send them the flow
|
||||
var buffer = new byte[Constants.WebSocketsMaxBufLen];
|
||||
var sBuffer = new ArraySegment<byte>(buffer);
|
||||
_logger.LogInformation("Receiving bytes...");
|
||||
|
||||
WebSocketReceiveResult received = await liveHandler.Socket.ReceiveAsync(sBuffer, liveHandler.TokenSource.Token);
|
||||
|
||||
_logger.LogInformation($"Received bytes : {received.Count}");
|
||||
_logger.LogInformation($"Is the end : {received.EndOfMessage}");
|
||||
|
||||
|
||||
|
||||
var fsInputQueue = new Queue<ArraySegment<byte>>();
|
||||
|
||||
bool endOfInput = false;
|
||||
sBuffer = new ArraySegment<byte>(buffer,0,received.Count);
|
||||
fsInputQueue.Enqueue(sBuffer);
|
||||
var taskWritingToFs = liveHandler.ReceiveUserFile(user, _logger, destDir, fsInputQueue, fileName, () => endOfInput);
|
||||
|
||||
|
||||
Stack<string> ToClose = new Stack<string>();
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
_logger.LogInformation($"Echoing {received.Count} bytes received in a {received.MessageType} message; Fin={received.EndOfMessage}");
|
||||
// Echo anything we receive
|
||||
// and send to all listner found
|
||||
_logger.LogInformation($"{liveHandler.Listeners.Count} listeners");
|
||||
foreach (var cliItem in liveHandler.Listeners)
|
||||
{
|
||||
var listenningSocket = cliItem.Value;
|
||||
if (listenningSocket.State == WebSocketState.Open)
|
||||
{
|
||||
_logger.LogInformation(cliItem.Key);
|
||||
await listenningSocket.SendAsync(
|
||||
sBuffer, received.MessageType, received.EndOfMessage, liveHandler.TokenSource.Token);
|
||||
}
|
||||
else if (listenningSocket.State == WebSocketState.CloseReceived || listenningSocket.State == WebSocketState.CloseSent)
|
||||
{
|
||||
ToClose.Push(cliItem.Key);
|
||||
}
|
||||
}
|
||||
|
||||
if (!received.CloseStatus.HasValue)
|
||||
{
|
||||
_logger.LogInformation("try and receive new bytes");
|
||||
|
||||
buffer = new byte[Constants.WebSocketsMaxBufLen];
|
||||
received = await liveHandler.Socket.ReceiveAsync(sBuffer, liveHandler.TokenSource.Token);
|
||||
|
||||
_logger.LogInformation($"Received bytes : {received.Count}");
|
||||
|
||||
sBuffer = new ArraySegment<byte>(buffer,0,received.Count);
|
||||
_logger.LogInformation($"segment : offset: {sBuffer.Offset} count: {sBuffer.Count}");
|
||||
_logger.LogInformation($"Is the end : {received.EndOfMessage}");
|
||||
|
||||
if (received.CloseStatus.HasValue)
|
||||
{
|
||||
endOfInput=true;
|
||||
_logger.LogInformation($"received a close status: {received.CloseStatus.Value}: {received.CloseStatusDescription}");
|
||||
}
|
||||
else fsInputQueue.Enqueue(sBuffer);
|
||||
}
|
||||
else endOfInput=true;
|
||||
while (ToClose.Count > 0)
|
||||
{
|
||||
string no = ToClose.Pop();
|
||||
_logger.LogInformation("Closing follower connection");
|
||||
WebSocket listenningSocket;
|
||||
if (liveHandler.Listeners.TryRemove(no, out listenningSocket))
|
||||
{
|
||||
await listenningSocket.CloseAsync(WebSocketCloseStatus.EndpointUnavailable,
|
||||
"State != WebSocketState.Open", CancellationToken.None);
|
||||
listenningSocket.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
while (liveHandler.Socket.State == WebSocketState.Open);
|
||||
|
||||
_logger.LogInformation("Closing connection");
|
||||
taskWritingToFs.Wait();
|
||||
await liveHandler.Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, received.CloseStatusDescription, liveHandler.TokenSource.Token);
|
||||
|
||||
liveHandler.TokenSource.Cancel();
|
||||
liveHandler.Dispose();
|
||||
_logger.LogInformation("Resulting file : " + JsonConvert.SerializeObject(taskWritingToFs.Result));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"Exception occured : {ex.Message}");
|
||||
_logger.LogError(ex.StackTrace);
|
||||
liveHandler.TokenSource.Cancel();
|
||||
throw;
|
||||
}
|
||||
taskWritingToFs.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Socket was not accepted open ...
|
||||
// not (meta.Socket != null && meta.Socket.State == WebSocketState.Open)
|
||||
if (liveHandler.Socket != null)
|
||||
{
|
||||
_logger.LogError($"meta.Socket.State not Open: {liveHandler.Socket.State} ");
|
||||
liveHandler.Socket.Dispose();
|
||||
}
|
||||
else
|
||||
_logger.LogError("socket object is null");
|
||||
}
|
||||
|
||||
RemoveLiveInfo(uname);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
if (ex.Message == "Unexpected end of stream")
|
||||
{
|
||||
_logger.LogError($"Unexpected end of stream");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError($"Really unexpected end of stream");
|
||||
await liveHandler.Socket?.CloseAsync(WebSocketCloseStatus.EndpointUnavailable, ex.Message, CancellationToken.None);
|
||||
}
|
||||
liveHandler.Socket?.Dispose();
|
||||
RemoveLiveInfo(uname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void RemoveLiveInfo(string userName)
|
||||
{
|
||||
LiveCastHandler caster;
|
||||
if (Casters.TryRemove(userName, out caster))
|
||||
_logger.LogInformation("removed live info");
|
||||
else
|
||||
_logger.LogError("could not remove live info");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using MailKit.Net.Smtp;
|
||||
using MailKit.Security;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
using Yavsc.Abstract.Manage;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Yavsc.Interface;
|
||||
using Yavsc.Settings;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
public class MailSender : IEmailSender, ITrueEmailSender
|
||||
{
|
||||
readonly SiteSettings siteSettings;
|
||||
readonly SmtpSettings smtpSettings;
|
||||
private readonly ILogger logger;
|
||||
|
||||
public MailSender(
|
||||
IOptions<SiteSettings> sitesOptions,
|
||||
IOptions<SmtpSettings> smtpOptions,
|
||||
ILoggerFactory loggerFactory
|
||||
)
|
||||
{
|
||||
siteSettings = sitesOptions.Value;
|
||||
smtpSettings = smtpOptions.Value;
|
||||
logger = loggerFactory.CreateLogger<MailSender>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="googleSettings"></param>
|
||||
/// <param name="registrationId"></param>
|
||||
/// <param name="ev"></param>
|
||||
/// <returns>a MessageWithPayloadResponse,
|
||||
/// <c>bool somethingsent = (response.failure == 0 && response.success > 0)</c>
|
||||
/// </returns>
|
||||
|
||||
|
||||
public async Task SendEmailAsync(string email, string subject, string htmlMessage)
|
||||
{
|
||||
await SendEmailAsync("", email, subject, htmlMessage);
|
||||
}
|
||||
|
||||
public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage)
|
||||
{
|
||||
logger.LogInformation($"SendEmail for {email} : {subject}");
|
||||
MimeMessage msg = new ();
|
||||
msg.From.Add(new MailboxAddress(siteSettings.Owner.Name,
|
||||
siteSettings.Owner.EMail));
|
||||
msg.To.Add(new MailboxAddress(name, email));
|
||||
msg.Body = new TextPart("html")
|
||||
{
|
||||
Text = htmlMessage
|
||||
};
|
||||
msg.Subject = subject;
|
||||
msg.MessageId = MimeKit.Utils.MimeUtils.GenerateMessageId(
|
||||
siteSettings.Authority
|
||||
);
|
||||
using (SmtpClient sc = new ())
|
||||
{
|
||||
sc.Connect(
|
||||
smtpSettings.Server,
|
||||
smtpSettings.Port,
|
||||
SecureSocketOptions.Auto);
|
||||
|
||||
if (smtpSettings.UserName!=null) {
|
||||
NetworkCredential creds = new (
|
||||
smtpSettings.UserName, smtpSettings.Password);
|
||||
await sc.AuthenticateAsync(System.Text.Encoding.UTF8, creds, System.Threading.CancellationToken.None);
|
||||
}
|
||||
await sc.SendAsync(msg);
|
||||
logger.LogInformation($"Sent : {msg.MessageId}");
|
||||
}
|
||||
return msg.MessageId;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using IdentityModel;
|
||||
using IdentityServer8.Models;
|
||||
using IdentityServer8.Services;
|
||||
using IdentityServer8.Stores;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Yavsc.Models;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
public class ProfileService : DefaultProfileService, IProfileService
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
public ProfileService(
|
||||
UserManager<ApplicationUser> userManager, ILogger<DefaultProfileService> logger) : base(logger)
|
||||
{
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
public async Task<List<Claim>> GetClaimsFromUserAsync(
|
||||
ProfileDataRequestContext context,
|
||||
ApplicationUser user)
|
||||
{
|
||||
var requestedApiResources = context.RequestedResources.Resources.ApiResources.Select(
|
||||
r => r.Name
|
||||
).ToArray();
|
||||
var requestedApiScopes = context.RequestedResources.Resources.ApiScopes.Select(
|
||||
s => s.Name
|
||||
).ToArray();
|
||||
|
||||
var requestedScopes = context.Client.AllowedScopes
|
||||
.Where(s => s != JwtClaimTypes.Subject
|
||||
&& requestedApiScopes.Contains(s))
|
||||
.ToList();
|
||||
|
||||
if (context.RequestedClaimTypes.Contains("profile"))
|
||||
if (requestedScopes.Contains("profile"))
|
||||
{
|
||||
requestedScopes.Remove("profile");
|
||||
requestedScopes.Add(JwtClaimTypes.Name);
|
||||
requestedScopes.Add(JwtClaimTypes.FamilyName);
|
||||
requestedScopes.Add(JwtClaimTypes.Email);
|
||||
requestedScopes.Add(JwtClaimTypes.PreferredUserName);
|
||||
requestedScopes.Add(JwtClaimTypes.Role);
|
||||
}
|
||||
|
||||
var claims = new List<Claim> {
|
||||
new Claim(JwtClaimTypes.Subject,user.Id.ToString()),
|
||||
};
|
||||
if (requestedScopes.Contains(JwtClaimTypes.Name)||
|
||||
requestedScopes.Contains(JwtClaimTypes.FamilyName))
|
||||
{
|
||||
claims.Add(new Claim(JwtClaimTypes.Name, user.FullName));
|
||||
}
|
||||
|
||||
if (requestedScopes.Contains(JwtClaimTypes.PreferredUserName) )
|
||||
{
|
||||
claims.Add(new Claim(JwtClaimTypes.Name, user.UserName));
|
||||
}
|
||||
if (requestedScopes.Contains(JwtClaimTypes.Email))
|
||||
claims.Add(new Claim(JwtClaimTypes.Email, user.Email));
|
||||
|
||||
if (requestedScopes.Contains(JwtClaimTypes.Role))
|
||||
{
|
||||
var roles = await this._userManager.GetRolesAsync(user);
|
||||
if (roles.Count()>0)
|
||||
{
|
||||
claims.Add(new Claim(JwtClaimTypes.Role,String.Join(" ",roles)));
|
||||
}
|
||||
}
|
||||
return claims;
|
||||
}
|
||||
|
||||
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
|
||||
{
|
||||
var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
|
||||
var user = await _userManager.FindByIdAsync(subjectId);
|
||||
context.IssuedClaims = await GetClaimsFromUserAsync(context, user);
|
||||
}
|
||||
|
||||
public async Task IsActiveAsync(IsActiveContext context)
|
||||
{
|
||||
var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
|
||||
var user = await _userManager.FindByIdAsync(subjectId);
|
||||
context.IsActive = user != null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Yavsc.Helpers;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
using Models.societe.com;
|
||||
public class SIRENChecker
|
||||
{
|
||||
private readonly CompanyInfoSettings _settings;
|
||||
public SIRENChecker(CompanyInfoSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
public async Task<CompanyInfoMessage> CheckAsync(string siren) {
|
||||
using (var web = new HttpClient())
|
||||
{
|
||||
return await web.CheckSiren(siren, _settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
|
||||
using IdentityServer8.Models;
|
||||
using IdentityServer8.Stores;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Yavsc.Models;
|
||||
|
||||
namespace Yavsc.Services;
|
||||
|
||||
public class YavscClientStore : IClientStore
|
||||
{
|
||||
ApplicationDbContext _context=null;
|
||||
public YavscClientStore(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
|
||||
async Task<Client> IClientStore.FindClientByIdAsync(string clientId)
|
||||
{
|
||||
var app = await _context.Applications.FirstOrDefaultAsync(c=>c.Id == clientId);
|
||||
|
||||
if (app == null) return null;
|
||||
|
||||
Client client = new()
|
||||
{
|
||||
ClientId = app.Id,
|
||||
ClientName = app.DisplayName,
|
||||
AbsoluteRefreshTokenLifetime = app.RefreshTokenLifeTime,
|
||||
AccessTokenLifetime = app.AccessTokenLifetime,
|
||||
AllowedGrantTypes =
|
||||
[
|
||||
GrantType.AuthorizationCode,
|
||||
GrantType.DeviceFlow,
|
||||
GrantType.ClientCredentials
|
||||
],
|
||||
ClientSecrets = [
|
||||
new Secret(app.Secret),
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
switch(app.Type)
|
||||
{
|
||||
case Models.Auth.ApplicationTypes.NativeConfidential:
|
||||
client.AccessTokenType = AccessTokenType.Reference;
|
||||
client.AllowedGrantTypes =
|
||||
[
|
||||
GrantType.DeviceFlow
|
||||
];
|
||||
client.AllowedScopes = [] ;
|
||||
break;
|
||||
case Models.Auth.ApplicationTypes.JavaScript:
|
||||
default:
|
||||
client.AccessTokenType = AccessTokenType.Jwt;
|
||||
client.AllowedGrantTypes =
|
||||
[
|
||||
GrantType.AuthorizationCode,
|
||||
GrantType.ClientCredentials
|
||||
];
|
||||
client.AllowedScopes = ["openid", "profile"];
|
||||
break;
|
||||
|
||||
}
|
||||
return client;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using Yavsc.Interface;
|
||||
|
Reference in New Issue
Block a user