ConfigManager: Test write access for config paths

This commit is contained in:
Jonathan Jenne 2019-07-08 12:18:58 +02:00
parent 75fc25bf94
commit b88479b8b5
3 changed files with 75 additions and 39 deletions

View File

@ -24,6 +24,8 @@ Public Class File
Private ReadOnly _logger As Logger Private ReadOnly _logger As Logger
Private ReadOnly _logConfig As LogConfig Private ReadOnly _logConfig As LogConfig
Private Const FILE_NAME_ACCESS_TEST = "accessTest.txt"
Public Sub New(LogConfig As LogConfig) Public Sub New(LogConfig As LogConfig)
_logConfig = LogConfig _logConfig = LogConfig
_logger = LogConfig.GetLogger() _logger = LogConfig.GetLogger()
@ -94,6 +96,55 @@ Public Class File
IO.File.Move(FilePath, Path.Combine(Directory, oFileInfo.Name)) IO.File.Move(FilePath, Path.Combine(Directory, oFileInfo.Name))
End Sub End Sub
''' <summary>
''' Tries to create a directory and returns its path.
''' Returns a temp path if `DirectoryPath` can not be created or written to.
''' </summary>
''' <param name="DirectoryPath">The directory to create</param>
''' <param name="TestWriteAccess">Should a write access test be performed?</param>
''' <returns>The used path</returns>
Public Function CreateDirectory(DirectoryPath As String, Optional TestWriteAccess As Boolean = True) As String
Dim oFinalPath As String
If Directory.Exists(DirectoryPath) Then
_logger.Debug("Directory {0} already exists. Skipping.", DirectoryPath)
oFinalPath = DirectoryPath
Else
Try
Directory.CreateDirectory(DirectoryPath)
oFinalPath = DirectoryPath
Catch ex As Exception
_logger.Error(ex)
_logger.Warn("Directory {0} could not be created. Temp path will be used instead.", DirectoryPath)
oFinalPath = Path.GetTempPath()
End Try
End If
If TestWriteAccess AndAlso Not TestPathIsWritable(DirectoryPath) Then
_logger.Warn("Directory {0} is not writable. Temp path will be used instead.", DirectoryPath)
oFinalPath = Path.GetTempPath()
Else
oFinalPath = DirectoryPath
End If
_logger.Debug("Using path {0}", oFinalPath)
Return oFinalPath
End Function
Public Function TestPathIsWritable(DirectoryPath As String) As Boolean
Try
Dim fileAccessPath = Path.Combine(DirectoryPath, FILE_NAME_ACCESS_TEST)
Using fs As FileStream = IO.File.Create(fileAccessPath)
fs.WriteByte(0)
End Using
IO.File.Delete(fileAccessPath)
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Function TestPathIsDirectory(Path As String) As Boolean Public Function TestPathIsDirectory(Path As String) As Boolean
If Not Directory.Exists(Path) Then If Not Directory.Exists(Path) Then
Return False Return False

View File

@ -79,7 +79,9 @@
<Compile Include="DocumentObject.vb" /> <Compile Include="DocumentObject.vb" />
<Compile Include="FileContainer.vb" /> <Compile Include="FileContainer.vb" />
<Compile Include="Encryption.vb" /> <Compile Include="Encryption.vb" />
<Compile Include="File.vb" /> <Compile Include="File.vb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Compile>
<Compile Include="FileContainerInner.vb" /> <Compile Include="FileContainerInner.vb" />
<Compile Include="FileWatcher.vb" /> <Compile Include="FileWatcher.vb" />
<Compile Include="FileWatcherFilters.vb" /> <Compile Include="FileWatcherFilters.vb" />

View File

@ -11,8 +11,8 @@ Public Class ConfigManager(Of T)
Private ReadOnly _LogConfig As LogConfig Private ReadOnly _LogConfig As LogConfig
Private ReadOnly _Logger As Logger Private ReadOnly _Logger As Logger
Private ReadOnly _File As Filesystem.File Private ReadOnly _File As Filesystem.File
Private ReadOnly _UserPath As String Private ReadOnly _UserDirectory As String
Private ReadOnly _ComputerPath As String Private ReadOnly _ComputerDirectory As String
Private ReadOnly _TestMode As Boolean = False Private ReadOnly _TestMode As Boolean = False
Private ReadOnly _Blueprint As T Private ReadOnly _Blueprint As T
@ -33,17 +33,17 @@ Public Class ConfigManager(Of T)
''' <returns></returns> ''' <returns></returns>
Public ReadOnly Property Config As T Public ReadOnly Property Config As T
''' <summary>
''' Path to the current user config.
''' </summary>
''' <returns></returns>
Public ReadOnly Property UserConfigPath As String Public ReadOnly Property UserConfigPath As String
Get
Return _UserPath
End Get
End Property
''' <summary>
''' Path to the current computer config. Maybe the same as `UserConfigPath`
''' </summary>
''' <returns></returns>
Public ReadOnly Property ComputerConfigPath As String Public ReadOnly Property ComputerConfigPath As String
Get
Return _ComputerPath
End Get
End Property
''' <summary> ''' <summary>
''' Creates a new instance of the ConfigManager ''' Creates a new instance of the ConfigManager
@ -58,35 +58,18 @@ Public Class ConfigManager(Of T)
_Logger = LogConfig.GetLogger() _Logger = LogConfig.GetLogger()
_File = New Filesystem.File(_LogConfig) _File = New Filesystem.File(_LogConfig)
_UserPath = Path.Combine(UserConfigPath, USER_CONFIG_NAME)
_ComputerPath = Path.Combine(ComputerConfigPath, COMPUTER_CONFIG_NAME)
_ForceUserConfig = ForceUserConfig
_Blueprint = Activator.CreateInstance(Of T) _Blueprint = Activator.CreateInstance(Of T)
_BlueprintType = _Blueprint.GetType _BlueprintType = _Blueprint.GetType
_Serializer = New XmlSerializer(_BlueprintType) _Serializer = New XmlSerializer(_BlueprintType)
If Not Directory.Exists(UserConfigPath) Then _UserDirectory = _File.CreateDirectory(UserConfigPath)
_Logger.Debug("UserConfigPath {0} did not exist and was created", UserConfigPath) _ComputerDirectory = _File.CreateDirectory(ComputerConfigPath)
Directory.CreateDirectory(UserConfigPath) _ForceUserConfig = ForceUserConfig
End If
If Not _File.TestPathIsDirectory(UserConfigPath) Then UserConfigPath = Path.Combine(_UserDirectory, USER_CONFIG_NAME)
_Logger.Warn("UserConfigPath {0} is not a directory", UserConfigPath) ComputerConfigPath = Path.Combine(_ComputerDirectory, COMPUTER_CONFIG_NAME)
Throw New ArgumentException($"Path {UserConfigPath} is not a directory!")
End If
If Not Directory.Exists(ComputerConfigPath) Then Config = LoadConfig()
_Logger.Debug("ComputerConfigPath {0} did not exist and was created", ComputerConfigPath)
Directory.CreateDirectory(ComputerConfigPath)
End If
If Not _File.TestPathIsDirectory(ComputerConfigPath) Then
_Logger.Warn("ComputerConfigPath {0} is not a directory", ComputerConfigPath)
Throw New ArgumentException($"Path {ComputerConfigPath} is not a directory!")
End If
_Config = LoadConfig()
End Sub End Sub
''' <summary> ''' <summary>
@ -105,7 +88,7 @@ Public Class ConfigManager(Of T)
''' <returns>True if save was successful, False otherwise</returns> ''' <returns>True if save was successful, False otherwise</returns>
Public Function Save(Optional ForceAll As Boolean = False) As Boolean Public Function Save(Optional ForceAll As Boolean = False) As Boolean
Try Try
WriteToFile(_Config, _UserPath, ForceAll) WriteToFile(Config, UserConfigPath, ForceAll)
Return True Return True
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@ -169,9 +152,9 @@ Public Class ConfigManager(Of T)
Private Function LoadComputerConfig(ByVal Config As T) As T Private Function LoadComputerConfig(ByVal Config As T) As T
If File.Exists(_ComputerPath) Then If File.Exists(ComputerConfigPath) Then
Try Try
Dim oComputerConfig = ReadFromFile(_ComputerPath) Dim oComputerConfig = ReadFromFile(ComputerConfigPath)
CopyValues(oComputerConfig, Config) CopyValues(oComputerConfig, Config)
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@ -186,9 +169,9 @@ Public Class ConfigManager(Of T)
End Function End Function
Private Function LoadUserConfig(ByVal Config As T) As T Private Function LoadUserConfig(ByVal Config As T) As T
If File.Exists(_UserPath) Then If File.Exists(UserConfigPath) Then
Try Try
Dim oUserConfig = ReadFromFile(_UserPath) Dim oUserConfig = ReadFromFile(UserConfigPath)
' if user config exists ' if user config exists
If Not IsNothing(oUserConfig) Then If Not IsNothing(oUserConfig) Then