This commit is contained in:
Paul Schneider 2026-02-14 16:54:27 +00:00
commit 45514010f2
3505 changed files with 154 additions and 523 deletions

View file

@ -0,0 +1,56 @@
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Yavsc.Abstract.Workflow;
using Yavsc.Models;
namespace Yavsc.Services
{
public class BillingService : IBillingService
{
public ApplicationDbContext DbContext { get; private set; }
public static Dictionary<string, Func<ApplicationDbContext, long, IDecidableQuery>> Billing =
new Dictionary<string, Func<ApplicationDbContext, long, IDecidableQuery>>();
public static List<PropertyInfo> UserSettings = new List<PropertyInfo>();
public static Dictionary<string, string> GlobalBillingMap =
new Dictionary<string, string>();
public Dictionary<string, string> BillingMap
{
get { return GlobalBillingMap; }
}
public BillingService(ApplicationDbContext dbContext)
{
DbContext = dbContext;
}
public Task<IDecidableQuery> GetBillAsync(string billingCode, long queryId)
{
return Task.FromResult(GetBillable(DbContext, billingCode, queryId));
}
public static IDecidableQuery GetBillable(ApplicationDbContext context, string billingCode, long queryId) => Billing[billingCode](context, queryId);
public async Task<IUserSettings> GetPerformersSettingsAsync(string activityCode, string userId)
{
var activity = await DbContext.Activities.SingleAsync(a => a.Code == activityCode);
if (activity.SettingsClassName == null) return null;
var dbSetGetter =
UserSettings.SingleOrDefault(s => s.Name == activity.SettingsClassName);
if (dbSetGetter==null) return null;
var dbSet = dbSetGetter.GetValue(DbContext);
if (dbSet == null) return null;
if (dbSet is DbSet<IUserSettings> userSettings)
{
return userSettings.FirstOrDefault(s => s.UserId == userId);
}
return null;
}
}
}

View file

@ -0,0 +1,13 @@
using Yavsc.Models.Blog;
public class BlogPostEdition
{
public string Content { get; internal set; }
public string Title { get; internal set; }
public string Photo { get; internal set; }
internal static BlogPostEdition From(BlogPost blog)
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,107 @@
using System.Security.Claims;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using rules;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Server.Helpers;
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;
readonly RuleSetParser ruleSetParser;
public FileSystemAuthManager(ApplicationDbContext dbContext, IOptions<SiteSettings> sitesOptions)
{
_dbContext = dbContext;
SiteSettings = sitesOptions.Value;
ruleSetParser = new RuleSetParser(false);
}
public FileAccessRight GetFilePathAccess(ClaimsPrincipal user, string fileRelativePath)
{
var cusername = user.GetUserName();
FileInfo fi = new FileInfo(
Path.Combine(Config.UserFilesDirName, fileRelativePath));
if (fileRelativePath.StartsWith(cusername+'/'))
{
return FileAccessRight.Read | FileAccessRight.Write;
}
var funame = fileRelativePath.Split('/')[0];
// TODO Assert valid user name
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);
}
var userFilesDir = new DirectoryInfo(
Path.Combine(Config.UserFilesDirName, funame));
var currentACLDir = fi.Directory;
do
{
var aclfileName = Path.Combine(currentACLDir.FullName,
SiteSettings.AccessListFileName);
FileInfo accessFileInfo = new FileInfo(aclfileName);
if (accessFileInfo.Exists)
ruleSetParser.ParseFile(accessFileInfo.FullName);
currentACLDir = currentACLDir.Parent;
} while (currentACLDir != userFilesDir);
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();
}
}
}

View file

@ -0,0 +1,271 @@
//
// 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.Logging;
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);
}
}
}
}

View file

@ -0,0 +1,84 @@
//
// MapTracks.cs
//
// Author:
// Paul Schneider <paulschneider@free.fr>
//
// Copyright (c) 2015 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 System.Threading.Tasks;
using Yavsc.Models.Google;
using Yavsc.Server.Helpers;
namespace Yavsc.GoogleApis
{
/// <summary>
/// Google Map tracks Api client.
/// </summary>
public class MapTracks {
protected static string scopeTracks = "https://www.googleapis.com/auth/tracks";
/// <summary>
/// Initializes a new instance of the <see cref="Yavsc.Helpers.Google.Api.MapTracks"/> class.
/// </summary>
/// <param name="authType">Auth type.</param>
/// <param name="redirectUri">Redirect URI.</param>
public MapTracks()
{}
/// <summary>
/// The google map tracks path (uri of the service).
/// </summary>
protected static string googleMapTracksPath = "https://www.googleapis.com/tracks/v1/";
// entities/[create|list|delete]
// collections/[list|create|[add|remove]entities|delete]
// crumbs/[record|getrecent|gethistory|report|summarize|getlocationinfo|delete
// entities/[create|list|delete]
// collections/[list|create|[add|remove]entities|delete]
// crumbs/[record|getrecent|gethistory|report|summarize|getlocationinfo|delete
/// <summary>
/// Creates the entity.
/// </summary>
/// <returns>The entity.</returns>
/// <param name="entities">Entities.</param>
public static async Task<string []> CreateEntity( Entity[] entities ) {
string [] ans = null;
using (SimpleJsonPostMethod wr =
new SimpleJsonPostMethod (googleMapTracksPath + "entities/create"))
{
ans = await wr.Invoke<string[]> (entities);
}
return ans;
}
/// <summary>
/// Lists the entities.
/// </summary>
/// <returns>The entities.</returns>
/// <param name="eq">Eq.</param>
static async Task <Entity[]> ListEntities (EntityQuery eq)
{
Entity [] ans = null;
using (SimpleJsonPostMethod wr =
new SimpleJsonPostMethod (googleMapTracksPath + "entities/create"))
{
ans = await wr.Invoke <Entity[]> (eq);
}
return ans;
}
}
}

View file

@ -0,0 +1,79 @@
//
// PeopleApi.cs
//
// Author:
// Paul Schneider <paul@pschneider.fr>
//
// Copyright (c) 2015 GNU GPL
//
// 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 System.IO;
using System.Net;
using Newtonsoft.Json;
using Yavsc.Abstract.Identity;
using Yavsc.Models.Google;
namespace Yavsc.GoogleApis
{
/// <summary>
/// Google People API.
/// </summary>
public class PeopleApi
{
/// <summary>
/// The get people URI.
/// </summary>
protected static string getPeopleUri = "https://www.googleapis.com/plus/v1/people";
/// <summary>
/// Initializes a new instance of the <see cref="Yavsc.Helpers.Google.Api.PeopleApi"/> class.
/// </summary>
/// <param name="authType">Auth type.</param>
/// <param name="redirectUri">Redirect URI.</param>
public PeopleApi()
{ }
/// <summary>
/// Gets the People object associated to the given Google Access Token
/// </summary>
/// <returns>The me.</returns>
/// <param name="gat">The Google Access Token object <see cref="AuthToken"/> class.</param>
public People GetMe(AuthToken gat)
{
People me;
HttpWebRequest webreppro = WebRequest.CreateHttp(getPeopleUri + "/me");
webreppro.ContentType = "application/http";
webreppro.Headers.Add(HttpRequestHeader.Authorization, gat.token_type + " " + gat.access_token);
webreppro.Method = "GET";
using (WebResponse proresp = webreppro.GetResponse())
{
using (Stream prresponseStream = proresp.GetResponseStream())
{
using (StreamReader rdr = new StreamReader(prresponseStream))
{
me = JsonConvert.DeserializeObject<People>(rdr.ReadToEnd());
prresponseStream.Close();
}
proresp.Close();
}
webreppro.Abort();
return me;
}
}
}
}

View file

@ -0,0 +1,29 @@
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>
///
/// </summary>
/// <param name="user"></param>
/// <param name="normalizedFullPath"></param>
/// <returns></returns>
FileAccessRight GetFilePathAccess(ClaimsPrincipal user, string fileRelativePath);
void SetAccess (long circleId, string normalizedFullPath, FileAccessRight access);
}
}

View file

@ -0,0 +1,202 @@
using System.Collections.Concurrent;
using System.Net.WebSockets;
using Yavsc.Models;
using Yavsc.ViewModels.Streaming;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
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");
}
}
}

View file

@ -0,0 +1,115 @@
using System.Net;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MimeKit;
using Microsoft.AspNetCore.Identity;
using Yavsc.Interface;
using Yavsc.Settings;
using Yavsc.Models;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Localization;
using System.Web;
namespace Yavsc.Services
{
public class MailSender : IEmailSender<ApplicationUser>, IEmailSender, ITrueEmailSender
{
private readonly IStringLocalizer<MailSender> localizer;
readonly SiteSettings siteSettings;
readonly SmtpSettings smtpSettings;
private readonly ILogger logger;
public MailSender(
IOptions<SiteSettings> sitesOptions,
IOptions<SmtpSettings> smtpOptions,
ILoggerFactory loggerFactory,
IStringLocalizer<MailSender> localizer
)
{
this.localizer = localizer;
siteSettings = sitesOptions.Value;
smtpSettings = smtpOptions.Value;
logger = loggerFactory.CreateLogger<MailSender>();
}
public Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="googleSettings"></param>
/// <param name="registrationId"></param>
/// <param name="ev"></param>
/// <returns>a MessageWithPayloadResponse,
/// <c>bool somethingsent = (response.failure == 0 &amp;&amp; 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)
{
sc.Authenticate(smtpSettings.UserName, smtpSettings.Password);
}
await sc.SendAsync(msg);
logger.LogInformation($"Sent : {msg.MessageId}");
sc.Disconnect(true);
}
return msg.MessageId;
}
public void SendEmailFromCriteria(string Criteria)
{
throw new NotImplementedException();
}
public async Task SendPasswordResetCodeAsync(ApplicationUser user, string email, string resetCode)
{
var callbackUrl = siteSettings.Audience + "/Account/ResetPassword/" +
HttpUtility.UrlEncode(user.Id) + "/" + HttpUtility.UrlEncode(resetCode);
await SendEmailAsync(user.UserName, user.Email,
localizer["Reset Password"],
localizer["Please reset your password by "] + " <a href=\"" +
callbackUrl + "\" >following this link</a>");
throw new NotImplementedException();
}
public async Task SendPasswordResetLinkAsync(ApplicationUser user, string email, string resetLink)
{
await SendEmailAsync(user.UserName, user.Email,
localizer["Reset Password"],
localizer["Please reset your password by "] + " <a href=\"" +
resetLink + "\" >following this link</a>");
}
}
}

View file

@ -0,0 +1,92 @@
using System.Security.Claims;
using IdentityModel;
using IdentityServer8.Models;
using IdentityServer8.Services;
using IdentityServer8.Stores;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Yavsc.Models;
namespace Yavsc.Services
{
public class ProfileService : IProfileService
{
private readonly UserManager<ApplicationUser> _userManager;
public ProfileService(
UserManager<ApplicationUser> userManager,
ILogger<DefaultProfileService> logger)
{
_userManager = userManager;
}
private async Task<List<Claim>> GetClaimsFromUserAsync(
ProfileDataRequestContext context,
ApplicationUser user)
{
var claims = new List<Claim> {
new Claim(JwtClaimTypes.Subject,user.Id.ToString()),
};
List<string> claimAdds = new List<string>();
foreach (var scope in context.RequestedResources.ParsedScopes)
{
if (context.Client.AllowedScopes.Contains(scope.ParsedName))
{
claims.Add(new Claim(JwtClaimTypes.Scope, scope.ParsedName));
claimAdds.Add(scope.ParsedName);
}
}
if (claimAdds.Contains(JwtClaimTypes.Profile))
{
claimAdds.Remove("profile");
claimAdds.Add(JwtClaimTypes.Name);
claimAdds.Add(JwtClaimTypes.Email);
claimAdds.Add(Constants.RoleClaimType);
}
if (claimAdds.Contains(JwtClaimTypes.Name))
claims.Add(new Claim(JwtClaimTypes.Name, user.FullName));
if (claimAdds.Contains(JwtClaimTypes.Email))
claims.Add(new Claim(JwtClaimTypes.Email, user.Email));
if (claimAdds.Contains(Constants.RoleClaimType))
{
var roles = await this._userManager.GetRolesAsync(user);
if (roles.Count()>0)
{
claims.AddRange(roles.Select(r => new Claim(Constants.RoleClaimType, r)));
}
}
return claims;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subjectId = GetSubjectId(context.Subject);
if (subjectId == null) return;
var user = await _userManager.FindByIdAsync(subjectId);
if (user == null) return;
context.IssuedClaims = await GetClaimsFromUserAsync(context, user);
}
public async Task IsActiveAsync(IsActiveContext context)
{
string? subjectId = GetSubjectId(context.Subject);
if (subjectId == null)
{
context.IsActive = false;
return;
}
var user = await _userManager.FindByIdAsync(subjectId);
context.IsActive = user != null;
}
private static string? GetSubjectId(ClaimsPrincipal claimsPrincipal)
{
return claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;
}
}
}

View file

@ -0,0 +1,22 @@
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);
}
}
}
}