using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using Microsoft.AspNet.SignalR.Owin; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Security.Principal; using Thermo.Active.Config; using Thermo.Active.Database.Controllers; using Thermo.Active.Model.DatabaseModels; using static Thermo.Active.Config.ServerConfig; using static Thermo.Active.Listeners.SignalRStaticObjects; using static Thermo.Active.Model.Constants; namespace Thermo.Active.Attributes { public class SignalRAuthorizeAttribute : AuthorizeAttribute { public string FunctionAccess; public ACTIONS Action; public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) { string token = request.QueryString["Authorization"]; using (SessionsController sessionsController = new SessionsController()) { // Find user session on this machine SessionModel session = sessionsController.FindSessionByToken(token); if (session == null) return false; } return base.AuthorizeHubConnection(hubDescriptor, request); } public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod) { var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId; var request = hubIncomingInvokerContext.Hub.Context.Request; var token = request.QueryString.Get("Authorization"); if (!string.IsNullOrEmpty(token)) { // check authorization if (!CheckAuthorization(FunctionAccess, token, out int machineId, out int userId)) return false; var claims = new ClaimsIdentity(AUTHENTICATION_TYPE); claims.AddClaim(new Claim(USER_ID_KEY, userId.ToString())); claims.AddClaim(new Claim(MACHINE_ID_KEY, machineId.ToString())); Dictionary _DCI = new Dictionary(); _DCI.Add("server.User", claims as IPrincipal); hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(_DCI), connectionId); return true; } return false; } private bool CheckAuthorization(string functionName, string token, out int machineId, out int userId) { machineId = userId = 0; using (SessionsController sessionsController = new SessionsController()) { // Find user session on this machine SessionModel session = sessionsController.FindSessionByToken(token); if (session == null) return false; // Check if the machine is the same where the user logged in if (session.MachineUser.MachineId != MachineConfig.MachineId) return false; machineId = session.MachineUser.MachineId; userId = session.MachineUser.UserId; MachineUserModel machineUser = new MachineUserModel(); using (MachinesUsersController machineUsersController = new MachinesUsersController()) { // Find machineUser data and joined to user data, role data, machine data machineUser = machineUsersController.FindByIdWithData(session.MachineUserId); } using (FunctionsAccessController acController = new FunctionsAccessController()) { // Read from db function levels FunctionAccessModel functionAccess = acController.FindEnabledFunctionByName(functionName); if (functionAccess != null && ServerConfigController.CheckAreaStatus(functionAccess.Area)) { if (Action == ACTIONS.READ) { // Check read permissions if (functionAccess.ReadLevelMin > machineUser.Role.Level) return false; // Not authorized } else { // Check write permissions if (functionAccess.WriteLevelMin > machineUser.Role.Level) return false; // Not authorized } // Check if PLC bit exists if (functionAccess.PlcId != 0) { // Check if functionality is enabled by PLC var functionalityIsEnabled = LastRuntimeFunctionality.Where(x => x.Name == functionName).FirstOrDefault(); if (functionalityIsEnabled == null || functionalityIsEnabled.Enabled == false) return false; } } else return false; // Authorized return true; } } } } }