//******************************************************************************************************
// SecurityHub.cs - Gbtc
//
// Copyright © 2016, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this
// file except in compliance with the License. You may obtain a copy of the License at:
//
// http://opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 03/03/2016 - Ritchie Carroll
// Generated original version of source code.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using GSF.Data.Model;
using GSF.Identity;
using GSF.Security;
using GSF.Security.Model;
using GSF.Web.Hubs;
using GSF.Web.Model;
using Microsoft.AspNet.SignalR.Hubs;
namespace GSF.Web.Security
{
///
/// Defines a SignalR security hub for managing users, groups and SID management.
///
[AuthorizeHubRole]
public class SecurityHub : RecordOperationsHub
{
#region [ Constructors ]
///
/// Creates a new .
///
public SecurityHub() :
this(null, null, null)
{
}
///
/// Creates a new with the specified logging functions.
///
/// Delegate to use to log status messages, if any.
/// Delegate to use to log exceptions, if any.
public SecurityHub(Action logStatusMessageFunction, Action logExceptionFunction) :
this(null, logStatusMessageFunction, logExceptionFunction)
{
}
///
/// Creates a new with the specified and logging functions.
///
/// Setting category that contains the connection settings. Defaults to "securityProvider".
/// Delegate to use to log status messages, if any.
/// Delegate to use to log exceptions, if any.
public SecurityHub(string settingsCategory, Action logStatusMessageFunction, Action logExceptionFunction) :
this(settingsCategory, logStatusMessageFunction, logExceptionFunction, true)
{
// Capture initial defaults
if ((object)logStatusMessageFunction != null && (object)s_logStatusMessageFunction == null)
s_logStatusMessageFunction = logStatusMessageFunction;
if ((object)logExceptionFunction != null && (object)s_logExceptionFunction == null)
s_logExceptionFunction = logExceptionFunction;
}
// ReSharper disable once UnusedParameter.Local
private SecurityHub(string settingsCategory, Action logStatusMessageFunction, Action logExceptionFunction, bool overload) :
base(settingsCategory ?? "securityProvider", logStatusMessageFunction ?? s_logStatusMessageFunction, logExceptionFunction ?? s_logExceptionFunction)
{
}
#endregion
#region [ Static ]
// Static Fields
private static Action s_logStatusMessageFunction;
private static Action s_logExceptionFunction;
// Static Properties
///
/// Gets current default Node ID for security.
///
public static readonly Guid DefaultNodeID = AdoSecurityProvider.DefaultNodeID;
#endregion
// Client-side script functionality
#region [ Security Functions ]
///
/// Resets the current provider cache.
///
/// Session ID as it appears in the cookie header value.
/// true if session was cleared; otherwise, false.
public bool Logout(string sessionCookieValue)
{
Guid sessionID;
SecurityPrincipal securityPrincipal;
if (!Guid.TryParse(sessionCookieValue, out sessionID))
return false;
// Flush any cached information that has been saved for this user including in the alternate SecurityProvider
if (AuthenticationHandler.TryGetPrincipal(sessionID, false, out securityPrincipal))
SecurityProviderCache.Flush(securityPrincipal.Identity.Name);
if (AuthenticationHandler.TryGetPrincipal(sessionID, true, out securityPrincipal))
SecurityProviderCache.Flush(securityPrincipal.Identity.Name);
// Clear any cached session state for user (this also clears any cached authorizations)
return SessionHandler.ClearSessionCache(sessionID);
}
///
/// Finds the specified user account record.
///
/// ID of requested user.
/// Specified user account record.
public UserAccount QueryUserAccount(Guid id)
{
return DataContext.Table().LoadRecord(id);
}
///
/// Finds the specified user account record by SID or database account name.
///
/// SID or database account name of requested user.
/// Specified user account record.
public UserAccount QueryUserAccountByName(string accountName)
{
return DataContext.Table().QueryRecordWhere("Name = {0}", accountName);
}
///
/// Searches user accounts by resolved names with no limit on total returned records.
///
/// Search text to lookup.
/// Search results as "IDLabel" instances - serialized as JSON [{ id : "value", label : "name" }, ...]; useful for dynamic lookup lists.
public IEnumerable SearchUserAccounts(string searchText)
{
return SearchUserAccounts(searchText, -1);
}
///
/// Searches user accounts by resolved names limited to the specified number of records.
///
/// Search text to lookup.
/// Limit of number of record to return.
/// Search results as "IDLabel" instances - serialized as JSON [{ id : "value", label : "name" }, ...]; useful for dynamic lookup lists.
public IEnumerable SearchUserAccounts(string searchText, int limit)
{
if (limit < 1)
return DataContext
.Table()
.QueryRecords()
.Select(record =>
{
record.Name = UserInfo.SIDToAccountName(record.Name ?? "");
return record;
})
.Where(record => record.Name?.StartsWith(searchText, StringComparison.InvariantCultureIgnoreCase) ?? false)
.Select(record => IDLabel.Create(record.ID.ToString(), record.Name));
return DataContext
.Table()
.QueryRecords()
.Select(record =>
{
record.Name = UserInfo.SIDToAccountName(record.Name ?? "");
return record;
})
.Where(record => record.Name?.StartsWith(searchText, StringComparison.InvariantCultureIgnoreCase) ?? false)
.Take(limit)
.Select(record => IDLabel.Create(record.ID.ToString(), record.Name));
}
///
/// Finds the specified security group record.
///
/// ID of requested group.
/// Specified security group record.
public SecurityGroup QuerySecurityGroup(Guid id)
{
return DataContext.Table().LoadRecord(id);
}
///
/// Finds the specified security group record by SID or database account name.
///
/// SID or database account name of requested group.
/// Specified security group record.
public SecurityGroup QuerySecurityGroupByName(string accountName)
{
return DataContext.Table().QueryRecordWhere("Name = {0}", accountName);
}
///
/// Searches security groups by resolved names.
///
/// Search text to lookup.
/// Search results as "Labels" - serialized as JSON [{ label : "value" }, ...]; useful for dynamic lookup lists.
public IEnumerable