Partial revert from 60b30ce542

Getting configuration via IServiceProvider
This commit is contained in:
pavelbannov 2019-05-17 14:58:09 +03:00
parent 60b30ce542
commit acb9457253
18 changed files with 1303 additions and 1334 deletions

View File

@ -1,405 +1,404 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Threading.Tasks;
using System.Web;
using ASC.Common.Data.AdoProxy;
using ASC.Common.Data.Sql;
using ASC.Common.Logging;
using ASC.Common.Web;
using Microsoft.AspNetCore.Http;
namespace ASC.Common.Data
{
public class DbManager : IDbManager
{
private readonly ILog logger = LogManager.GetLogger("ASC.SQL");
private readonly ProxyContext proxyContext;
private readonly bool shared;
private DbCommand command;
private ISqlDialect dialect;
private volatile bool disposed;
private readonly int? commandTimeout;
private DbCommand Command
{
get
{
CheckDispose();
if (command == null)
{
command = OpenConnection().CreateCommand();
}
if (command.Connection.State == ConnectionState.Closed || command.Connection.State == ConnectionState.Broken)
{
command = OpenConnection().CreateCommand();
}
if (commandTimeout.HasValue)
{
command.CommandTimeout = commandTimeout.Value;
}
return command;
}
}
public string DatabaseId { get; private set; }
public bool InTransaction
{
get { return Command.Transaction != null; }
}
public DbConnection Connection
{
get { return Command.Connection; }
}
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
DbRegistry DbRegistry { get => (DbRegistry)HttpContext.Current.RequestServices.GetService(typeof(DbRegistry)); }
public DbManager(string databaseId, int? commandTimeout = null)
: this(databaseId, true, commandTimeout)
{
}
public DbManager(string databaseId, bool shared, int? commandTimeout = null)
{
if (databaseId == null) throw new ArgumentNullException("databaseId");
DatabaseId = databaseId;
this.shared = shared;
if (logger.IsDebugEnabled)
{
proxyContext = new ProxyContext(AdoProxyExecutedEventHandler);
}
if (commandTimeout.HasValue)
{
this.commandTimeout = commandTimeout;
}
}
#region IDisposable Members
public void Dispose()
{
lock (this)
{
if (disposed) return;
disposed = true;
if (command != null)
{
if (command.Connection != null) command.Connection.Dispose();
command.Dispose();
command = null;
}
}
}
#endregion
public static IDbManager FromHttpContext(string databaseId)
{
if (HttpContext.Current != null)
{
var dbManager = DisposableHttpContext.Current[databaseId] as DbManager;
if (dbManager == null || dbManager.disposed)
{
var localDbManager = new DbManager(databaseId);
var dbManagerAdapter = new DbManagerProxy(localDbManager);
DisposableHttpContext.Current[databaseId] = localDbManager;
return dbManagerAdapter;
}
return new DbManagerProxy(dbManager);
}
return new DbManager(databaseId);
}
private DbConnection OpenConnection()
{
var connection = GetConnection();
connection.Open();
return connection;
}
private DbConnection GetConnection()
{
CheckDispose();
DbConnection connection = null;
string key = null;
if (shared && HttpContext.Current != null)
{
key = string.Format("Connection {0}|{1}", GetDialect(), DbRegistry.GetConnectionString(DatabaseId));
connection = DisposableHttpContext.Current[key] as DbConnection;
if (connection != null)
{
var state = ConnectionState.Closed;
var disposed = false;
try
{
state = connection.State;
}
catch (ObjectDisposedException)
{
disposed = true;
}
if (!disposed && (state == ConnectionState.Closed || state == ConnectionState.Broken))
{
if (string.IsNullOrEmpty(connection.ConnectionString))
{
connection.ConnectionString = DbRegistry.GetConnectionString(DatabaseId).ConnectionString;
}
return connection;
}
}
}
connection = DbRegistry.CreateDbConnection(DatabaseId);
if (proxyContext != null)
{
connection = new DbConnectionProxy(connection, proxyContext);
}
if (shared && HttpContext.Current != null) DisposableHttpContext.Current[key] = connection;
return connection;
}
public IDbTransaction BeginTransaction()
{
if (InTransaction) throw new InvalidOperationException("Transaction already open.");
Command.Transaction = Command.Connection.BeginTransaction();
var tx = new DbTransaction(Command.Transaction);
tx.Unavailable += TransactionUnavailable;
return tx;
}
public IDbTransaction BeginTransaction(IsolationLevel il)
{
if (InTransaction) throw new InvalidOperationException("Transaction already open.");
il = GetDialect().GetSupportedIsolationLevel(il);
Command.Transaction = Command.Connection.BeginTransaction(il);
var tx = new DbTransaction(Command.Transaction);
tx.Unavailable += TransactionUnavailable;
return tx;
}
public IDbTransaction BeginTransaction(bool nestedIfAlreadyOpen)
{
return nestedIfAlreadyOpen && InTransaction ? new DbNestedTransaction(Command.Transaction) : BeginTransaction();
}
public List<object[]> ExecuteList(string sql, params object[] parameters)
{
return Command.ExecuteList(sql, parameters);
}
public Task<List<object[]>> ExecuteListAsync(string sql, params object[] parameters)
{
return Command.ExecuteListAsync(sql, parameters);
}
public List<object[]> ExecuteList(ISqlInstruction sql)
{
return Command.ExecuteList(sql, GetDialect());
}
public Task<List<object[]>> ExecuteListAsync(ISqlInstruction sql)
{
return Command.ExecuteListAsync(sql, GetDialect());
}
public List<T> ExecuteList<T>(ISqlInstruction sql, Converter<IDataRecord, T> converter)
{
return Command.ExecuteList(sql, GetDialect(), converter);
}
public T ExecuteScalar<T>(string sql, params object[] parameters)
{
return Command.ExecuteScalar<T>(sql, parameters);
}
public T ExecuteScalar<T>(ISqlInstruction sql)
{
return Command.ExecuteScalar<T>(sql, GetDialect());
}
public int ExecuteNonQuery(string sql, params object[] parameters)
{
return Command.ExecuteNonQuery(sql, parameters);
}
public Task<int> ExecuteNonQueryAsync(string sql, params object[] parameters)
{
return Command.ExecuteNonQueryAsync(sql, parameters);
}
public int ExecuteNonQuery(ISqlInstruction sql)
{
return Command.ExecuteNonQuery(sql, GetDialect());
}
public int ExecuteBatch(IEnumerable<ISqlInstruction> batch)
{
if (batch == null) throw new ArgumentNullException("batch");
var affected = 0;
using (var tx = BeginTransaction())
{
foreach (var sql in batch)
{
affected += ExecuteNonQuery(sql);
}
tx.Commit();
}
return affected;
}
private void TransactionUnavailable(object sender, EventArgs e)
{
if (Command.Transaction != null)
{
Command.Transaction = null;
}
}
private void CheckDispose()
{
if (disposed) throw new ObjectDisposedException(GetType().FullName);
}
private ISqlDialect GetDialect()
{
return dialect ?? (dialect = DbRegistry.GetSqlDialect(DatabaseId));
}
private void AdoProxyExecutedEventHandler(ExecutedEventArgs a)
{
logger.DebugWithProps(a.SqlMethod,
new KeyValuePair<string, object>("duration", a.Duration.TotalMilliseconds),
new KeyValuePair<string, object>("sql", RemoveWhiteSpaces(a.Sql)),
new KeyValuePair<string, object>("sqlParams", RemoveWhiteSpaces(a.SqlParameters))
);
}
private string RemoveWhiteSpaces(string str)
{
return !string.IsNullOrEmpty(str) ?
str.Replace(Environment.NewLine, " ").Replace("\n", "").Replace("\r", "").Replace("\t", " ") :
string.Empty;
}
}
public class DbManagerProxy : IDbManager
{
private DbManager dbManager { get; set; }
public DbManagerProxy(DbManager dbManager)
{
this.dbManager = dbManager;
}
public void Dispose()
{
if (HttpContext.Current == null)
{
dbManager.Dispose();
}
}
public DbConnection Connection { get { return dbManager.Connection; } }
public string DatabaseId { get { return dbManager.DatabaseId; } }
public bool InTransaction { get { return dbManager.InTransaction; } }
public IDbTransaction BeginTransaction()
{
return dbManager.BeginTransaction();
}
public IDbTransaction BeginTransaction(IsolationLevel isolationLevel)
{
return dbManager.BeginTransaction(isolationLevel);
}
public IDbTransaction BeginTransaction(bool nestedIfAlreadyOpen)
{
return dbManager.BeginTransaction(nestedIfAlreadyOpen);
}
public List<object[]> ExecuteList(string sql, params object[] parameters)
{
return dbManager.ExecuteList(sql, parameters);
}
public List<object[]> ExecuteList(ISqlInstruction sql)
{
return dbManager.ExecuteList(sql);
}
public Task<List<object[]>> ExecuteListAsync(ISqlInstruction sql)
{
return dbManager.ExecuteListAsync(sql);
}
public List<T> ExecuteList<T>(ISqlInstruction sql, Converter<IDataRecord, T> converter)
{
return dbManager.ExecuteList<T>(sql, converter);
}
public T ExecuteScalar<T>(string sql, params object[] parameters)
{
return dbManager.ExecuteScalar<T>(sql, parameters);
}
public T ExecuteScalar<T>(ISqlInstruction sql)
{
return dbManager.ExecuteScalar<T>(sql);
}
public int ExecuteNonQuery(string sql, params object[] parameters)
{
return dbManager.ExecuteNonQuery(sql, parameters);
}
public int ExecuteNonQuery(ISqlInstruction sql)
{
return dbManager.ExecuteNonQuery(sql);
}
public int ExecuteBatch(IEnumerable<ISqlInstruction> batch)
{
return dbManager.ExecuteBatch(batch);
}
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Threading.Tasks;
using System.Web;
using ASC.Common.Data.AdoProxy;
using ASC.Common.Data.Sql;
using ASC.Common.Logging;
using ASC.Common.Web;
using Microsoft.AspNetCore.Http;
namespace ASC.Common.Data
{
public class DbManager : IDbManager
{
private readonly ILog logger = LogManager.GetLogger("ASC.SQL");
private readonly ProxyContext proxyContext;
private readonly bool shared;
private DbCommand command;
private ISqlDialect dialect;
private volatile bool disposed;
private readonly int? commandTimeout;
private DbCommand Command
{
get
{
CheckDispose();
if (command == null)
{
command = OpenConnection().CreateCommand();
}
if (command.Connection.State == ConnectionState.Closed || command.Connection.State == ConnectionState.Broken)
{
command = OpenConnection().CreateCommand();
}
if (commandTimeout.HasValue)
{
command.CommandTimeout = commandTimeout.Value;
}
return command;
}
}
public string DatabaseId { get; private set; }
public bool InTransaction
{
get { return Command.Transaction != null; }
}
public DbConnection Connection
{
get { return Command.Connection; }
}
public DbManager(string databaseId, int? commandTimeout = null)
: this(databaseId, true, commandTimeout)
{
}
public DbManager(string databaseId, bool shared, int? commandTimeout = null)
{
if (databaseId == null) throw new ArgumentNullException("databaseId");
DatabaseId = databaseId;
this.shared = shared;
if (logger.IsDebugEnabled)
{
proxyContext = new ProxyContext(AdoProxyExecutedEventHandler);
}
if (commandTimeout.HasValue)
{
this.commandTimeout = commandTimeout;
}
}
#region IDisposable Members
public void Dispose()
{
lock (this)
{
if (disposed) return;
disposed = true;
if (command != null)
{
if (command.Connection != null) command.Connection.Dispose();
command.Dispose();
command = null;
}
}
}
#endregion
public static IDbManager FromHttpContext(string databaseId)
{
if (HttpContext.Current != null)
{
var dbManager = DisposableHttpContext.Current[databaseId] as DbManager;
if (dbManager == null || dbManager.disposed)
{
var localDbManager = new DbManager(databaseId);
var dbManagerAdapter = new DbManagerProxy(localDbManager);
DisposableHttpContext.Current[databaseId] = localDbManager;
return dbManagerAdapter;
}
return new DbManagerProxy(dbManager);
}
return new DbManager(databaseId);
}
private DbConnection OpenConnection()
{
var connection = GetConnection();
connection.Open();
return connection;
}
private DbConnection GetConnection()
{
CheckDispose();
DbConnection connection = null;
string key = null;
if (shared && HttpContext.Current != null)
{
key = string.Format("Connection {0}|{1}", GetDialect(), DbRegistry.GetConnectionString(DatabaseId));
connection = DisposableHttpContext.Current[key] as DbConnection;
if (connection != null)
{
var state = ConnectionState.Closed;
var disposed = false;
try
{
state = connection.State;
}
catch (ObjectDisposedException)
{
disposed = true;
}
if (!disposed && (state == ConnectionState.Closed || state == ConnectionState.Broken))
{
if (string.IsNullOrEmpty(connection.ConnectionString))
{
connection.ConnectionString = DbRegistry.GetConnectionString(DatabaseId).ConnectionString;
}
return connection;
}
}
}
connection = DbRegistry.CreateDbConnection(DatabaseId);
if (proxyContext != null)
{
connection = new DbConnectionProxy(connection, proxyContext);
}
if (shared && HttpContext.Current != null) DisposableHttpContext.Current[key] = connection;
return connection;
}
public IDbTransaction BeginTransaction()
{
if (InTransaction) throw new InvalidOperationException("Transaction already open.");
Command.Transaction = Command.Connection.BeginTransaction();
var tx = new DbTransaction(Command.Transaction);
tx.Unavailable += TransactionUnavailable;
return tx;
}
public IDbTransaction BeginTransaction(IsolationLevel il)
{
if (InTransaction) throw new InvalidOperationException("Transaction already open.");
il = GetDialect().GetSupportedIsolationLevel(il);
Command.Transaction = Command.Connection.BeginTransaction(il);
var tx = new DbTransaction(Command.Transaction);
tx.Unavailable += TransactionUnavailable;
return tx;
}
public IDbTransaction BeginTransaction(bool nestedIfAlreadyOpen)
{
return nestedIfAlreadyOpen && InTransaction ? new DbNestedTransaction(Command.Transaction) : BeginTransaction();
}
public List<object[]> ExecuteList(string sql, params object[] parameters)
{
return Command.ExecuteList(sql, parameters);
}
public Task<List<object[]>> ExecuteListAsync(string sql, params object[] parameters)
{
return Command.ExecuteListAsync(sql, parameters);
}
public List<object[]> ExecuteList(ISqlInstruction sql)
{
return Command.ExecuteList(sql, GetDialect());
}
public Task<List<object[]>> ExecuteListAsync(ISqlInstruction sql)
{
return Command.ExecuteListAsync(sql, GetDialect());
}
public List<T> ExecuteList<T>(ISqlInstruction sql, Converter<IDataRecord, T> converter)
{
return Command.ExecuteList(sql, GetDialect(), converter);
}
public T ExecuteScalar<T>(string sql, params object[] parameters)
{
return Command.ExecuteScalar<T>(sql, parameters);
}
public T ExecuteScalar<T>(ISqlInstruction sql)
{
return Command.ExecuteScalar<T>(sql, GetDialect());
}
public int ExecuteNonQuery(string sql, params object[] parameters)
{
return Command.ExecuteNonQuery(sql, parameters);
}
public Task<int> ExecuteNonQueryAsync(string sql, params object[] parameters)
{
return Command.ExecuteNonQueryAsync(sql, parameters);
}
public int ExecuteNonQuery(ISqlInstruction sql)
{
return Command.ExecuteNonQuery(sql, GetDialect());
}
public int ExecuteBatch(IEnumerable<ISqlInstruction> batch)
{
if (batch == null) throw new ArgumentNullException("batch");
var affected = 0;
using (var tx = BeginTransaction())
{
foreach (var sql in batch)
{
affected += ExecuteNonQuery(sql);
}
tx.Commit();
}
return affected;
}
private void TransactionUnavailable(object sender, EventArgs e)
{
if (Command.Transaction != null)
{
Command.Transaction = null;
}
}
private void CheckDispose()
{
if (disposed) throw new ObjectDisposedException(GetType().FullName);
}
private ISqlDialect GetDialect()
{
return dialect ?? (dialect = DbRegistry.GetSqlDialect(DatabaseId));
}
private void AdoProxyExecutedEventHandler(ExecutedEventArgs a)
{
logger.DebugWithProps(a.SqlMethod,
new KeyValuePair<string, object>("duration", a.Duration.TotalMilliseconds),
new KeyValuePair<string, object>("sql", RemoveWhiteSpaces(a.Sql)),
new KeyValuePair<string, object>("sqlParams", RemoveWhiteSpaces(a.SqlParameters))
);
}
private string RemoveWhiteSpaces(string str)
{
return !string.IsNullOrEmpty(str) ?
str.Replace(Environment.NewLine, " ").Replace("\n", "").Replace("\r", "").Replace("\t", " ") :
string.Empty;
}
}
public class DbManagerProxy : IDbManager
{
private DbManager dbManager { get; set; }
public DbManagerProxy(DbManager dbManager)
{
this.dbManager = dbManager;
}
public void Dispose()
{
if (HttpContext.Current == null)
{
dbManager.Dispose();
}
}
public DbConnection Connection { get { return dbManager.Connection; } }
public string DatabaseId { get { return dbManager.DatabaseId; } }
public bool InTransaction { get { return dbManager.InTransaction; } }
public IDbTransaction BeginTransaction()
{
return dbManager.BeginTransaction();
}
public IDbTransaction BeginTransaction(IsolationLevel isolationLevel)
{
return dbManager.BeginTransaction(isolationLevel);
}
public IDbTransaction BeginTransaction(bool nestedIfAlreadyOpen)
{
return dbManager.BeginTransaction(nestedIfAlreadyOpen);
}
public List<object[]> ExecuteList(string sql, params object[] parameters)
{
return dbManager.ExecuteList(sql, parameters);
}
public List<object[]> ExecuteList(ISqlInstruction sql)
{
return dbManager.ExecuteList(sql);
}
public Task<List<object[]>> ExecuteListAsync(ISqlInstruction sql)
{
return dbManager.ExecuteListAsync(sql);
}
public List<T> ExecuteList<T>(ISqlInstruction sql, Converter<IDataRecord, T> converter)
{
return dbManager.ExecuteList<T>(sql, converter);
}
public T ExecuteScalar<T>(string sql, params object[] parameters)
{
return dbManager.ExecuteScalar<T>(sql, parameters);
}
public T ExecuteScalar<T>(ISqlInstruction sql)
{
return dbManager.ExecuteScalar<T>(sql);
}
public int ExecuteNonQuery(string sql, params object[] parameters)
{
return dbManager.ExecuteNonQuery(sql, parameters);
}
public int ExecuteNonQuery(ISqlInstruction sql)
{
return dbManager.ExecuteNonQuery(sql);
}
public int ExecuteBatch(IEnumerable<ISqlInstruction> batch)
{
return dbManager.ExecuteBatch(batch);
}
}
}

View File

@ -42,142 +42,139 @@ namespace ASC.Common.Data
public string Description { get; set; }
public string Type { get; set; }
}
public class DbRegistry
{
private const string DEFAULT = "DEFAULT";
private static readonly object syncRoot = new object();
private static readonly IDictionary<string, DbProviderFactory> providers = new Dictionary<string, DbProviderFactory>(StringComparer.InvariantCultureIgnoreCase);
private static readonly IDictionary<string, string> connnectionStrings = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
private static readonly IDictionary<string, ISqlDialect> dialects = new Dictionary<string, ISqlDialect>(StringComparer.InvariantCultureIgnoreCase);
private static volatile bool configured = false;
protected IConfiguration Configuration { get; set; }
public DbRegistry(IConfiguration configuration)
public static class DbRegistry
{
private const string DEFAULT = "DEFAULT";
private static readonly object syncRoot = new object();
private static readonly IDictionary<string, DbProviderFactory> providers = new Dictionary<string, DbProviderFactory>(StringComparer.InvariantCultureIgnoreCase);
private static readonly IDictionary<string, string> connnectionStrings = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
private static readonly IDictionary<string, ISqlDialect> dialects = new Dictionary<string, ISqlDialect>(StringComparer.InvariantCultureIgnoreCase);
private static volatile bool configured = false;
static DbRegistry()
{
Configuration = configuration;
dialects["MySql.Data.MySqlClient.MySqlClientFactory"] = new MySQLDialect();
dialects["System.Data.SQLite.SQLiteFactory"] = new SQLiteDialect();
}
internal void RegisterDatabase(string databaseId, DbProviderFactory providerFactory, string connectionString)
{
if (string.IsNullOrEmpty(databaseId)) throw new ArgumentNullException("databaseId");
if (providerFactory == null) throw new ArgumentNullException("providerFactory");
if (!providers.ContainsKey(databaseId))
{
lock (syncRoot)
{
if (!providers.ContainsKey(databaseId))
{
providers.Add(databaseId, providerFactory);
if (!string.IsNullOrEmpty(connectionString))
{
connnectionStrings.Add(databaseId, connectionString);
}
}
}
}
}
internal void RegisterDatabase(string databaseId, string providerInvariantName, string connectionString)
{
RegisterDatabase(databaseId, DbProviderFactories.GetFactory(providerInvariantName), connectionString);
}
public void RegisterDatabase(string databaseId, ConnectionStringSettings connectionString)
{
RegisterDatabase(databaseId, connectionString.ProviderName, connectionString.ConnectionString);
}
public void UnRegisterDatabase(string databaseId)
{
if (string.IsNullOrEmpty(databaseId)) throw new ArgumentNullException("databaseId");
if (providers.ContainsKey(databaseId))
{
lock (syncRoot)
{
if (providers.ContainsKey(databaseId))
{
providers.Remove(databaseId);
}
}
}
if (connnectionStrings.ContainsKey(databaseId))
{
lock (syncRoot)
{
if (connnectionStrings.ContainsKey(databaseId))
{
connnectionStrings.Remove(databaseId);
}
}
}
}
public bool IsDatabaseRegistered(string databaseId)
{
lock (syncRoot)
{
return providers.ContainsKey(databaseId);
}
}
public DbConnection CreateDbConnection(string databaseId)
{
Configure();
if (!providers.ContainsKey(databaseId))
{
databaseId = DEFAULT;
}
var connection = providers[databaseId].CreateConnection();
if (connnectionStrings.ContainsKey(databaseId))
{
connection.ConnectionString = connnectionStrings[databaseId];
}
return connection;
}
public DbProviderFactory GetDbProviderFactory(string databaseId)
{
Configure();
if (!providers.ContainsKey(databaseId))
{
databaseId = DEFAULT;
}
return providers.ContainsKey(databaseId) ? providers[databaseId] : null;
}
public ConnectionStringSettings GetConnectionString(string databaseId)
{
Configure();
if (!connnectionStrings.ContainsKey(databaseId))
{
databaseId = DEFAULT;
}
return connnectionStrings.ContainsKey(databaseId) ? new ConnectionStringSettings(databaseId, connnectionStrings[databaseId], providers[databaseId].GetType().Name) : null;
}
public ISqlDialect GetSqlDialect(string databaseId)
{
var provider = GetDbProviderFactory(databaseId);
if (provider != null && dialects.ContainsKey(provider.GetType().FullName))
{
return dialects[provider.GetType().FullName];
}
return SqlDialect.Default;
}
public void Configure()
dialects["MySql.Data.MySqlClient.MySqlClientFactory"] = new MySQLDialect();
dialects["System.Data.SQLite.SQLiteFactory"] = new SQLiteDialect();
}
internal static void RegisterDatabase(string databaseId, DbProviderFactory providerFactory, string connectionString)
{
if (string.IsNullOrEmpty(databaseId)) throw new ArgumentNullException("databaseId");
if (providerFactory == null) throw new ArgumentNullException("providerFactory");
if (!providers.ContainsKey(databaseId))
{
lock (syncRoot)
{
if (!providers.ContainsKey(databaseId))
{
providers.Add(databaseId, providerFactory);
if (!string.IsNullOrEmpty(connectionString))
{
connnectionStrings.Add(databaseId, connectionString);
}
}
}
}
}
internal static void RegisterDatabase(string databaseId, string providerInvariantName, string connectionString)
{
RegisterDatabase(databaseId, DbProviderFactories.GetFactory(providerInvariantName), connectionString);
}
public static void RegisterDatabase(string databaseId, ConnectionStringSettings connectionString)
{
RegisterDatabase(databaseId, connectionString.ProviderName, connectionString.ConnectionString);
}
public static void UnRegisterDatabase(string databaseId)
{
if (string.IsNullOrEmpty(databaseId)) throw new ArgumentNullException("databaseId");
if (providers.ContainsKey(databaseId))
{
lock (syncRoot)
{
if (providers.ContainsKey(databaseId))
{
providers.Remove(databaseId);
}
}
}
if (connnectionStrings.ContainsKey(databaseId))
{
lock (syncRoot)
{
if (connnectionStrings.ContainsKey(databaseId))
{
connnectionStrings.Remove(databaseId);
}
}
}
}
public static bool IsDatabaseRegistered(string databaseId)
{
lock (syncRoot)
{
return providers.ContainsKey(databaseId);
}
}
public static DbConnection CreateDbConnection(string databaseId)
{
Configure();
if (!providers.ContainsKey(databaseId))
{
databaseId = DEFAULT;
}
var connection = providers[databaseId].CreateConnection();
if (connnectionStrings.ContainsKey(databaseId))
{
connection.ConnectionString = connnectionStrings[databaseId];
}
return connection;
}
public static DbProviderFactory GetDbProviderFactory(string databaseId)
{
Configure();
if (!providers.ContainsKey(databaseId))
{
databaseId = DEFAULT;
}
return providers.ContainsKey(databaseId) ? providers[databaseId] : null;
}
public static ConnectionStringSettings GetConnectionString(string databaseId)
{
Configure();
if (!connnectionStrings.ContainsKey(databaseId))
{
databaseId = DEFAULT;
}
return connnectionStrings.ContainsKey(databaseId) ? new ConnectionStringSettings(databaseId, connnectionStrings[databaseId], providers[databaseId].GetType().Name) : null;
}
public static ISqlDialect GetSqlDialect(string databaseId)
{
var provider = GetDbProviderFactory(databaseId);
if (provider != null && dialects.ContainsKey(provider.GetType().FullName))
{
return dialects[provider.GetType().FullName];
}
return SqlDialect.Default;
}
public static void Configure()
{
if (!configured)
{
@ -185,6 +182,7 @@ namespace ASC.Common.Data
{
if (!configured)
{
var Configuration = DependencyInjection.CommonServiceProvider.GetService<IConfiguration>();
var dbProviderFactories = Configuration.GetSection("DbProviderFactories");
foreach (var ch in dbProviderFactories.GetChildren())

View File

@ -0,0 +1,12 @@
using System;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Common.DependencyInjection
{
public static class CommonServiceProvider
{
public static IServiceProvider Current { get; set; }
public static T GetService<T>() => Current.GetService<T>();
}
}

View File

@ -1,92 +1,88 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
#region usings
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
#endregion
namespace ASC.Security.Cryptography
{
public class InstanceCrypto
{
protected MachinePseudoKeys MachinePseudoKeys { get; set; }
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
public InstanceCrypto(MachinePseudoKeys machinePseudoKeys) => MachinePseudoKeys = machinePseudoKeys;
public string Encrypt(string data)
{
return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(data)));
}
public byte[] Encrypt(byte[] data)
{
var hasher = Rijndael.Create();
hasher.Key = EKey();
hasher.IV = new byte[hasher.BlockSize >> 3];
using (var ms = new MemoryStream())
using (var ss = new CryptoStream(ms, hasher.CreateEncryptor(), CryptoStreamMode.Write))
{
ss.Write(data, 0, data.Length);
ss.FlushFinalBlock();
hasher.Clear();
return ms.ToArray();
}
}
public string Decrypt(string data)
{
return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(data)));
}
public byte[] Decrypt(byte[] data)
{
var hasher = Rijndael.Create();
hasher.Key = EKey();
hasher.IV = new byte[hasher.BlockSize >> 3];
using (var ms = new MemoryStream(data))
using (var ss = new CryptoStream(ms, hasher.CreateDecryptor(), CryptoStreamMode.Read))
{
var buffer = new byte[data.Length];
int size = ss.Read(buffer, 0, buffer.Length);
hasher.Clear();
var newBuffer = new byte[size];
Array.Copy(buffer, newBuffer, size);
return newBuffer;
}
}
private byte[] EKey()
{
return MachinePseudoKeys.GetMachineConstant(32);
}
}
#region usings
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
#endregion
namespace ASC.Security.Cryptography
{
public static class InstanceCrypto
{
public static string Encrypt(string data)
{
return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(data)));
}
public static byte[] Encrypt(byte[] data)
{
Rijndael hasher = Rijndael.Create();
hasher.Key = EKey();
hasher.IV = new byte[hasher.BlockSize >> 3];
using (var ms = new MemoryStream())
using (var ss = new CryptoStream(ms, hasher.CreateEncryptor(), CryptoStreamMode.Write))
{
ss.Write(data, 0, data.Length);
ss.FlushFinalBlock();
hasher.Clear();
return ms.ToArray();
}
}
public static string Decrypt(string data)
{
return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(data)));
}
public static byte[] Decrypt(byte[] data)
{
Rijndael hasher = Rijndael.Create();
hasher.Key = EKey();
hasher.IV = new byte[hasher.BlockSize >> 3];
using (var ms = new MemoryStream(data))
using (var ss = new CryptoStream(ms, hasher.CreateDecryptor(), CryptoStreamMode.Read))
{
var buffer = new byte[data.Length];
int size = ss.Read(buffer, 0, buffer.Length);
hasher.Clear();
var newBuffer = new byte[size];
Array.Copy(buffer, newBuffer, size);
return newBuffer;
}
}
private static byte[] EKey()
{
return MachinePseudoKeys.GetMachineConstant(32);
}
}
}

View File

@ -1,46 +1,46 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using ASC.Common.Security;
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using ASC.Common.Security;
using Microsoft.Extensions.Configuration;
namespace ASC.Security.Cryptography
{
public class MachinePseudoKeys
{
private byte[] confkey = null;
public MachinePseudoKeys(IConfiguration configuration)
{
namespace ASC.Security.Cryptography
{
public static class MachinePseudoKeys
{
private static readonly byte[] confkey = null;
static MachinePseudoKeys()
{
var configuration = Common.DependencyInjection.CommonServiceProvider.GetService<IConfiguration>();
var key = configuration["core:machinekey"];
if (string.IsNullOrEmpty(key))
{
@ -49,30 +49,30 @@ namespace ASC.Security.Cryptography
if (!string.IsNullOrEmpty(key))
{
confkey = Encoding.UTF8.GetBytes(key);
}
}
public byte[] GetMachineConstant()
{
if (confkey != null)
{
return confkey;
}
var path = typeof(MachinePseudoKeys).Assembly.Location;
var fi = new FileInfo(path);
return BitConverter.GetBytes(fi.CreationTime.ToOADate());
}
public byte[] GetMachineConstant(int bytesCount)
{
var cnst = Enumerable.Repeat<byte>(0, sizeof (int)).Concat(GetMachineConstant()).ToArray();
var icnst = BitConverter.ToInt32(cnst, cnst.Length - sizeof (int));
var rnd = new AscRandom(icnst);
var buff = new byte[bytesCount];
rnd.NextBytes(buff);
return buff;
}
}
}
}
public static byte[] GetMachineConstant()
{
if (confkey != null)
{
return confkey;
}
var path = typeof(MachinePseudoKeys).Assembly.Location;
var fi = new FileInfo(path);
return BitConverter.GetBytes(fi.CreationTime.ToOADate());
}
public static byte[] GetMachineConstant(int bytesCount)
{
var cnst = Enumerable.Repeat<byte>(0, sizeof(int)).Concat(GetMachineConstant()).ToArray();
var icnst = BitConverter.ToInt32(cnst, cnst.Length - sizeof(int));
var rnd = new AscRandom(icnst);
var buff = new byte[bytesCount];
rnd.NextBytes(buff);
return buff;
}
}
}

View File

@ -1,94 +1,92 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Security.Cryptography;
using System.Text;
using System.Web.Script.Serialization;
using ASC.Security.Cryptography;
using Microsoft.AspNetCore.WebUtilities;
namespace ASC.Common.Utils
{
public class Signature
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Security.Cryptography;
using System.Text;
using System.Web.Script.Serialization;
using ASC.Security.Cryptography;
using Microsoft.AspNetCore.WebUtilities;
namespace ASC.Common.Utils
{
public static class Signature
{
protected MachinePseudoKeys MachinePseudoKeys { get; set; }
public Signature(MachinePseudoKeys machinePseudoKeys) => MachinePseudoKeys = machinePseudoKeys;
public string Create<T>(T obj)
{
return Create(obj, Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()));
}
public string Create<T>(T obj, string secret)
{
var serializer = new JavaScriptSerializer();
var str = serializer.Serialize(obj);
var payload = GetHashBase64(str + secret) + "?" + str;
return WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(payload));
}
public T Read<T>(string signature)
{
return Read<T>(signature, Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()));
}
public T Read<T>(string signature, string secret)
{
return Read<T>(signature, secret, true);
}
public T Read<T>(string signature, string secret, bool useSecret)
{
try
{
var payloadParts = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(signature)).Split('?');
if (!useSecret || GetHashBase64(payloadParts[1] + secret) == payloadParts[0]
|| GetHashBase64MD5(payloadParts[1] + secret) == payloadParts[0] //todo: delete
)
{
//Sig correct
return new JavaScriptSerializer().Deserialize<T>(payloadParts[1]);
}
}
catch (Exception)
{
}
return default;
}
private string GetHashBase64(string str)
{
return Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(str)));
}
private string GetHashBase64MD5(string str)
{
return Convert.ToBase64String(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(str)));
}
}
public static string Create<T>(T obj)
{
return Create(obj, Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()));
}
public static string Create<T>(T obj, string secret)
{
var serializer = new JavaScriptSerializer();
var str = serializer.Serialize(obj);
var payload = GetHashBase64(str + secret) + "?" + str;
return WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(payload));
}
public static T Read<T>(string signature)
{
return Read<T>(signature, Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()));
}
public static T Read<T>(string signature, string secret)
{
return Read<T>(signature, secret, true);
}
public static T Read<T>(string signature, string secret, bool useSecret)
{
try
{
var payloadParts = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(signature)).Split('?');
if (!useSecret || GetHashBase64(payloadParts[1] + secret) == payloadParts[0]
|| GetHashBase64MD5(payloadParts[1] + secret) == payloadParts[0] //todo: delete
)
{
//Sig correct
return new JavaScriptSerializer().Deserialize<T>(payloadParts[1]);
}
}
catch (Exception)
{
}
return default(T);
}
private static string GetHashBase64(string str)
{
return Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(str)));
}
private static string GetHashBase64MD5(string str)
{
return Convert.ToBase64String(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(str)));
}
}
}

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Http;
using ASC.Common.DependencyInjection;
using Microsoft.AspNetCore.Http;
namespace ASC.Common
{
@ -8,7 +9,8 @@ namespace ASC.Common
public static void Configure(IHttpContextAccessor httpContextAccessor)
{
m_httpContextAccessor = httpContextAccessor;
m_httpContextAccessor = httpContextAccessor;
CommonServiceProvider.Current = httpContextAccessor.HttpContext.RequestServices;
}
public static Microsoft.AspNetCore.Http.HttpContext Current

View File

@ -31,16 +31,16 @@ using System.Globalization;
namespace ASC.Core.Configuration
{
//class ConnectionStringNameTypeConverter : TypeConverter
//{
// public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
// {
// return sourceType == typeof(string);
// }
class ConnectionStringNameTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
// public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
// {
// return DbRegistry.GetConnectionString((string)value);
// }
//}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return DbRegistry.GetConnectionString((string)value);
}
}
}

View File

@ -1,99 +1,96 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System.Configuration;
using ASC.Common.Data;
using ASC.Core.Billing;
using ASC.Core.Caching;
using ASC.Core.Data;
namespace ASC.Core
{
public class CoreContext
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System.Configuration;
using ASC.Common.Data;
using ASC.Core.Billing;
using ASC.Core.Caching;
using ASC.Core.Data;
namespace ASC.Core
{
public static class CoreContext
{
public DbRegistry DbRegistry { get; set; }
public CoreContext(DbRegistry dbRegistry)
static CoreContext()
{
DbRegistry = dbRegistry;
ConfigureCoreContextByDefault();
}
public static CoreConfiguration Configuration { get; private set; }
public TenantManager TenantManager1 => TenantManager;
public static TenantManager TenantManager { get; private set; }
public static UserManager UserManager { get; private set; }
public static AuthManager Authentication { get; private set; }
public static AuthorizationManager AuthorizationManager { get; private set; }
public static PaymentManager PaymentManager { get; private set; }
internal static SubscriptionManager SubscriptionManager { get; private set; }
private static bool QuotaCacheEnabled
{
get
{
if (ConfigurationManager.AppSettings["core.enable-quota-cache"] == null)
return true;
bool enabled;
return !bool.TryParse(ConfigurationManager.AppSettings["core.enable-quota-cache"], out enabled) || enabled;
}
}
private void ConfigureCoreContextByDefault()
{
var cs = DbRegistry.GetConnectionString("core");
if (cs == null)
{
throw new ConfigurationErrorsException("Can not configure CoreContext: connection string with name core not found.");
}
var tenantService = new CachedTenantService(new DbTenantService(cs));
var userService = new CachedUserService(new DbUserService(cs));
var azService = new CachedAzService(new DbAzService(cs));
var quotaService = QuotaCacheEnabled ? (IQuotaService) new CachedQuotaService(new DbQuotaService(cs)) : new DbQuotaService(cs);
var subService = new CachedSubscriptionService(new DbSubscriptionService(cs));
var tariffService = new TariffService(cs, quotaService, tenantService);
Configuration = new CoreConfiguration(tenantService);
TenantManager = new TenantManager(tenantService, quotaService, tariffService);
PaymentManager = new PaymentManager(Configuration, quotaService, tariffService);
UserManager = new UserManager(userService);
Authentication = new AuthManager(userService);
AuthorizationManager = new AuthorizationManager(azService);
SubscriptionManager = new SubscriptionManager(subService);
}
}
ConfigureCoreContextByDefault();
}
public static CoreConfiguration Configuration { get; private set; }
public static TenantManager TenantManager { get; private set; }
public static UserManager UserManager { get; private set; }
public static AuthManager Authentication { get; private set; }
public static AuthorizationManager AuthorizationManager { get; private set; }
public static PaymentManager PaymentManager { get; private set; }
internal static SubscriptionManager SubscriptionManager { get; private set; }
private static bool QuotaCacheEnabled
{
get
{
if (ConfigurationManager.AppSettings["core.enable-quota-cache"] == null)
return true;
bool enabled;
return !bool.TryParse(ConfigurationManager.AppSettings["core.enable-quota-cache"], out enabled) || enabled;
}
}
private static void ConfigureCoreContextByDefault()
{
var cs = DbRegistry.GetConnectionString("core");
if (cs == null)
{
throw new ConfigurationErrorsException("Can not configure CoreContext: connection string with name core not found.");
}
var tenantService = new CachedTenantService(new DbTenantService(cs));
var userService = new CachedUserService(new DbUserService(cs));
var azService = new CachedAzService(new DbAzService(cs));
var quotaService = QuotaCacheEnabled ? (IQuotaService)new CachedQuotaService(new DbQuotaService(cs)) : new DbQuotaService(cs);
var subService = new CachedSubscriptionService(new DbSubscriptionService(cs));
var tariffService = new TariffService(cs, quotaService, tenantService);
Configuration = new CoreConfiguration(tenantService);
TenantManager = new TenantManager(tenantService, quotaService, tariffService);
PaymentManager = new PaymentManager(Configuration, quotaService, tariffService);
UserManager = new UserManager(userService);
Authentication = new AuthManager(userService);
AuthorizationManager = new AuthorizationManager(azService);
SubscriptionManager = new SubscriptionManager(subService);
}
}
}

View File

@ -1,288 +1,283 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Security;
using System.Security.Authentication;
using System.Security.Principal;
using System.Threading;
using System.Web;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Security;
using ASC.Common.Security.Authentication;
using ASC.Common.Security.Authorizing;
using ASC.Core.Billing;
using ASC.Core.Security.Authentication;
using ASC.Core.Security.Authorizing;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using Microsoft.Extensions.Configuration;
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
namespace ASC.Core
{
public class SecurityContext
{
private static readonly ILog log = LogManager.GetLogger("ASC.Core");
public static IAccount CurrentAccount
{
get { return Principal.Identity is IAccount ? (IAccount)Principal.Identity : Configuration.Constants.Guest; }
}
public static bool IsAuthenticated
{
get { return CurrentAccount.IsAuthenticated; }
}
public static IPermissionResolver PermissionResolver { get; private set; }
protected IConfiguration configuration { get; set; }
protected CookieStorage cookieStorage { get; set; }
protected CoreContext CoreContext { get; set; }
public SecurityContext(IConfiguration configuration, CookieStorage cookieStorage, CoreContext coreContext)
using System;
using System.Collections.Generic;
using System.Security;
using System.Security.Authentication;
using System.Security.Principal;
using System.Threading;
using System.Web;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Security;
using ASC.Common.Security.Authentication;
using ASC.Common.Security.Authorizing;
using ASC.Common.Web;
using ASC.Core.Billing;
using ASC.Core.Security.Authentication;
using ASC.Core.Security.Authorizing;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using Microsoft.AspNetCore.Http.Features;
namespace ASC.Core
{
public static class SecurityContext
{
private static readonly ILog log = LogManager.GetLogger("ASC.Core");
public static IAccount CurrentAccount
{
this.configuration = configuration;
this.cookieStorage = cookieStorage;
CoreContext = coreContext;
var azManager = new AzManager(new RoleProvider(), new PermissionProvider());
PermissionResolver = new PermissionResolver(azManager);
get { return Principal.Identity is IAccount ? (IAccount)Principal.Identity : Configuration.Constants.Guest; }
}
public string AuthenticateMe(string login, string password)
{
if (login == null) throw new ArgumentNullException("login");
if (password == null) throw new ArgumentNullException("password");
var tenantid = CoreContext.TenantManager.GetCurrentTenant().TenantId;
var u = CoreContext.UserManager.GetUsers(tenantid, login, Hasher.Base64Hash(password, HashAlg.SHA256));
return AuthenticateMe(new UserAccount(u, tenantid));
}
public bool AuthenticateMe(string cookie)
{
if (!string.IsNullOrEmpty(cookie))
{
int tenant;
Guid userid;
string login;
string password;
int indexTenant;
DateTime expire;
int indexUser;
if (cookie.Equals("Bearer", StringComparison.InvariantCulture))
{
var ipFrom = string.Empty;
var address = string.Empty;
if (HttpContext.Current != null)
{
var request = HttpContext.Current.Request;
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
address = "for " + request.GetUrlRewriter();
}
log.InfoFormat("Empty Bearer cookie: {0} {1}", ipFrom, address);
}
else if (cookieStorage.DecryptCookie(cookie, out tenant, out userid, out login, out password, out indexTenant, out expire, out indexUser))
{
if (tenant != CoreContext.TenantManager1.GetCurrentTenant().TenantId)
{
return false;
}
var settingsTenant = TenantCookieSettings.GetForTenant(tenant);
if (indexTenant != settingsTenant.Index)
{
return false;
}
if (expire != DateTime.MaxValue && expire < DateTime.UtcNow)
{
return false;
}
try
{
if (userid != Guid.Empty)
{
var settingsUser = TenantCookieSettings.GetForUser(userid);
if (indexUser != settingsUser.Index)
{
return false;
}
AuthenticateMe(new UserAccount(new UserInfo { ID = userid }, tenant));
}
else
{
AuthenticateMe(login, password);
}
return true;
}
catch (InvalidCredentialException ice)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}, login {4}, pass {5}",
ice.Message, cookie, tenant, userid, login, password);
}
catch (SecurityException se)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}, login {4}, pass {5}",
se.Message, cookie, tenant, userid, login, password);
}
catch (Exception err)
{
log.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, login {3}, pass {4}: {5}",
cookie, tenant, userid, login, password, err);
}
}
else
{
var ipFrom = string.Empty;
var address = string.Empty;
if (HttpContext.Current != null)
{
var request = HttpContext.Current.Request;
address = "for " + request.GetUrlRewriter();
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
}
log.WarnFormat("Can not decrypt cookie: {0} {1} {2}", cookie, ipFrom, address);
}
}
return false;
}
public string AuthenticateMe(IAccount account)
{
if (account == null || account.Equals(Configuration.Constants.Guest)) throw new InvalidCredentialException("account");
var roles = new List<string> { Role.Everyone };
string cookie = null;
if (account is ISystemAccount && account.ID == Configuration.Constants.CoreSystem.ID)
{
roles.Add(Role.System);
}
if (account is IUserAccount)
{
var u = CoreContext.UserManager.GetUsers(account.ID);
if (u.ID == Users.Constants.LostUser.ID)
{
throw new InvalidCredentialException("Invalid username or password.");
}
if (u.Status != EmployeeStatus.Active)
{
throw new SecurityException("Account disabled.");
}
// for LDAP users only
if (u.Sid != null)
{
if (!CoreContext.TenantManager.GetTenantQuota(CoreContext.TenantManager.GetCurrentTenant().TenantId).Ldap)
{
throw new BillingException("Your tariff plan does not support this option.", "Ldap");
}
}
if (CoreContext.UserManager.IsUserInGroup(u.ID, Users.Constants.GroupAdmin.ID))
{
roles.Add(Role.Administrators);
}
roles.Add(Role.Users);
account = new UserAccount(u, CoreContext.TenantManager.GetCurrentTenant().TenantId);
cookie = cookieStorage.EncryptCookie(CoreContext.TenantManager.GetCurrentTenant().TenantId, account.ID);
}
Principal = new GenericPrincipal(account, roles.ToArray());
return cookie;
}
public string AuthenticateMe(Guid userId)
{
return AuthenticateMe(CoreContext.Authentication.GetAccountByID(userId));
}
public static void Logout()
{
Principal = null;
}
public static void SetUserPassword(Guid userID, string password)
{
CoreContext.Authentication.SetUserPassword(userID, password);
}
public static bool CheckPermissions(params IAction[] actions)
{
return PermissionResolver.Check(CurrentAccount, actions);
}
public static bool CheckPermissions(ISecurityObject securityObject, params IAction[] actions)
{
return CheckPermissions(securityObject, null, actions);
}
public static bool CheckPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
return PermissionResolver.Check(CurrentAccount, objectId, securityObjProvider, actions);
}
public static void DemandPermissions(params IAction[] actions)
{
PermissionResolver.Demand(CurrentAccount, actions);
}
public static void DemandPermissions(ISecurityObject securityObject, params IAction[] actions)
{
DemandPermissions(securityObject, null, actions);
}
public static void DemandPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
PermissionResolver.Demand(CurrentAccount, objectId, securityObjProvider, actions);
}
private static IPrincipal Principal
{
get { return Thread.CurrentPrincipal; }
set
{
Thread.CurrentPrincipal = value;
if (HttpContext.Current != null) HttpContext.Current.User = new System.Security.Claims.ClaimsPrincipal(value);
}
}
}
public static bool IsAuthenticated
{
get { return CurrentAccount.IsAuthenticated; }
}
public static IPermissionResolver PermissionResolver { get; private set; }
static SecurityContext()
{
var azManager = new AzManager(new RoleProvider(), new PermissionProvider());
PermissionResolver = new PermissionResolver(azManager);
}
public static string AuthenticateMe(string login, string password)
{
if (login == null) throw new ArgumentNullException("login");
if (password == null) throw new ArgumentNullException("password");
var tenantid = CoreContext.TenantManager.GetCurrentTenant().TenantId;
var u = CoreContext.UserManager.GetUsers(tenantid, login, Hasher.Base64Hash(password, HashAlg.SHA256));
return AuthenticateMe(new UserAccount(u, tenantid));
}
public static bool AuthenticateMe(string cookie)
{
if (!string.IsNullOrEmpty(cookie))
{
int tenant;
Guid userid;
string login;
string password;
int indexTenant;
DateTime expire;
int indexUser;
if (cookie.Equals("Bearer", StringComparison.InvariantCulture))
{
var ipFrom = string.Empty;
var address = string.Empty;
if (HttpContext.Current != null)
{
var request = HttpContext.Current.Request;
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
address = "for " + request.GetUrlRewriter();
}
log.InfoFormat("Empty Bearer cookie: {0} {1}", ipFrom, address);
}
else if (CookieStorage.DecryptCookie(cookie, out tenant, out userid, out login, out password, out indexTenant, out expire, out indexUser))
{
if (tenant != CoreContext.TenantManager.GetCurrentTenant().TenantId)
{
return false;
}
var settingsTenant = TenantCookieSettings.GetForTenant(tenant);
if (indexTenant != settingsTenant.Index)
{
return false;
}
if (expire != DateTime.MaxValue && expire < DateTime.UtcNow)
{
return false;
}
try
{
if (userid != Guid.Empty)
{
var settingsUser = TenantCookieSettings.GetForUser(userid);
if (indexUser != settingsUser.Index)
{
return false;
}
AuthenticateMe(new UserAccount(new UserInfo { ID = userid }, tenant));
}
else
{
AuthenticateMe(login, password);
}
return true;
}
catch (InvalidCredentialException ice)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}, login {4}, pass {5}",
ice.Message, cookie, tenant, userid, login, password);
}
catch (SecurityException se)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}, login {4}, pass {5}",
se.Message, cookie, tenant, userid, login, password);
}
catch (Exception err)
{
log.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, login {3}, pass {4}: {5}",
cookie, tenant, userid, login, password, err);
}
}
else
{
var ipFrom = string.Empty;
var address = string.Empty;
if (HttpContext.Current != null)
{
var request = HttpContext.Current.Request;
address = "for " + request.GetUrlRewriter();
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
}
log.WarnFormat("Can not decrypt cookie: {0} {1} {2}", cookie, ipFrom, address);
}
}
return false;
}
public static string AuthenticateMe(IAccount account)
{
if (account == null || account.Equals(Configuration.Constants.Guest)) throw new InvalidCredentialException("account");
var roles = new List<string> { Role.Everyone };
string cookie = null;
if (account is ISystemAccount && account.ID == Configuration.Constants.CoreSystem.ID)
{
roles.Add(Role.System);
}
if (account is IUserAccount)
{
var u = CoreContext.UserManager.GetUsers(account.ID);
if (u.ID == Users.Constants.LostUser.ID)
{
throw new InvalidCredentialException("Invalid username or password.");
}
if (u.Status != EmployeeStatus.Active)
{
throw new SecurityException("Account disabled.");
}
// for LDAP users only
if (u.Sid != null)
{
if (!CoreContext.TenantManager.GetTenantQuota(CoreContext.TenantManager.GetCurrentTenant().TenantId).Ldap)
{
throw new BillingException("Your tariff plan does not support this option.", "Ldap");
}
}
if (CoreContext.UserManager.IsUserInGroup(u.ID, Users.Constants.GroupAdmin.ID))
{
roles.Add(Role.Administrators);
}
roles.Add(Role.Users);
account = new UserAccount(u, CoreContext.TenantManager.GetCurrentTenant().TenantId);
cookie = CookieStorage.EncryptCookie(CoreContext.TenantManager.GetCurrentTenant().TenantId, account.ID);
}
Principal = new GenericPrincipal(account, roles.ToArray());
return cookie;
}
public static string AuthenticateMe(Guid userId)
{
return AuthenticateMe(CoreContext.Authentication.GetAccountByID(userId));
}
public static void Logout()
{
Principal = null;
}
public static void SetUserPassword(Guid userID, string password)
{
CoreContext.Authentication.SetUserPassword(userID, password);
}
public static bool CheckPermissions(params IAction[] actions)
{
return PermissionResolver.Check(CurrentAccount, actions);
}
public static bool CheckPermissions(ISecurityObject securityObject, params IAction[] actions)
{
return CheckPermissions(securityObject, null, actions);
}
public static bool CheckPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
return PermissionResolver.Check(CurrentAccount, objectId, securityObjProvider, actions);
}
public static void DemandPermissions(params IAction[] actions)
{
PermissionResolver.Demand(CurrentAccount, actions);
}
public static void DemandPermissions(ISecurityObject securityObject, params IAction[] actions)
{
DemandPermissions(securityObject, null, actions);
}
public static void DemandPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
PermissionResolver.Demand(CurrentAccount, objectId, securityObjProvider, actions);
}
private static IPrincipal Principal
{
get { return Thread.CurrentPrincipal; }
set
{
Thread.CurrentPrincipal = value;
if (HttpContext.Current != null) HttpContext.Current.User = new System.Security.Claims.ClaimsPrincipal(value);
}
}
}
}

View File

@ -58,8 +58,6 @@ namespace ASC.Core
get;
private set;
}
public CookieStorage CookieStorage { get; set; }
public HostedSolution(ConnectionStringSettings connectionString)
: this(connectionString, null)

View File

@ -43,8 +43,6 @@ namespace ASC.Core
private readonly Dictionary<string, HostedSolution> regions = new Dictionary<string, HostedSolution>();
private readonly String dbid;
private volatile bool initialized = false;
DbRegistry DbRegistry { get; set; }
public MultiRegionHostedSolution(string dbid)
{

View File

@ -1,123 +1,120 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Globalization;
using System.Web;
using ASC.Common.Logging;
using ASC.Security.Cryptography;
using ASC.Core.Tenants;
using ASC.Common;
using ASC.Common.Web;
namespace ASC.Core.Security.Authentication
{
public class CookieStorage
{
private const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss,fff";
protected InstanceCrypto InstanceCrypto { get; set; }
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
public CookieStorage(InstanceCrypto instanceCrypto) => InstanceCrypto = instanceCrypto;
public bool DecryptCookie(string cookie, out int tenant, out Guid userid, out string login, out string password, out int indexTenant, out DateTime expire, out int indexUser)
{
tenant = Tenant.DEFAULT_TENANT;
userid = Guid.Empty;
login = null;
password = null;
indexTenant = 0;
expire = DateTime.MaxValue;
indexUser = 0;
if (string.IsNullOrEmpty(cookie))
{
return false;
}
try
{
cookie = (HttpUtility.UrlDecode(cookie) ?? "").Replace(' ', '+');
var s = InstanceCrypto.Decrypt(cookie).Split('$');
if (0 < s.Length) login = s[0];
if (1 < s.Length) tenant = int.Parse(s[1]);
if (2 < s.Length) password = s[2];
if (4 < s.Length) userid = new Guid(s[4]);
if (5 < s.Length) indexTenant = int.Parse(s[5]);
if (6 < s.Length) expire = DateTime.ParseExact(s[6], DateTimeFormat, CultureInfo.InvariantCulture);
if (7 < s.Length) indexUser = int.Parse(s[7]);
return true;
}
catch(Exception err)
{
LogManager.GetLogger("ASC.Core").ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, login {3}, pass {4}, indexTenant {5}, expire {6}: {7}",
cookie, tenant, userid, login, password, indexTenant, expire.ToString(DateTimeFormat), err);
}
return false;
}
public string EncryptCookie(int tenant, Guid userid, string login = null, string password = null)
{
var settingsTenant = TenantCookieSettings.GetForTenant(tenant);
var expires = TenantCookieSettings.GetExpiresTime(tenant);
var settingsUser = TenantCookieSettings.GetForUser(tenant, userid);
return EncryptCookie(tenant, userid, login, password, settingsTenant.Index, expires, settingsUser.Index);
}
public string EncryptCookie(int tenant, Guid userid, string login, string password, int indexTenant, DateTime expires, int indexUser)
{
var s = string.Format("{0}${1}${2}${3}${4}${5}${6}${7}",
(login ?? string.Empty).ToLowerInvariant(),
tenant,
password,
GetUserDepenencySalt(),
userid.ToString("N"),
indexTenant,
expires.ToString(DateTimeFormat, CultureInfo.InvariantCulture),
indexUser);
return InstanceCrypto.Encrypt(s);
}
private string GetUserDepenencySalt()
{
var data = string.Empty;
try
{
if (HttpContext.Current != null && HttpContext.Current.Request != null)
{
var forwarded = HttpContext.Current.Request.Headers["X-Forwarded-For"].ToString();
data = string.IsNullOrEmpty(forwarded) ? HttpContext.Current.Request.GetUserHostAddress() : forwarded.Split(':')[0];
}
}
catch { }
return Hasher.Base64Hash(data ?? string.Empty, HashAlg.SHA256);
}
}
using System;
using System.Globalization;
using System.Web;
using ASC.Common.Logging;
using ASC.Security.Cryptography;
using ASC.Core.Tenants;
using ASC.Common;
using ASC.Common.Web;
namespace ASC.Core.Security.Authentication
{
class CookieStorage
{
private const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss,fff";
public static bool DecryptCookie(string cookie, out int tenant, out Guid userid, out string login, out string password, out int indexTenant, out DateTime expire, out int indexUser)
{
tenant = Tenant.DEFAULT_TENANT;
userid = Guid.Empty;
login = null;
password = null;
indexTenant = 0;
expire = DateTime.MaxValue;
indexUser = 0;
if (string.IsNullOrEmpty(cookie))
{
return false;
}
try
{
cookie = (HttpUtility.UrlDecode(cookie) ?? "").Replace(' ', '+');
var s = InstanceCrypto.Decrypt(cookie).Split('$');
if (0 < s.Length) login = s[0];
if (1 < s.Length) tenant = int.Parse(s[1]);
if (2 < s.Length) password = s[2];
if (4 < s.Length) userid = new Guid(s[4]);
if (5 < s.Length) indexTenant = int.Parse(s[5]);
if (6 < s.Length) expire = DateTime.ParseExact(s[6], DateTimeFormat, CultureInfo.InvariantCulture);
if (7 < s.Length) indexUser = int.Parse(s[7]);
return true;
}
catch (Exception err)
{
LogManager.GetLogger("ASC.Core").ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, login {3}, pass {4}, indexTenant {5}, expire {6}: {7}",
cookie, tenant, userid, login, password, indexTenant, expire.ToString(DateTimeFormat), err);
}
return false;
}
public static string EncryptCookie(int tenant, Guid userid, string login = null, string password = null)
{
var settingsTenant = TenantCookieSettings.GetForTenant(tenant);
var expires = TenantCookieSettings.GetExpiresTime(tenant);
var settingsUser = TenantCookieSettings.GetForUser(tenant, userid);
return EncryptCookie(tenant, userid, login, password, settingsTenant.Index, expires, settingsUser.Index);
}
public static string EncryptCookie(int tenant, Guid userid, string login, string password, int indexTenant, DateTime expires, int indexUser)
{
var s = string.Format("{0}${1}${2}${3}${4}${5}${6}${7}",
(login ?? string.Empty).ToLowerInvariant(),
tenant,
password,
GetUserDepenencySalt(),
userid.ToString("N"),
indexTenant,
expires.ToString(DateTimeFormat, CultureInfo.InvariantCulture),
indexUser);
return InstanceCrypto.Encrypt(s);
}
private static string GetUserDepenencySalt()
{
var data = string.Empty;
try
{
if (HttpContext.Current != null && HttpContext.Current.Request != null)
{
var forwarded = HttpContext.Current.Request.Headers["X-Forwarded-For"].ToString();
data = string.IsNullOrEmpty(forwarded) ? HttpContext.Current.Request.GetUserHostAddress() : forwarded.Split(':')[0];
}
}
catch { }
return Hasher.Base64Hash(data ?? string.Empty, HashAlg.SHA256);
}
}
}

View File

@ -35,7 +35,7 @@ namespace ASC.Core.Common.Tests
public class CookieStorageTest
{
[TestMethod]
public void Validate(CookieStorage CookieStorage)
public void Validate()
{
var t1 = 1;
var id1 = Guid.NewGuid();

View File

@ -35,7 +35,7 @@ namespace ASC.Core.Common.Tests
public class SignatureTest
{
[TestMethod]
public void TestSignature(Signature Signature)
public void TestSignature()
{
var validObject = new { expire = DateTime.UtcNow.AddMinutes(15), key = "345jhndfg", ip = "192.168.1.1" };
var encoded = Signature.Create(validObject, "ThE SeCret Key!");

View File

@ -12,32 +12,25 @@ namespace ASC.Web.Api.Handlers
{
public class CookieAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
protected SecurityContext SecurityContext { get; set; }
protected IHttpContextAccessor HttpContextAccessor { get; set; }
public CookieAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
public CookieAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, SecurityContext securityContext, IHttpContextAccessor httpContextAccessor)
public CookieAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IHttpContextAccessor httpContextAccessor)
: this(options, logger, encoder, clock)
{
SecurityContext = securityContext;
HttpContextAccessor = httpContextAccessor;
Common.HttpContext.Configure(httpContextAccessor);
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
ASC.Common.HttpContext.Configure(HttpContextAccessor);
SecurityContext.AuthenticateMe(Context.Request.Cookies["asc_auth_key"]);
var result = SecurityContext.AuthenticateMe(Context.Request.Cookies["asc_auth_key"]);
return Task.FromResult(
AuthenticateResult.Success(
new AuthenticationTicket(
new ClaimsPrincipal(Thread.CurrentPrincipal),
new AuthenticationProperties(),
Scheme.Name)));
result ?
AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(Thread.CurrentPrincipal), new AuthenticationProperties(), Scheme.Name)) :
AuthenticateResult.Fail("fail")
);
}
}
}

View File

@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ASC.Web.Api
{

View File

@ -25,14 +25,6 @@ namespace ASC.Web.Api
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<MachinePseudoKeys>();
services.AddSingleton<Signature>();
services.AddSingleton<InstanceCrypto>();
services.AddSingleton<CookieStorage>();
services.AddSingleton<SecurityContext>();
services.AddSingleton<DbRegistry>();
services.AddSingleton<CoreContext>();
services.AddControllers()
.AddNewtonsoftJson()
.AddXmlSerializerFormatters();