Partial revert from 60b30ce542
Getting configuration via IServiceProvider
This commit is contained in:
parent
60b30ce542
commit
acb9457253
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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())
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -58,8 +58,6 @@ namespace ASC.Core
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public CookieStorage CookieStorage { get; set; }
|
||||
|
||||
public HostedSolution(ConnectionStringSettings connectionString)
|
||||
: this(connectionString, null)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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!");
|
||||
|
@ -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")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user