view ServerMonitor/Objects/Server.cs @ 4:3142e52cbe69

Lots more progress
author Brad Greco <brad@bgreco.net>
date Sun, 10 Feb 2019 20:51:26 -0500
parents 3e1a2131f897
children b6fe203af9d5
line wrap: on
line source

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.ComponentModel;
using Renci.SshNet;
using System.Runtime.Serialization;

namespace ServerMonitorApp
{
    public enum LoginType { PrivateKey = 0, Password = 1 };

    public class Server
    {
        private string _host;
        private int _port;
        private string _username;
        private LoginType _loginType;
        private string _keyFile;
        private SshClient _sshClient;
        private bool _enabled = true;
        private byte[] passwordHash;

        public event EventHandler CheckModified;
        public event EventHandler EnabledChanged;

        public readonly BindingList<Check> Checks = new BindingList<Check>();

        public int Id { get; set; }

        public string Name { get; set; }

        public string Host
        {
            get { return _host; }
            set { _host = value; InvalidateSshConnection(); }
        }

        public int Port
        {
            get { return _port; }
            set { _port = value; InvalidateSshConnection(); }
        }

        public string Username
        {
            get { return _username; }
            set { _username = value; InvalidateSshConnection(); }
        }

        public LoginType LoginType
        {
            get { return _loginType; }
            set { _loginType = value; InvalidateSshConnection(); }
        }

        public string KeyFile
        {
            get { return _keyFile; }
            set { _keyFile = value; InvalidateSshConnection(); }
        }

        public string Password
        {
            get {
                return passwordHash == null ? null :
                    Encoding.UTF8.GetString(ProtectedData.Unprotect(passwordHash, Encoding.UTF8.GetBytes("Server".Reverse().ToString()), DataProtectionScope.CurrentUser));
            }
            set
            {
                passwordHash = ProtectedData.Protect(Encoding.UTF8.GetBytes(value),
                                 Encoding.UTF8.GetBytes("Server".Reverse().ToString()), // Minor obfuscation of additional entropy
                                 DataProtectionScope.CurrentUser);
            }
        }

        public bool Enabled
        {
            get { return _enabled; }
            set { _enabled = value; EnabledChanged?.Invoke(this, new EventArgs()); }
        }

        public CheckStatus Status => !Enabled ? CheckStatus.Disabled : Checks
            .Where(c => c.Enabled)
            .Select(c => c.LastRunStatus)
            .DefaultIfEmpty(CheckStatus.Success)
            .Max();

        public SshClient SshClient
        {
            get
            {
                if (_sshClient == null)
                {
                    AuthenticationMethod auth = null;
                    if (LoginType == LoginType.Password)
                        auth = new PasswordAuthenticationMethod(Username, Password);
                    else
                        auth = new PrivateKeyAuthenticationMethod(Username, new PrivateKeyFile(KeyFile));
                    ConnectionInfo info = new ConnectionInfo(Host, Port, Username, auth);
                    _sshClient = new SshClient(info);
                }
                return _sshClient;
            }
        }

        /*public Server() { }

        public Server(Server server)
        {
            Name = server.Name;
            Host = server.Host;
            Port = server.Port;
            Username = server.Username;
            LoginType = server.LoginType;
            KeyFile = server.KeyFile;
            Enabled = server.Enabled;
        }*/

        public void DeleteCheck(Check check)
        {
            Checks.Remove(check);
            check.Server = null;
            CheckModified?.Invoke(check, new EventArgs());
        }

        public string Validate()
        {
            string message = string.Empty;
            if (Name.Length == 0)
                message += "\"Name\" must not be empty" + Environment.NewLine;
            if (Host.Length == 0)
                message += "\"Host\" must not be empty" + Environment.NewLine;
            return message.Length > 0 ? message : null;
        }

        public void UpdateCheck(Check check)
        {
            Check oldCheck = Checks.FirstOrDefault(c => c.Id == check.Id);
            if (!ReferenceEquals(check, oldCheck))
            {
                int index = Checks.IndexOf(oldCheck);
                if (index == -1)
                    Checks.Add(check);
                else
                    Checks[index] = check;
            }
            CheckModified?.Invoke(check, new EventArgs());
        }

        public bool IsEmpty()
        {
            return Name.IsNullOrEmpty()
                && Host.IsNullOrEmpty()
                && Checks.Count == 0;
        }

        private void InvalidateSshConnection()
        {
            _sshClient?.Dispose();
            _sshClient = null;
        }
    }
}