mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-10 13:23:18 +00:00
service sync timer. control service from console
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using Bit.Core.Models;
|
using Bit.Core.Models;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -55,7 +56,7 @@ namespace Bit.Console
|
|||||||
Con.WriteLine("4. Configure sync");
|
Con.WriteLine("4. Configure sync");
|
||||||
Con.WriteLine("5. Simulate directory sync");
|
Con.WriteLine("5. Simulate directory sync");
|
||||||
Con.WriteLine("6. Sync directory");
|
Con.WriteLine("6. Sync directory");
|
||||||
Con.WriteLine("7. Start/stop background service");
|
Con.WriteLine("7. Control background service");
|
||||||
Con.WriteLine("8. Exit");
|
Con.WriteLine("8. Exit");
|
||||||
Con.WriteLine();
|
Con.WriteLine();
|
||||||
Con.Write("What would you like to do? ");
|
Con.Write("What would you like to do? ");
|
||||||
@@ -95,9 +96,10 @@ namespace Bit.Console
|
|||||||
case "sync":
|
case "sync":
|
||||||
await SyncAsync();
|
await SyncAsync();
|
||||||
break;
|
break;
|
||||||
|
case "7":
|
||||||
case "svc":
|
case "svc":
|
||||||
case "service":
|
case "service":
|
||||||
|
await ServiceAsync();
|
||||||
break;
|
break;
|
||||||
case "exit":
|
case "exit":
|
||||||
case "quit":
|
case "quit":
|
||||||
@@ -697,6 +699,80 @@ namespace Bit.Console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Task ServiceAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Con.WriteLine("Service current status: {0}", ControllerService.Instance.StatusString);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Con.WriteLine("Service unavailable.");
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var start = false;
|
||||||
|
var stop = false;
|
||||||
|
var status = false;
|
||||||
|
if(_usingArgs)
|
||||||
|
{
|
||||||
|
var parameters = ParseParameters();
|
||||||
|
if(parameters.ContainsKey("start"))
|
||||||
|
{
|
||||||
|
start = true;
|
||||||
|
}
|
||||||
|
else if(parameters.ContainsKey("stop"))
|
||||||
|
{
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con.WriteLine("1. Start service");
|
||||||
|
Con.WriteLine("2. Stop service");
|
||||||
|
Con.WriteLine("3. Check service status");
|
||||||
|
Con.WriteLine("4. Nothing, go back");
|
||||||
|
Con.WriteLine();
|
||||||
|
Con.Write("Option: ");
|
||||||
|
var selection = Con.ReadLine();
|
||||||
|
|
||||||
|
switch(selection)
|
||||||
|
{
|
||||||
|
case "1":
|
||||||
|
case "start":
|
||||||
|
start = true;
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
case "stop":
|
||||||
|
stop = true;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
case "status":
|
||||||
|
status = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(start)
|
||||||
|
{
|
||||||
|
Con.WriteLine("Starting service...");
|
||||||
|
ControllerService.Instance.Start();
|
||||||
|
}
|
||||||
|
else if(stop)
|
||||||
|
{
|
||||||
|
Con.WriteLine("Stopping service...");
|
||||||
|
ControllerService.Instance.Stop();
|
||||||
|
}
|
||||||
|
else if(status)
|
||||||
|
{
|
||||||
|
Con.WriteLine("Status: {0}", ControllerService.Instance.StatusString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}
|
||||||
|
|
||||||
private static string ReadSecureLine()
|
private static string ReadSecureLine()
|
||||||
{
|
{
|
||||||
var input = string.Empty;
|
var input = string.Empty;
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
<Reference Include="System.DirectoryServices" />
|
<Reference Include="System.DirectoryServices" />
|
||||||
<Reference Include="System.DirectoryServices.Protocols" />
|
<Reference Include="System.DirectoryServices.Protocols" />
|
||||||
<Reference Include="System.Security" />
|
<Reference Include="System.Security" />
|
||||||
|
<Reference Include="System.ServiceProcess" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
@@ -83,6 +84,7 @@
|
|||||||
<Compile Include="Models\ProfileResponse.cs" />
|
<Compile Include="Models\ProfileResponse.cs" />
|
||||||
<Compile Include="Models\TokenResponse.cs" />
|
<Compile Include="Models\TokenResponse.cs" />
|
||||||
<Compile Include="Services\ApiService.cs" />
|
<Compile Include="Services\ApiService.cs" />
|
||||||
|
<Compile Include="Services\ControllerService.cs" />
|
||||||
<Compile Include="Services\AzureDirectoryService.cs" />
|
<Compile Include="Services\AzureDirectoryService.cs" />
|
||||||
<Compile Include="Services\LdapDirectoryService.cs" />
|
<Compile Include="Services\LdapDirectoryService.cs" />
|
||||||
<Compile Include="Services\IDirectoryService.cs" />
|
<Compile Include="Services\IDirectoryService.cs" />
|
||||||
|
|||||||
70
src/Core/Services/ControllerService.cs
Normal file
70
src/Core/Services/ControllerService.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security;
|
||||||
|
using System.ServiceProcess;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bit.Core.Services
|
||||||
|
{
|
||||||
|
public class ControllerService
|
||||||
|
{
|
||||||
|
private static ControllerService _instance;
|
||||||
|
|
||||||
|
private ControllerService()
|
||||||
|
{
|
||||||
|
Controller = new ServiceController("bitwarden Directory Connector");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ControllerService Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(_instance == null)
|
||||||
|
{
|
||||||
|
_instance = new ControllerService();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceController Controller { get; private set; }
|
||||||
|
public ServiceControllerStatus Status => Controller.Status;
|
||||||
|
public string StatusString => Controller == null ? "Unavailable" : Status.ToString();
|
||||||
|
public bool Running => Status == ServiceControllerStatus.Running;
|
||||||
|
public bool Paused => Status == ServiceControllerStatus.Paused;
|
||||||
|
public bool Stopped => Status == ServiceControllerStatus.Stopped;
|
||||||
|
public bool Pending =>
|
||||||
|
Status == ServiceControllerStatus.ContinuePending ||
|
||||||
|
Status == ServiceControllerStatus.PausePending ||
|
||||||
|
Status == ServiceControllerStatus.StartPending ||
|
||||||
|
Status == ServiceControllerStatus.StopPending;
|
||||||
|
|
||||||
|
public bool Start()
|
||||||
|
{
|
||||||
|
if(Controller == null || !Stopped)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.Start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Stop()
|
||||||
|
{
|
||||||
|
if(Controller == null || !Controller.CanStop)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.Stop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using Bit.Core.Services;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
@@ -6,7 +8,7 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Service
|
namespace Service
|
||||||
{
|
{
|
||||||
@@ -15,6 +17,7 @@ namespace Service
|
|||||||
{
|
{
|
||||||
private IContainer _components;
|
private IContainer _components;
|
||||||
private EventLog _eventLog;
|
private EventLog _eventLog;
|
||||||
|
private Timer _timer;
|
||||||
|
|
||||||
public Service()
|
public Service()
|
||||||
{
|
{
|
||||||
@@ -44,6 +47,9 @@ namespace Service
|
|||||||
|
|
||||||
_components?.Dispose();
|
_components?.Dispose();
|
||||||
_components = null;
|
_components = null;
|
||||||
|
|
||||||
|
_timer?.Dispose();
|
||||||
|
_timer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
@@ -52,11 +58,53 @@ namespace Service
|
|||||||
protected override void OnStart(string[] args)
|
protected override void OnStart(string[] args)
|
||||||
{
|
{
|
||||||
_eventLog.WriteEntry("Service started!", EventLogEntryType.Information);
|
_eventLog.WriteEntry("Service started!", EventLogEntryType.Information);
|
||||||
|
|
||||||
|
if(SettingsService.Instance.Server == null)
|
||||||
|
{
|
||||||
|
_eventLog.WriteEntry("Server not configured.", EventLogEntryType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SettingsService.Instance.Sync == null)
|
||||||
|
{
|
||||||
|
_eventLog.WriteEntry("Sync not configured.", EventLogEntryType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!AuthService.Instance.Authenticated || !AuthService.Instance.OrganizationSet)
|
||||||
|
{
|
||||||
|
_eventLog.WriteEntry("Not authenticated with proper organization set.", EventLogEntryType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timerDelegate = new TimerCallback(Callback);
|
||||||
|
_timer = new Timer(timerDelegate, null, 1000, 60 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStop()
|
protected override void OnStop()
|
||||||
{
|
{
|
||||||
_eventLog.WriteEntry("Service stopped!", EventLogEntryType.Information);
|
_eventLog.WriteEntry("Service stopped!", EventLogEntryType.Information);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Callback(object stateInfo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = Sync.SyncAllAsync(false, true).GetAwaiter().GetResult();
|
||||||
|
if(result.Success)
|
||||||
|
{
|
||||||
|
_eventLog.WriteEntry($"Synced {result.Groups.Count} groups, {result.Users.Count} users.",
|
||||||
|
EventLogEntryType.SuccessAudit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_eventLog.WriteEntry($"Sync failed: {result.ErrorMessage}", EventLogEntryType.FailureAudit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(ApplicationException e)
|
||||||
|
{
|
||||||
|
_eventLog.WriteEntry($"Sync exception: {e.Message}", EventLogEntryType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user