Refactoring
The main server owns the migrations, it's the server part, it's simpler. It's Yavsc, not one of its lib.
This commit is contained in:
parent
52edbff231
commit
b3d565b6d9
67 changed files with 130 additions and 164 deletions
|
|
@ -1,11 +1,6 @@
|
|||
using System.Security.Claims;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.Models.Blog;
|
||||
|
||||
namespace Yavsc.Helpers
|
||||
namespace Yavsc.Server.Helpers
|
||||
{
|
||||
public static class UserHelpers
|
||||
{
|
||||
|
|
@ -24,30 +19,5 @@ namespace Yavsc.Helpers
|
|||
return user.Identity.IsAuthenticated;
|
||||
}
|
||||
|
||||
public static IEnumerable<BlogPost> UserPosts(this ApplicationDbContext dbContext, string posterId, string? readerId)
|
||||
{
|
||||
if (readerId == null)
|
||||
{
|
||||
var userPosts = dbContext.blogSpotPublications.Include(
|
||||
b => b.BlogPost
|
||||
).Where(x => x.BlogPost.AuthorId == posterId)
|
||||
.Select(x=>x.BlogPost).ToArray();
|
||||
return userPosts;
|
||||
}
|
||||
else
|
||||
{
|
||||
long[] readerCirclesMemberships =
|
||||
dbContext.Circle.Include(c => c.Members)
|
||||
.Where(c => c.Members.Any(m => m.MemberId == readerId))
|
||||
.Select(c => c.Id).ToArray();
|
||||
return dbContext.BlogSpot.Include(
|
||||
b => b.Author
|
||||
).Include(p => p.ACL).Where(x => x.Author.Id == posterId &&
|
||||
(x.ACL.Count == 0 || x.ACL.Any(a => readerCirclesMemberships.Contains(a.CircleId))));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace Yavsc
|
|||
using Models.Chat;
|
||||
using Yavsc.Abstract.Chat;
|
||||
using Yavsc.Helpers;
|
||||
using Yavsc.Server.Helpers;
|
||||
using Yavsc.Services;
|
||||
public partial class ChatHub : Hub, IDisposable
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,26 +1,2 @@
|
|||
SOURCE_DIR=../..
|
||||
MAKEFILE_DIR=$(SOURCE_DIR)/scripts/make
|
||||
BASERESX=Resources/Yavsc.Models.Relationship.HyperLink.resx \
|
||||
Resources/Yavsc.Models.Streaming.LiveFlow.resx
|
||||
BASERESXGEN=$(BASERESX:.resx=.Designer.cs)
|
||||
|
||||
include $(MAKEFILE_DIR)/dnx.mk
|
||||
include $(MAKEFILE_DIR)/versioning.mk
|
||||
|
||||
default: all
|
||||
|
||||
$(BINTARGETPATH): ../OAuth.AspNet.AuthServer/bin/$(CONFIGURATION)/OAuth.AspNet.AuthServer.dll \
|
||||
../Yavsc.Abstract/bin/$(CONFIGURATION)/Yavsc.Abstract.dll prepare_code
|
||||
|
||||
../OAuth.AspNet.AuthServer/bin/$(CONFIGURATION)/OAuth.AspNet.AuthServer.dll:
|
||||
make -C ../OAuth.AspNet.AuthServer
|
||||
|
||||
../Yavsc.Abstract/bin/$(CONFIGURATION)/Yavsc.Abstract.dll:
|
||||
make -C ../Yavsc.Abstract
|
||||
|
||||
%.Designer.cs: %.resx
|
||||
strongresbuildercli -l -p -t -r "Yavsc.Server.Resources." $^
|
||||
|
||||
prepare_code: $(BASERESXGEN)
|
||||
|
||||
all: $(BINTARGETPATH)
|
||||
listConnections:
|
||||
dotnet ef migrations list --connection "$(YAVSC_CONNECTION_STRING)"
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ namespace Yavsc.Models
|
|||
|
||||
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
|
||||
{
|
||||
public ApplicationDbContext()
|
||||
{
|
||||
|
||||
}
|
||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,193 +0,0 @@
|
|||
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Yavsc;
|
||||
using Yavsc.Helpers;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.Models.Blog;
|
||||
using Yavsc.Server.Exceptions;
|
||||
using Yavsc.ViewModels.Auth;
|
||||
using Yavsc.ViewModels.Blog;
|
||||
|
||||
public class BlogSpotService
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
|
||||
|
||||
public BlogSpotService(ApplicationDbContext context,
|
||||
IAuthorizationService authorizationService)
|
||||
{
|
||||
_authorizationService = authorizationService;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public BlogPost Create(string userId, BlogPostEditViewModel blogInput)
|
||||
{
|
||||
BlogPost post = new BlogPost
|
||||
{
|
||||
Title = blogInput.Title,
|
||||
Content = blogInput.Content,
|
||||
Photo = blogInput.Photo,
|
||||
AuthorId = userId
|
||||
};
|
||||
_context.BlogSpot.Add(post);
|
||||
_context.SaveChanges(userId);
|
||||
return post;
|
||||
}
|
||||
public async Task<BlogPostEditViewModel> GetPostForEdition(ClaimsPrincipal user, long blogPostId)
|
||||
{
|
||||
var blog = await _context.BlogSpot.Include(x => x.Author).Include(x => x.ACL).SingleAsync(m => m.Id == blogPostId);
|
||||
var auth = await _authorizationService.AuthorizeAsync(user, blog, new EditPermission());
|
||||
if (!auth.Succeeded)
|
||||
{
|
||||
throw new AuthorizationFailureException(auth);
|
||||
}
|
||||
return BlogPostEditViewModel.From(blog);
|
||||
}
|
||||
|
||||
public async Task<BlogPost> Details(ClaimsPrincipal user, long blogPostId)
|
||||
{
|
||||
|
||||
BlogPost blog = await _context.BlogSpot
|
||||
.Include(p => p.Author)
|
||||
.Include(p => p.Tags)
|
||||
.Include(p => p.Comments)
|
||||
.Include(p => p.ACL)
|
||||
.SingleAsync(m => m.Id == blogPostId);
|
||||
if (blog == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var auth = await _authorizationService.AuthorizeAsync(user, blog, new ReadPermission());
|
||||
if (!auth.Succeeded)
|
||||
{
|
||||
throw new AuthorizationFailureException(auth);
|
||||
}
|
||||
foreach (var c in blog.Comments)
|
||||
{
|
||||
c.Author = _context.Users.First(u => u.Id == c.AuthorId);
|
||||
}
|
||||
return blog;
|
||||
}
|
||||
|
||||
public async Task Modify(ClaimsPrincipal user, BlogPostEditViewModel blogEdit)
|
||||
{
|
||||
var blog = _context.BlogSpot.SingleOrDefault(b => b.Id == blogEdit.Id);
|
||||
Debug.Assert(blog != null);
|
||||
var auth = await _authorizationService.AuthorizeAsync(user, blog, new EditPermission());
|
||||
if (!auth.Succeeded)
|
||||
{
|
||||
throw new AuthorizationFailureException(auth);
|
||||
}
|
||||
blog.Content = blogEdit.Content;
|
||||
blog.Title = blogEdit.Title;
|
||||
blog.Photo = blogEdit.Photo;
|
||||
blog.ACL = blogEdit.ACL;
|
||||
// saves the change
|
||||
_context.Update(blog);
|
||||
var publication = await _context.blogSpotPublications.SingleOrDefaultAsync
|
||||
(p=>p.BlogpostId==blogEdit.Id);
|
||||
if (publication != null)
|
||||
{
|
||||
if (!blogEdit.Publish)
|
||||
{
|
||||
_context.blogSpotPublications.Remove(publication);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (blogEdit.Publish)
|
||||
{
|
||||
_context.blogSpotPublications.Add(
|
||||
new BlogSpotPublication
|
||||
{
|
||||
BlogpostId = blogEdit.Id
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
_context.SaveChanges(user.GetUserId());
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<IBlogPost>> Index(ClaimsPrincipal user, string id, int skip = 0, int take = 25)
|
||||
{
|
||||
IEnumerable<IBlogPost> posts;
|
||||
|
||||
if (user.Identity.IsAuthenticated)
|
||||
{
|
||||
string viewerId = user.GetUserId();
|
||||
long[] userCircles = await _context.Circle.Include(c => c.Members).
|
||||
Where(c => c.Members.Any(m => m.MemberId == viewerId))
|
||||
.Select(c => c.Id).ToArrayAsync();
|
||||
|
||||
posts = _context.BlogSpot
|
||||
.Include(b => b.Author)
|
||||
.Include(p => p.ACL)
|
||||
.Include(p => p.Tags)
|
||||
.Include(p => p.Comments)
|
||||
.Where(p => p.ACL == null
|
||||
|| p.ACL.Count == 0
|
||||
|| (p.AuthorId == viewerId)
|
||||
|| (userCircles != null &&
|
||||
p.ACL.Any(a => userCircles.Contains(a.CircleId)))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
posts = _context.blogSpotPublications
|
||||
.Include(p => p.BlogPost)
|
||||
.Include(b => b.BlogPost.Author)
|
||||
.Include(p => p.BlogPost.ACL)
|
||||
.Include(p => p.BlogPost.Tags)
|
||||
.Include(p => p.BlogPost.Comments)
|
||||
.Where(p => p.BlogPost.ACL == null
|
||||
|| p.BlogPost.ACL.Count == 0)
|
||||
.Select(p => p.BlogPost).ToArray();
|
||||
}
|
||||
|
||||
var data = posts.OrderByDescending(p => p.DateModified);
|
||||
return data;
|
||||
}
|
||||
|
||||
public async Task Delete(ClaimsPrincipal user, long id)
|
||||
{
|
||||
var uid = user.GetUserId();
|
||||
BlogPost blog = _context.BlogSpot.Single(m => m.Id == id);
|
||||
|
||||
_context.BlogSpot.Remove(blog);
|
||||
_context.SaveChanges(user.GetUserId());
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<BlogPost>> UserPosts(
|
||||
string posterName,
|
||||
string? readerId,
|
||||
int pageLen = 10,
|
||||
int pageNum = 0)
|
||||
{
|
||||
string? posterId = (await _context.Users.SingleOrDefaultAsync(u => u.UserName == posterName))?.Id ?? null;
|
||||
if (posterId == null) return Array.Empty<BlogPost>();
|
||||
return _context.UserPosts(posterId, readerId);
|
||||
}
|
||||
|
||||
public object? GetTitle(string title)
|
||||
{
|
||||
return _context.BlogSpot.Include(
|
||||
b => b.Author
|
||||
).Where(x => x.Title == title).OrderByDescending(
|
||||
x => x.DateCreated
|
||||
).ToList();
|
||||
}
|
||||
|
||||
public async Task<BlogPost?> GetBlogPostAsync(long value)
|
||||
{
|
||||
return await _context.BlogSpot
|
||||
.Include(b => b.Author)
|
||||
.Include(b => b.ACL)
|
||||
.SingleOrDefaultAsync(x => x.Id == value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,345 +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;
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using Microsoft.Extensions.Options;
|
|||
using rules;
|
||||
using Yavsc.Helpers;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.Server.Helpers;
|
||||
|
||||
namespace Yavsc.Services
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,171 +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;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Diagnostics;
|
||||
using RazorEngine.Compilation.ImpromptuInterface.Optimization;
|
||||
using RazorEngine.Compilation.ImpromptuInterface;
|
||||
|
||||
namespace Yavsc.Lib
|
||||
{
|
||||
public class YavscTemplateEngine
|
||||
{
|
||||
ISet<string> Namespaces = new System.Collections.Generic.HashSet<string> {
|
||||
"System",
|
||||
"Yavsc.Templates" ,
|
||||
"Yavsc.Models",
|
||||
"Yavsc.Models.Identity"};
|
||||
|
||||
readonly IStringLocalizer<YavscTemplateEngine> stringLocalizer;
|
||||
readonly ApplicationDbContext dbContext;
|
||||
|
||||
readonly ILogger logger;
|
||||
|
||||
public YavscTemplateEngine(ApplicationDbContext dbContext,
|
||||
IStringLocalizer<YavscTemplateEngine> localizer,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
stringLocalizer = localizer;
|
||||
this.dbContext = dbContext;
|
||||
|
||||
logger = loggerFactory.CreateLogger<YavscTemplateEngine>();
|
||||
}
|
||||
|
||||
public string RunUserTemplate(string templateCode)
|
||||
{
|
||||
|
||||
string subtemp = stringLocalizer["MonthlySubjectTemplate"].Value;
|
||||
|
||||
logger.LogInformation($"Generating SendMonthlyEmail {templateCode}");
|
||||
|
||||
|
||||
var templateInfo = dbContext.MailingTemplate.FirstOrDefault(t => t.Id == templateCode);
|
||||
Debug.Assert (templateInfo != null);
|
||||
var templatekey = RazorEngine.Engine.Razor.GetKey(templateInfo.Id);
|
||||
|
||||
logger.LogInformation($"Using code: {templateCode}, subject: {subtemp} ");
|
||||
logger.LogInformation("And body:\n" + templateInfo.Body);
|
||||
|
||||
|
||||
// Generate code for the template
|
||||
using (var inMemoryCsharpCode = new MemoryStream())
|
||||
{
|
||||
using (var writter = new StreamWriter(inMemoryCsharpCode))
|
||||
{
|
||||
RazorEngine.Engine.Razor.Run(templatekey, writter);
|
||||
inMemoryCsharpCode.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(Encoding.Default.GetString(inMemoryCsharpCode.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 inMemoryAssembly = new MemoryStream())
|
||||
{
|
||||
logger.LogInformation("Emitting result ...");
|
||||
EmitResult result = compilation.Emit(inMemoryAssembly);
|
||||
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());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var user in dbContext.ApplicationUser.Where(
|
||||
u => u.AllowMonthlyEmail
|
||||
))
|
||||
{
|
||||
|
||||
var template = result.CallActLike<UserOrientedTemplate>(user);
|
||||
return template.GeneratedText;
|
||||
}
|
||||
|
||||
/* result.CallActLike<>
|
||||
|
||||
inMemoryAssembly.Seek(0, SeekOrigin.Begin);
|
||||
Assembly assembly = Assembly.Load(inMemoryAssembly.ToArray());
|
||||
// UserOrientedTemplate userOrientedTemplate = (UserOrientedTemplate)
|
||||
// FIXME Activator.CreateInstance(Type.GetType(templateInfo.TemplateType));
|
||||
|
||||
foreach (var user in dbContext.ApplicationUser.Where(
|
||||
u => u.AllowMonthlyEmail
|
||||
))
|
||||
{
|
||||
logger.LogInformation("Generation for " + user.UserName);
|
||||
userOrientedTemplate.Init();
|
||||
userOrientedTemplate.User = user; */
|
||||
throw new NotImplementedException();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue