EDMIService: Use config module, prepare mssql connections
This commit is contained in:
parent
52ff2713c7
commit
62be9dc666
25
Service.EDMIService/Config.vb
Normal file
25
Service.EDMIService/Config.vb
Normal file
@ -0,0 +1,25 @@
|
||||
Imports DigitalData.Modules.Config.ConfigAttributes
|
||||
|
||||
Public Class Config
|
||||
<ConnectionString>
|
||||
Public Property ConnectionString_IDB As String = String.Empty
|
||||
<ConnectionString>
|
||||
Public Property ConnectionString_ECM As String = String.Empty
|
||||
<ConnectionString>
|
||||
Public Property Firebird_Datasource As String = String.Empty
|
||||
<ConnectionString>
|
||||
Public Property Firebird_DatabaseUser As String = String.Empty
|
||||
<ConnectionString>
|
||||
Public Property Firebird_DatabaseName As String = String.Empty
|
||||
<ConnectionString>
|
||||
Public Property Firebird_DatabasePassword As String = String.Empty
|
||||
|
||||
Public Property WorkPath As String = String.Empty
|
||||
|
||||
Public Property DatastorePath As String = String.Empty
|
||||
|
||||
Public Property ContainerPath As String = String.Empty
|
||||
Public Property ContainerPassword As String = String.Empty
|
||||
|
||||
Public Property Debug As Boolean = False
|
||||
End Class
|
||||
@ -11,9 +11,10 @@ Public Class EDMIService
|
||||
Implements IEDMIService
|
||||
|
||||
Public Shared LogConfig As LogConfig
|
||||
Public Shared MSSQL As MSSQLServer
|
||||
Public Shared MSSQL_ECM As MSSQLServer
|
||||
Public Shared MSSQL_IDB As MSSQLServer
|
||||
Public Shared Firebird As Firebird
|
||||
Public Shared AppConfig As AppConfig
|
||||
Public Shared AppConfig As Config
|
||||
Public Shared Filesystem As Filesystem.File
|
||||
Public Shared EDMIArchive As EDMI.File.Archive
|
||||
Public Shared GlobalState As GlobalState
|
||||
@ -33,8 +34,6 @@ Public Class EDMIService
|
||||
_username = oUsername
|
||||
_logger = LogConfig.GetLogger()
|
||||
_logger.Debug("New Request by User [{0}]", _username)
|
||||
|
||||
|
||||
End Sub
|
||||
|
||||
Public Function StripDomainFromUsername(UserName As String)
|
||||
@ -65,45 +64,87 @@ Public Class EDMIService
|
||||
Return True
|
||||
End Function
|
||||
#End Region
|
||||
#Region "=== Database Request ==="
|
||||
Public Sub CreateRequest(Name As String, Optional Debug As Boolean = False)
|
||||
_request = New Request(Name, _username, Firebird, Debug)
|
||||
_debug = Debug
|
||||
|
||||
_logger.Info("Creating request {0}/{1}", _request.Name, _request.RequestId)
|
||||
End Sub
|
||||
|
||||
Public Function CreateDatabaseRequest(Name As String, Optional Debug As Boolean = False) As String Implements IEDMIService.CreateDatabaseRequest
|
||||
CreateRequest(Name, Debug)
|
||||
|
||||
Return _request.Name
|
||||
#Region "=== Database (MSSQL IDB) ==="
|
||||
Public Function ReturnDatatable_MSSQL_IDB(SQL As String) As TableResult Implements IEDMIService.ReturnDatatable_MSSQL_IDB
|
||||
Try
|
||||
_logger.Info($"ReturnDatatable_MSSQL_IDB, SQL: {SQL}")
|
||||
Dim oResult As DataTable = MSSQL_IDB.GetDatatable(SQL)
|
||||
Return New TableResult(oResult)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_request.LogError(ex.Message)
|
||||
Return New TableResult(ex.Message)
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Sub CloseDatabaseRequest() Implements IEDMIService.CloseDatabaseRequest
|
||||
If IsNothing(_request) Then
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
_logger.Info("Closing request {0}", _request.ToString)
|
||||
_request.Connection.Close()
|
||||
_request = Nothing
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
#Region "=== Database (Firebird) ==="
|
||||
Private Sub TestRequestCreated()
|
||||
If IsNothing(_request) Then
|
||||
Throw New Exceptions.NoRequestException()
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Public Function ReturnDatatable(SQL As String) As TableResult Implements IEDMIService.ReturnDatatable
|
||||
Public Function ReturnScalar_MSSQL_IDB(SQL As String) As ScalarResult Implements IEDMIService.ReturnScalar_MSSQL_IDB
|
||||
Try
|
||||
TestRequestCreated()
|
||||
_logger.Info($"ReturnScalar_MSSQL_IDB, SQL: {SQL}")
|
||||
Dim oResult As Object = MSSQL_IDB.GetScalarValue(SQL)
|
||||
Return New ScalarResult(oResult)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_request.LogError(ex.Message)
|
||||
Return New ScalarResult(ex.Message)
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function ExecuteNonQuery_MSSQL_IDB(SQL As String) As NonQueryResult Implements IEDMIService.ExecuteNonQuery_MSSQL_IDB
|
||||
Try
|
||||
_logger.Info($"ExecuteNonQuery_MSSQL_IDB, SQL: {SQL}")
|
||||
Dim oResult As Boolean = MSSQL_IDB.ExecuteNonQuery(SQL)
|
||||
Return New NonQueryResult()
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_request.LogError(ex.Message)
|
||||
Return New NonQueryResult(ex.Message)
|
||||
End Try
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
#Region "=== Database (MSSQL ECM) ==="
|
||||
Public Function ReturnDatatable_MSSQL_ECM(SQL As String) As TableResult Implements IEDMIService.ReturnDatatable_MSSQL_ECM
|
||||
Try
|
||||
_logger.Info($"ReturnDatatable_MSSQL_ECM, SQL: {SQL}")
|
||||
Dim oResult As DataTable = MSSQL_ECM.GetDatatable(SQL)
|
||||
Return New TableResult(oResult)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_request.LogError(ex.Message)
|
||||
Return New TableResult(ex.Message)
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function ReturnScalar_MSSQL_ECM(SQL As String) As ScalarResult Implements IEDMIService.ReturnScalar_MSSQL_ECM
|
||||
Try
|
||||
_logger.Info($"ReturnScalar_MSSQL_ECM, SQL: {SQL}")
|
||||
Dim oResult As Object = MSSQL_ECM.GetScalarValue(SQL)
|
||||
Return New ScalarResult(oResult)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_request.LogError(ex.Message)
|
||||
Return New ScalarResult(ex.Message)
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function ExecuteNonQuery_MSSQL_ECM(SQL As String) As NonQueryResult Implements IEDMIService.ExecuteNonQuery_MSSQL_ECM
|
||||
Try
|
||||
_logger.Info($"ExecuteNonQuery_MSSQL_ECM, SQL: {SQL}")
|
||||
Dim oResult As Boolean = MSSQL_ECM.ExecuteNonQuery(SQL)
|
||||
Return New NonQueryResult()
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_request.LogError(ex.Message)
|
||||
Return New NonQueryResult(ex.Message)
|
||||
End Try
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
#Region "=== Database (Firebird) ==="
|
||||
Public Function ReturnDatatable_Firebird(SQL As String) As TableResult Implements IEDMIService.ReturnDatatable_Firebird
|
||||
Try
|
||||
_logger.Info($"ReturnDatatable, SQL: {SQL}")
|
||||
_request.LogDebug($"ReturnDatatable, SQL: {SQL}")
|
||||
|
||||
Dim oResult As DataTable = Firebird.GetDatatableWithConnection(SQL, _request.Connection)
|
||||
Return New TableResult(oResult)
|
||||
Catch ex As Exception
|
||||
@ -113,13 +154,9 @@ Public Class EDMIService
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function ReturnScalar(SQL As String) As ScalarResult Implements IEDMIService.ReturnScalar
|
||||
Public Function ReturnScalar_Firebird(SQL As String) As ScalarResult Implements IEDMIService.ReturnScalar_Firebird
|
||||
Try
|
||||
TestRequestCreated()
|
||||
|
||||
_logger.Info($"ReturnScalar, SQL: {SQL}")
|
||||
_request.LogDebug($"ReturnScalar, SQL: {SQL}")
|
||||
|
||||
Dim oResult As Object = Firebird.GetScalarValueWithConnection(SQL, _request.Connection)
|
||||
Return New ScalarResult(oResult)
|
||||
Catch ex As Exception
|
||||
@ -129,13 +166,9 @@ Public Class EDMIService
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function ExecuteNonQuery(SQL As String) As NonQueryResult Implements IEDMIService.ExecuteNonQuery
|
||||
Public Function ExecuteNonQuery_Firebird(SQL As String) As NonQueryResult Implements IEDMIService.ExecuteNonQuery_Firebird
|
||||
Try
|
||||
TestRequestCreated()
|
||||
|
||||
_logger.Info($"ExecuteNonQuery, SQL: {SQL}")
|
||||
_request.LogDebug($"ExecuteNonQuery, SQL: {SQL}")
|
||||
|
||||
Dim oResult As Boolean = Firebird.ExecuteNonQueryWithConnection(SQL, _request.Connection)
|
||||
Return New NonQueryResult()
|
||||
Catch ex As Exception
|
||||
@ -145,6 +178,8 @@ Public Class EDMIService
|
||||
End Try
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
|
||||
#Region "=== Document ==="
|
||||
''' <summary>
|
||||
''' Imports a file according to ObjectStoreId
|
||||
@ -198,7 +233,7 @@ Public Class EDMIService
|
||||
oCommand.Parameters.AddWithValue("@REF_DOCID", 0)
|
||||
oCommand.Parameters.Add(New SqlParameter("@IDB_OBJ_ID", SqlDbType.BigInt))
|
||||
|
||||
Dim oObjectId = MSSQL.GetScalarValue(oCommand, "@IDB_OBJ_ID")
|
||||
Dim oObjectId = MSSQL_IDB.GetScalarValue(oCommand, "@IDB_OBJ_ID")
|
||||
|
||||
Return New Messages.DocumentImportResponse() With {.ObjectId = oObjectId}
|
||||
Catch ex As Exception
|
||||
@ -210,14 +245,14 @@ Public Class EDMIService
|
||||
Public Function GetFileByObjectId(Data As Messages.DocumentStreamRequest) As Messages.DocumentStreamResponse Implements IEDMIService.GetFileByObjectId
|
||||
Try
|
||||
Dim oSQL As String = $"SELECT ObjectStoreId FROM VWIDB_DOC_DATA WHERE IDB_OBJ_ID = {Data.ObjectId}"
|
||||
Dim oObjectStoreId = MSSQL.GetScalarValue(oSQL)
|
||||
Dim oObjectStoreId = MSSQL_IDB.GetScalarValue(oSQL)
|
||||
|
||||
Dim oObjectStore = GlobalState.ObjectStores.
|
||||
Where(Function(s) s.Id = oObjectStoreId).
|
||||
FirstOrDefault()
|
||||
|
||||
Dim oSQL2 As String = $"SELECT DocRelativePath FROM VWIDB_DOC_DATA WHERE IDB_OBJ_ID = {Data.ObjectId}"
|
||||
Dim oPath As String = MSSQL.GetScalarValue(oSQL2)
|
||||
Dim oPath As String = MSSQL_IDB.GetScalarValue(oSQL2)
|
||||
|
||||
|
||||
If IsNothing(oPath) Then
|
||||
@ -259,7 +294,7 @@ Public Class EDMIService
|
||||
Public Function ListFilesForUser() As Messages.DocumentListResponse Implements IEDMIService.ListFilesForUser
|
||||
Try
|
||||
Dim oSQL = $"SELECT * FROM VWIDB_DOC_DATA"
|
||||
Dim oDatatable As DataTable = MSSQL.GetDatatable(oSQL)
|
||||
Dim oDatatable As DataTable = MSSQL_IDB.GetDatatable(oSQL)
|
||||
oDatatable.TableName = "DocumentList"
|
||||
|
||||
Return New Messages.DocumentListResponse() With {
|
||||
|
||||
@ -101,7 +101,7 @@
|
||||
<Import Include="System.Threading.Tasks" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AppConfig.vb" />
|
||||
<Compile Include="Config.vb" />
|
||||
<Compile Include="GlobalState.vb" />
|
||||
<Compile Include="Messages.vb" />
|
||||
<Compile Include="Results\BaseResult.vb" />
|
||||
@ -165,6 +165,10 @@
|
||||
<Project>{1477032d-7a02-4c5f-b026-a7117da4bc6b}</Project>
|
||||
<Name>EDMI.File</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Modules.Config\Config.vbproj">
|
||||
<Project>{44982F9B-6116-44E2-85D0-F39650B1EF99}</Project>
|
||||
<Name>Config</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Modules.Database\Database.vbproj">
|
||||
<Project>{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}</Project>
|
||||
<Name>Database</Name>
|
||||
|
||||
@ -7,10 +7,10 @@ Public Class GlobalState
|
||||
Private _MSSQL As MSSQLServer
|
||||
Public Property ObjectStores As New List(Of ObjectStore)
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, MSSQL As MSSQLServer)
|
||||
Public Sub New(LogConfig As LogConfig, MSSQL_IDB As MSSQLServer)
|
||||
_LogConfig = LogConfig
|
||||
_Logger = LogConfig.GetLogger()
|
||||
_MSSQL = MSSQL
|
||||
_MSSQL = MSSQL_IDB
|
||||
End Sub
|
||||
|
||||
Public Sub LoadObjectStores()
|
||||
|
||||
@ -10,21 +10,37 @@ Interface IEDMIService
|
||||
Function Heartbeat() As Boolean
|
||||
#End Region
|
||||
|
||||
#Region "Database"
|
||||
#Region "Database (Firebird)"
|
||||
<OperationContract>
|
||||
Function CreateDatabaseRequest(Name As String, Optional Debug As Boolean = False) As String
|
||||
Function ReturnDatatable_Firebird(SQL As String) As TableResult
|
||||
|
||||
<OperationContract>
|
||||
Sub CloseDatabaseRequest()
|
||||
Function ReturnScalar_Firebird(SQL As String) As ScalarResult
|
||||
|
||||
<OperationContract>
|
||||
Function ReturnDatatable(SQL As String) As TableResult
|
||||
Function ExecuteNonQuery_Firebird(SQL As String) As NonQueryResult
|
||||
#End Region
|
||||
|
||||
#Region "Database (MSSQL IDB)"
|
||||
<OperationContract>
|
||||
Function ReturnDatatable_MSSQL_IDB(SQL As String) As TableResult
|
||||
|
||||
<OperationContract>
|
||||
Function ReturnScalar(SQL As String) As ScalarResult
|
||||
Function ReturnScalar_MSSQL_IDB(SQL As String) As ScalarResult
|
||||
|
||||
<OperationContract>
|
||||
Function ExecuteNonQuery(SQL As String) As NonQueryResult
|
||||
Function ExecuteNonQuery_MSSQL_IDB(SQL As String) As NonQueryResult
|
||||
#End Region
|
||||
|
||||
#Region "Database (MSSQL ECM)"
|
||||
<OperationContract>
|
||||
Function ReturnDatatable_MSSQL_ECM(SQL As String) As TableResult
|
||||
|
||||
<OperationContract>
|
||||
Function ReturnScalar_MSSQL_ECM(SQL As String) As ScalarResult
|
||||
|
||||
<OperationContract>
|
||||
Function ExecuteNonQuery_MSSQL_ECM(SQL As String) As NonQueryResult
|
||||
#End Region
|
||||
|
||||
#Region "Document (New)"
|
||||
|
||||
@ -4,6 +4,7 @@ Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules
|
||||
Imports System.ServiceModel.Description
|
||||
Imports DigitalData.Modules.Config
|
||||
|
||||
Public Class WindowsService
|
||||
Inherits ServiceBase
|
||||
@ -13,9 +14,11 @@ Public Class WindowsService
|
||||
Private _Logger As Logger
|
||||
|
||||
Private _Firebird As Firebird
|
||||
Private _MSSQL As MSSQLServer
|
||||
Private _MSSQL_ECM As MSSQLServer
|
||||
Private _MSSQL_IDB As MSSQLServer
|
||||
|
||||
Private _Config As AppConfig
|
||||
Private _ConfigManager As ConfigManager(Of Config)
|
||||
Private _Config As Config
|
||||
Private _Path As EDMI.File.Path
|
||||
Private _Archive As EDMI.File.Archive
|
||||
Private _Filesystem As Filesystem.File
|
||||
@ -31,27 +34,36 @@ Public Class WindowsService
|
||||
|
||||
Protected Overrides Sub OnStart(ByVal args As String())
|
||||
Try
|
||||
_Config = New AppConfig()
|
||||
_LogConfig = New LogConfig(LogConfig.PathType.CustomPath, "E:\EDMService") With {
|
||||
.Debug = True
|
||||
}
|
||||
Dim oServicePath As String = AppDomain.CurrentDomain.BaseDirectory
|
||||
|
||||
_LogConfig = New LogConfig(LogConfig.PathType.CustomPath, oServicePath)
|
||||
_Logger = _LogConfig.GetLogger()
|
||||
_Logger.Info("Service {0} is starting...", SERVICE_DISPLAY_NAME)
|
||||
_Logger.Info("ServiceDirectory: {0}", oServicePath)
|
||||
|
||||
MaybeStartFirebird()
|
||||
MaybeStartMSSQL()
|
||||
_Logger.Info("Loading Config")
|
||||
_ConfigManager = New ConfigManager(Of Config)(_LogConfig, oServicePath)
|
||||
_Config = _ConfigManager.Config
|
||||
_LogConfig.Debug = _ConfigManager.Config.Debug
|
||||
|
||||
_Logger.Debug("Connecting to Databases")
|
||||
|
||||
_Firebird = StartFirebird()
|
||||
_MSSQL_ECM = StartMSSQL_ECM()
|
||||
_MSSQL_IDB = StartMSSQL_IDB()
|
||||
|
||||
_Logger.Debug("Initializing EDMI Functions")
|
||||
|
||||
_Archive = New EDMI.File.Archive(_LogConfig)
|
||||
_Filesystem = New Filesystem.File(_LogConfig)
|
||||
_Global = New GlobalState(_LogConfig, _MSSQL)
|
||||
_Global = New GlobalState(_LogConfig, _MSSQL_IDB)
|
||||
|
||||
_Logger.Debug("Loading Objectstores")
|
||||
_Global.LoadObjectStores()
|
||||
|
||||
_Logger.Info("EDMI Functions initialized.")
|
||||
|
||||
EDMIService.MSSQL = _MSSQL
|
||||
_Logger.Debug("Preparing WCF ServiceHost")
|
||||
EDMIService.MSSQL_ECM = _MSSQL_ECM
|
||||
EDMIService.MSSQL_IDB = _MSSQL_IDB
|
||||
EDMIService.Firebird = _Firebird
|
||||
EDMIService.LogConfig = _LogConfig
|
||||
EDMIService.AppConfig = _Config
|
||||
@ -59,56 +71,56 @@ Public Class WindowsService
|
||||
EDMIService.Filesystem = _Filesystem
|
||||
EDMIService.GlobalState = _Global
|
||||
|
||||
_Logger.Debug("Starting WCF ServiceHost...")
|
||||
|
||||
_Logger.Debug("Starting WCF ServiceHost")
|
||||
_ServiceHost = New ServiceHost(GetType(EDMIService))
|
||||
_ServiceHost.Open()
|
||||
|
||||
_Logger.Info("WCF ServiceHost started.")
|
||||
_Logger.Info("WCF ServiceHost started")
|
||||
|
||||
_Logger.Info("Service {0} successfully started.", SERVICE_DISPLAY_NAME)
|
||||
_Logger.Info("Service {0} successfully started", SERVICE_DISPLAY_NAME)
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex, "Failed to start the service host!")
|
||||
GracefullyStop()
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Sub MaybeStartFirebird()
|
||||
If _Config.IsFirebirdConfigured() Then
|
||||
_Logger.Debug("Connecting to Firebird")
|
||||
_Firebird = New Firebird(
|
||||
_LogConfig,
|
||||
_Config.FirebirdDataSource,
|
||||
_Config.FirebirdDatabase,
|
||||
_Config.FirebirdUser,
|
||||
_Config.FirebirdPassword
|
||||
)
|
||||
_Logger.Info("Database connection established.")
|
||||
Else
|
||||
_Logger.Info("Firebird is not configured, will not be used!")
|
||||
End If
|
||||
End Sub
|
||||
Private Function StartFirebird() As Firebird
|
||||
_Logger.Debug("Connecting to Firebird")
|
||||
Dim oFirebird = New Firebird(
|
||||
_LogConfig,
|
||||
_Config.Firebird_Datasource,
|
||||
_Config.Firebird_DatabaseName,
|
||||
_Config.Firebird_DatabaseUser,
|
||||
_Config.Firebird_DatabasePassword
|
||||
)
|
||||
_Logger.Info("Database connection established.")
|
||||
Return oFirebird
|
||||
End Function
|
||||
|
||||
Private Sub MaybeStartMSSQL()
|
||||
If _Config.IsMSSQLConfigured() Then
|
||||
_Logger.Debug("Connecting to MSSQL")
|
||||
_MSSQL = New MSSQLServer(_LogConfig, _Config.MSSQLConnectionString)
|
||||
_Logger.Info("Database connection established.")
|
||||
Else
|
||||
_Logger.Info("MSSQL is not configured, will not be used!")
|
||||
End If
|
||||
End Sub
|
||||
Private Function StartMSSQL_ECM() As MSSQLServer
|
||||
_Logger.Debug("Connecting to ECM MSSQL")
|
||||
Dim oMSSQL = New MSSQLServer(_LogConfig, _Config.ConnectionString_ECM)
|
||||
_Logger.Info("Database connection to ECM Database established.")
|
||||
Return oMSSQL
|
||||
End Function
|
||||
|
||||
Private Function StartMSSQL_IDB() As MSSQLServer
|
||||
_Logger.Debug("Connecting to IDB MSSQL")
|
||||
Dim oMSSQL = New MSSQLServer(_LogConfig, _Config.ConnectionString_IDB)
|
||||
_Logger.Info("Database connection to IDB Database established.")
|
||||
Return oMSSQL
|
||||
End Function
|
||||
|
||||
Protected Overrides Sub OnStop()
|
||||
GracefullyStop()
|
||||
End Sub
|
||||
|
||||
Private Sub GracefullyStop()
|
||||
_Logger.Info("Service {0} is stopping!", SERVICE_DISPLAY_NAME)
|
||||
If _ServiceHost IsNot Nothing Then
|
||||
_ServiceHost.Close()
|
||||
_ServiceHost = Nothing
|
||||
End If
|
||||
_Logger.Info("Service {0} is stopping!", SERVICE_DISPLAY_NAME)
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user