Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1ed6f17c9 | ||
|
|
656a3c2dae | ||
|
|
716fc98f8a | ||
|
|
5e01835826 | ||
|
|
9ad2ce50e3 |
26 changed files with 787 additions and 1 deletions
12
LANCommander.SDK/Enums/VPNStatus.cs
Normal file
12
LANCommander.SDK/Enums/VPNStatus.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.Enums
|
||||
{
|
||||
public enum VPNStatus
|
||||
{
|
||||
Disconnected,
|
||||
Connected,
|
||||
}
|
||||
}
|
||||
11
LANCommander.SDK/Enums/VPNType.cs
Normal file
11
LANCommander.SDK/Enums/VPNType.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.Enums
|
||||
{
|
||||
public enum VPNType
|
||||
{
|
||||
ZeroTier = 1
|
||||
}
|
||||
}
|
||||
13
LANCommander.SDK/VPN/Clients/IVPNClient.cs
Normal file
13
LANCommander.SDK/VPN/Clients/IVPNClient.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Clients
|
||||
{
|
||||
public interface IVPNClient
|
||||
{
|
||||
bool Connect();
|
||||
bool Disconnect();
|
||||
VPNConnectionStatus GetStatus();
|
||||
}
|
||||
}
|
||||
174
LANCommander.SDK/VPN/Clients/ZeroTierClient.cs
Normal file
174
LANCommander.SDK/VPN/Clients/ZeroTierClient.cs
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
using LANCommander.SDK.VPN.Configurations;
|
||||
using LANCommander.SDK.VPN.Exceptions;
|
||||
using LANCommander.SDK.VPN.Models.ZeroTier;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Clients
|
||||
{
|
||||
public class ZeroTierClient : IVPNClient
|
||||
{
|
||||
private ZeroTierConfiguration Configuration;
|
||||
private RestClient ZeroTierServiceClient;
|
||||
private Client Client;
|
||||
private string Token;
|
||||
private const string BaseUrl = "http://localhost:9993";
|
||||
|
||||
public ZeroTierClient(ZeroTierConfiguration configuration, Client client) {
|
||||
Configuration = configuration;
|
||||
Client = client;
|
||||
|
||||
ZeroTierServiceClient = new RestClient(BaseUrl);
|
||||
|
||||
var tokenPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "ZeroTier", "One", "authtoken.secret");
|
||||
|
||||
if (File.Exists(tokenPath))
|
||||
Token = File.ReadAllText(tokenPath);
|
||||
else
|
||||
throw new ClientInitializationException("Could not read the token");
|
||||
}
|
||||
|
||||
public bool Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
var task = PostRequest<UpdateNetworkSettingsResponse>($"/network/{Configuration.NetworkId}", new UpdateNetworkSettingsRequest
|
||||
{
|
||||
AllowDefault = false,
|
||||
AllowDNS = true,
|
||||
AllowManaged = true,
|
||||
AllowGlobal = false
|
||||
});
|
||||
|
||||
task.Wait();
|
||||
|
||||
var response = task.Result;
|
||||
|
||||
Client.PostRequest<ApproveNodeRequest>("/api/ZeroTier/ApproveNode", new ApproveNodeRequest
|
||||
{
|
||||
NodeId = response.Id
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Disconnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = GetNodeStatus();
|
||||
|
||||
var task = DeleteRequest<LeaveNetworkResponse>($"/network/{Configuration.NetworkId}");
|
||||
|
||||
task.Wait();
|
||||
|
||||
var response = task.Result;
|
||||
|
||||
if (response.Result)
|
||||
{
|
||||
Client.PostRequest<ApproveNodeRequest>("/api/ZeroTier/RemoveNode", new ApproveNodeRequest
|
||||
{
|
||||
NodeId = status.Address
|
||||
});
|
||||
}
|
||||
|
||||
return response.Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public VPNConnectionStatus GetStatus()
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = GetNodeStatus();
|
||||
|
||||
return new VPNConnectionStatus
|
||||
{
|
||||
Connected = response.Online,
|
||||
Status = response.Online ? "Connected" : "Not Connected"
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private NodeStatusResponse GetNodeStatus()
|
||||
{
|
||||
var task = GetRequest<NodeStatusResponse>("/status");
|
||||
|
||||
task.Wait();
|
||||
|
||||
var response = task.Result;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<T> PostRequest<T>(string route, object body)
|
||||
{
|
||||
if (Token == null)
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddJsonBody(body)
|
||||
.AddHeader("X-ZT1-AUTH", Token);
|
||||
|
||||
var response = await ZeroTierServiceClient.PostAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<T> PostRequest<T>(string route)
|
||||
{
|
||||
if (Token == null)
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddHeader("X-ZT1-AUTH", Token);
|
||||
|
||||
var response = await ZeroTierServiceClient.PostAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<T> GetRequest<T>(string route)
|
||||
{
|
||||
if (Token == null)
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddHeader("X-ZT1-AUTH", Token);
|
||||
|
||||
var response = await ZeroTierServiceClient.GetAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<T> DeleteRequest<T>(string route)
|
||||
{
|
||||
if (Token == null)
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddHeader("X-ZT1-AUTH", Token);
|
||||
|
||||
var response = await ZeroTierServiceClient.DeleteAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
LANCommander.SDK/VPN/Configurations/VPNConfiguration.cs
Normal file
13
LANCommander.SDK/VPN/Configurations/VPNConfiguration.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using LANCommander.SDK.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Configurations
|
||||
{
|
||||
public class VPNConfiguration
|
||||
{
|
||||
public VPNType Type { get; set; }
|
||||
public object Data { get; set; }
|
||||
}
|
||||
}
|
||||
12
LANCommander.SDK/VPN/Configurations/ZeroTierConfiguration.cs
Normal file
12
LANCommander.SDK/VPN/Configurations/ZeroTierConfiguration.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using LANCommander.SDK.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Configurations
|
||||
{
|
||||
public class ZeroTierConfiguration
|
||||
{
|
||||
public string NetworkId { get; set; }
|
||||
}
|
||||
}
|
||||
12
LANCommander.SDK/VPN/ConnectionStatus.cs
Normal file
12
LANCommander.SDK/VPN/ConnectionStatus.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN
|
||||
{
|
||||
public class VPNConnectionStatus
|
||||
{
|
||||
public bool Connected { get; set; }
|
||||
public string Status { get; set; }
|
||||
}
|
||||
}
|
||||
11
LANCommander.SDK/VPN/Exceptions/ClientConnectionException.cs
Normal file
11
LANCommander.SDK/VPN/Exceptions/ClientConnectionException.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Exceptions
|
||||
{
|
||||
public class ClientConnectionException : Exception
|
||||
{
|
||||
public ClientConnectionException(string message) : base(message) { }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Exceptions
|
||||
{
|
||||
public class ClientInitializationException : Exception
|
||||
{
|
||||
public ClientInitializationException(string message) : base(message) { }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Exceptions.ZeroTier
|
||||
{
|
||||
public class ServiceNotInstalledException : Exception
|
||||
{
|
||||
public ServiceNotInstalledException(string message) : base(message) { }
|
||||
}
|
||||
}
|
||||
11
LANCommander.SDK/VPN/Models/ZeroTier/ApproveNodeRequest.cs
Normal file
11
LANCommander.SDK/VPN/Models/ZeroTier/ApproveNodeRequest.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Models.ZeroTier
|
||||
{
|
||||
public class ApproveNodeRequest
|
||||
{
|
||||
public string NodeId { get; set; }
|
||||
}
|
||||
}
|
||||
11
LANCommander.SDK/VPN/Models/ZeroTier/LeaveNetworkRequest.cs
Normal file
11
LANCommander.SDK/VPN/Models/ZeroTier/LeaveNetworkRequest.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Models.ZeroTier
|
||||
{
|
||||
public class LeaveNetworkRequest
|
||||
{
|
||||
public string NetworkId { get; set; }
|
||||
}
|
||||
}
|
||||
11
LANCommander.SDK/VPN/Models/ZeroTier/LeaveNetworkResponse.cs
Normal file
11
LANCommander.SDK/VPN/Models/ZeroTier/LeaveNetworkResponse.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Models.ZeroTier
|
||||
{
|
||||
public class LeaveNetworkResponse
|
||||
{
|
||||
public bool Result { get; set; }
|
||||
}
|
||||
}
|
||||
13
LANCommander.SDK/VPN/Models/ZeroTier/NodeStatusResponse.cs
Normal file
13
LANCommander.SDK/VPN/Models/ZeroTier/NodeStatusResponse.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Models.ZeroTier
|
||||
{
|
||||
public class NodeStatusResponse
|
||||
{
|
||||
public string Address { get; set; }
|
||||
public bool Online { get; set; }
|
||||
public bool TcpFallbackActive { get; set; }
|
||||
}
|
||||
}
|
||||
11
LANCommander.SDK/VPN/Models/ZeroTier/RemoveNodeRequest.cs
Normal file
11
LANCommander.SDK/VPN/Models/ZeroTier/RemoveNodeRequest.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Models.ZeroTier
|
||||
{
|
||||
public class RemoveNodeRequest
|
||||
{
|
||||
public string NodeId { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Models.ZeroTier
|
||||
{
|
||||
public class UpdateNetworkSettingsRequest
|
||||
{
|
||||
public bool AllowDNS { get; set; }
|
||||
public bool AllowDefault { get; set; }
|
||||
public bool AllowManaged { get; set; }
|
||||
public bool AllowGlobal { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LANCommander.SDK.VPN.Models.ZeroTier
|
||||
{
|
||||
public class UpdateNetworkSettingsResponse
|
||||
{
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
||||
63
LANCommander.SDK/VPNService.cs
Normal file
63
LANCommander.SDK/VPNService.cs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
using LANCommander.SDK.VPN;
|
||||
using LANCommander.SDK.VPN.Clients;
|
||||
using LANCommander.SDK.VPN.Configurations;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.SDK
|
||||
{
|
||||
public class VPNService
|
||||
{
|
||||
private readonly ILogger Logger;
|
||||
private Client Client { get; set; }
|
||||
|
||||
public delegate void OnConnectedHandler(object sender);
|
||||
public event OnConnectedHandler OnConnected;
|
||||
|
||||
public delegate void OnDisconnectedHandler(object sender);
|
||||
public event OnDisconnectedHandler OnDisconnected;
|
||||
|
||||
private IVPNClient VPNClient;
|
||||
|
||||
public VPNService(Client client)
|
||||
{
|
||||
Client = client;
|
||||
}
|
||||
|
||||
public VPNService(Client client, ILogger logger)
|
||||
{
|
||||
Client = client;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
var configuration = Client.GetRequest<VPNConfiguration>("/api/VPN/Configuration");
|
||||
|
||||
switch (configuration.Type)
|
||||
{
|
||||
case Enums.VPNType.ZeroTier:
|
||||
VPNClient = new ZeroTierClient(configuration.Data as ZeroTierConfiguration, Client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Connect()
|
||||
{
|
||||
return VPNClient.Connect();
|
||||
}
|
||||
|
||||
public bool Disconnect()
|
||||
{
|
||||
return VPNClient.Disconnect();
|
||||
}
|
||||
|
||||
public VPNConnectionStatus GetStatus()
|
||||
{
|
||||
return VPNClient.GetStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
38
LANCommander/Controllers/Api/VPNController.cs
Normal file
38
LANCommander/Controllers/Api/VPNController.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using LANCommander.Models;
|
||||
using LANCommander.SDK.VPN.Configurations;
|
||||
using LANCommander.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LANCommander.Controllers.Api
|
||||
{
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class VPNController : ControllerBase
|
||||
{
|
||||
public VPNController() { }
|
||||
|
||||
[HttpGet]
|
||||
public async Task<VPNConfiguration> GetConfiguration()
|
||||
{
|
||||
var settings = SettingService.GetSettings();
|
||||
var configuration = new VPNConfiguration()
|
||||
{
|
||||
Type = SDK.Enums.VPNType.ZeroTier
|
||||
};
|
||||
|
||||
switch (settings.VPN.Type)
|
||||
{
|
||||
case SDK.Enums.VPNType.ZeroTier:
|
||||
configuration.Data = new ZeroTierConfiguration
|
||||
{
|
||||
NetworkId = (settings.VPN.Configuration as LANCommanderZeroTierSettings).NetworkId
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return configuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
74
LANCommander/Controllers/Api/ZeroTierController.cs
Normal file
74
LANCommander/Controllers/Api/ZeroTierController.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Data.Models;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.SDK.VPN.Models.ZeroTier;
|
||||
using LANCommander.Services;
|
||||
using LANCommander.Services.VPNServices;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LANCommander.Controllers.Api
|
||||
{
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ZeroTierController : ControllerBase
|
||||
{
|
||||
private readonly ZeroTierService ZeroTierService;
|
||||
private readonly UserManager<User> UserManager;
|
||||
private readonly RoleManager<Role> RoleManager;
|
||||
|
||||
public ZeroTierController(ZeroTierService zeroTierService, UserManager<User> userManager, RoleManager<Role> roleManager)
|
||||
{
|
||||
ZeroTierService = zeroTierService;
|
||||
UserManager = userManager;
|
||||
RoleManager = roleManager;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> ApproveNode(ApproveNodeRequest request)
|
||||
{
|
||||
var settings = SettingService.GetSettings();
|
||||
|
||||
var user = await UserManager.FindByNameAsync(User.Identity.Name);
|
||||
var roleNames = await UserManager.GetRolesAsync(user);
|
||||
|
||||
bool allowed = false;
|
||||
|
||||
foreach (var roleName in roleNames)
|
||||
{
|
||||
var role = await RoleManager.FindByNameAsync(roleName);
|
||||
|
||||
if (role != null && settings.VPN.AllowedRoles.Contains(role.Id))
|
||||
{
|
||||
allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allowed)
|
||||
return Forbid();
|
||||
|
||||
var config = settings.VPN.Configuration as LANCommanderZeroTierSettings;
|
||||
|
||||
await ZeroTierService.ApproveNode(config.NetworkId, user.UserName);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> RemoveNode(RemoveNodeRequest request)
|
||||
{
|
||||
var settings = SettingService.GetSettings();
|
||||
|
||||
var user = await UserManager.FindByNameAsync(User.Identity.Name);
|
||||
|
||||
// Do we add any check here that the user is authorized to do VPN stuff?
|
||||
// We should at least do a check that they own that
|
||||
|
||||
await ZeroTierService.RemoveNode(request.NodeId);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using NLog.Targets;
|
||||
using LANCommander.SDK.Enums;
|
||||
using NLog.Targets;
|
||||
|
||||
namespace LANCommander.Models
|
||||
{
|
||||
|
|
@ -23,6 +24,7 @@ namespace LANCommander.Models
|
|||
public LANCommanderArchiveSettings Archives { get; set; } = new LANCommanderArchiveSettings();
|
||||
public LANCommanderMediaSettings Media { get; set; } = new LANCommanderMediaSettings();
|
||||
public LANCommanderIPXRelaySettings IPXRelay { get; set; } = new LANCommanderIPXRelaySettings();
|
||||
public LANCommanderVPNSettings VPN { get; set; } = new LANCommanderVPNSettings();
|
||||
public LANCommanderWikiSettings Wiki { get; set; } = new LANCommanderWikiSettings();
|
||||
public LANCommanderUpdateSettings Update { get; set; } = new LANCommanderUpdateSettings();
|
||||
public LANCommanderLogSettings Logs { get; set; } = new LANCommanderLogSettings();
|
||||
|
|
@ -90,6 +92,20 @@ namespace LANCommander.Models
|
|||
public bool Logging { get; set; } = false;
|
||||
}
|
||||
|
||||
public class LANCommanderVPNSettings
|
||||
{
|
||||
public bool Enabled { get; set; } = false;
|
||||
public IEnumerable<Guid> AllowedRoles { get; set; }
|
||||
public VPNType Type { get; set; } = VPNType.ZeroTier;
|
||||
public object Configuration { get; set; }
|
||||
}
|
||||
|
||||
public class LANCommanderZeroTierSettings
|
||||
{
|
||||
public string NetworkId { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
}
|
||||
|
||||
public class LANCommanderWikiSettings
|
||||
{
|
||||
public bool Enabled { get; set; } = false;
|
||||
|
|
|
|||
8
LANCommander/Models/ZeroTier/MemberConfig.cs
Normal file
8
LANCommander/Models/ZeroTier/MemberConfig.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace LANCommander.Models.ZeroTier
|
||||
{
|
||||
public class MemberConfig
|
||||
{
|
||||
public bool ActiveBridge { get; set; }
|
||||
public bool Authorized { get; set; }
|
||||
}
|
||||
}
|
||||
10
LANCommander/Models/ZeroTier/ModifyMemberRequest.cs
Normal file
10
LANCommander/Models/ZeroTier/ModifyMemberRequest.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
namespace LANCommander.Models.ZeroTier
|
||||
{
|
||||
public class ModifyMemberRequest
|
||||
{
|
||||
public bool Hidden { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public MemberConfig Config { get; set; }
|
||||
}
|
||||
}
|
||||
92
LANCommander/Services/VPNServices/ZeroTierService.cs
Normal file
92
LANCommander/Services/VPNServices/ZeroTierService.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
using LANCommander.Models;
|
||||
using LANCommander.Models.ZeroTier;
|
||||
using RestSharp;
|
||||
|
||||
namespace LANCommander.Services.VPNServices
|
||||
{
|
||||
public class ZeroTierService
|
||||
{
|
||||
private const string BaseUrl = "https://api.zerotier.com/api/v1";
|
||||
private RestClient Client { get; set; }
|
||||
private LANCommanderZeroTierSettings Configuration { get; set; }
|
||||
|
||||
public ZeroTierService() {
|
||||
Client = new RestClient(BaseUrl);
|
||||
|
||||
var settings = SettingService.GetSettings();
|
||||
|
||||
Configuration = settings.VPN.Configuration as LANCommanderZeroTierSettings;
|
||||
}
|
||||
|
||||
public async Task ApproveNode(string nodeId, string username)
|
||||
{
|
||||
await PostRequestAsync<object>($"/network/{Configuration.NetworkId}/member/{nodeId}", new ModifyMemberRequest
|
||||
{
|
||||
Hidden = false,
|
||||
Name = username,
|
||||
Config = new MemberConfig
|
||||
{
|
||||
Authorized = true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task RemoveNode(string nodeId)
|
||||
{
|
||||
await DeleteRequest<object>($"/network/{Configuration.NetworkId}/member/{nodeId}");
|
||||
}
|
||||
|
||||
private async Task<T> PostRequestAsync<T>(string route, object body)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(Configuration.ApiKey))
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddJsonBody(body)
|
||||
.AddHeader("Authorization", $"token {Configuration.ApiKey}");
|
||||
|
||||
var response = await Client.PostAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<T> PostRequestAsync<T>(string route)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(Configuration.ApiKey))
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddHeader("Authorization", $"token {Configuration.ApiKey}");
|
||||
|
||||
var response = await Client.PostAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<T> GetRequest<T>(string route)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(Configuration.ApiKey))
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddHeader("Authorization", $"token {Configuration.ApiKey}");
|
||||
|
||||
var response = await Client.GetAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<T> DeleteRequest<T>(string route)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(Configuration.ApiKey))
|
||||
return default;
|
||||
|
||||
var request = new RestRequest(route)
|
||||
.AddHeader("Authorization", $"token {Configuration.ApiKey}");
|
||||
|
||||
var response = await Client.DeleteAsync<T>(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
LANCommander/UI/Pages/Settings/VPN/Forms/ZeroTier.razor
Normal file
28
LANCommander/UI/Pages/Settings/VPN/Forms/ZeroTier.razor
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
@using LANCommander.Models
|
||||
@using LANCommander.SDK.VPN.Configurations
|
||||
|
||||
<FormItem Label="Network ID">
|
||||
<Input @bind-Value="Configuration.NetworkId" />
|
||||
</FormItem>
|
||||
|
||||
@code {
|
||||
[Parameter] public string Value { get; set; } = "";
|
||||
[Parameter] public EventCallback<string> ValueChanged { get; set; }
|
||||
|
||||
[Parameter] public LANCommanderZeroTierSettings Configuration { get; set; } = new LANCommanderZeroTierSettings();
|
||||
[Parameter] public EventCallback<LANCommanderZeroTierSettings> ConfigurationChanged { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Configuration == null)
|
||||
{
|
||||
Configuration = new LANCommanderZeroTierSettings();
|
||||
await ConfigurationChanged.InvokeAsync(Configuration);
|
||||
}
|
||||
}
|
||||
|
||||
async Task Changed()
|
||||
{
|
||||
await ConfigurationChanged.InvokeAsync(Configuration);
|
||||
}
|
||||
}
|
||||
95
LANCommander/UI/Pages/Settings/VPN/Index.razor
Normal file
95
LANCommander/UI/Pages/Settings/VPN/Index.razor
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
@page "/Settings/VPN"
|
||||
@using LANCommander.SDK.VPN.Configurations
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using LANCommander.Models;
|
||||
@using LANCommander.Extensions
|
||||
@using LANCommander.SDK.Enums
|
||||
@layout SettingsLayout
|
||||
@inject SettingService SettingService
|
||||
@inject IMessageService MessageService
|
||||
@inject RoleManager<Role> RoleManager
|
||||
@attribute [Authorize(Roles = "Administrator")]
|
||||
|
||||
<PageHeader Title="VPN" />
|
||||
|
||||
<div style="padding: 0 24px;">
|
||||
<Form Model="Settings" Layout="@FormLayout.Vertical">
|
||||
<FormItem Label="Enable">
|
||||
<Switch @bind-Checked="context.VPN.Enabled" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label="Type">
|
||||
<Select @bind-Value="@context.VPN.Type" TItem="VPNType" TItemValue="VPNType" DataSource="Enum.GetValues<VPNType>()">
|
||||
<LabelTemplate Context="Value">@Value.GetDisplayName()</LabelTemplate>
|
||||
<ItemTemplate Context="Value">@Value.GetDisplayName()</ItemTemplate>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label="Allowed Roles">
|
||||
<Transfer DataSource="AllowedRolesTransferItems" TargetKeys="AllowedRolesTargetKeys" OnChange="OnChangeAllowedRoles" Titles="@(new string[] { "Available", "Allowed" })" />
|
||||
</FormItem>
|
||||
|
||||
@switch (context.VPN.Type)
|
||||
{
|
||||
case VPNType.ZeroTier:
|
||||
<LANCommander.UI.Pages.Settings.VPN.Forms.ZeroTier Configuration="context.VPN.Configuration as LANCommanderZeroTierSettings" ConfigurationChanged="config => context.VPN.Configuration = config" />
|
||||
break;
|
||||
}
|
||||
|
||||
<FormItem>
|
||||
<Button OnClick="Save" Type="@ButtonType.Primary">Save</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
LANCommanderSettings Settings;
|
||||
|
||||
ICollection<Role> Roles = new List<Role>();
|
||||
IEnumerable<TransferItem> AllowedRolesTransferItems { get; set; } = new List<TransferItem>();
|
||||
List<string> AllowedRolesTargetKeys { get; set; } = new List<string>();
|
||||
ICollection<Role> SelectedAllowedRoles = new List<Role>();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Settings = SettingService.GetSettings();
|
||||
Roles = await RoleManager.Roles.ToListAsync();
|
||||
|
||||
SelectedAllowedRoles = Roles.Where(r => Settings.VPN.AllowedRoles.Contains(r.Id)).ToList();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
AllowedRolesTransferItems = Roles.Select(r => new TransferItem()
|
||||
{
|
||||
Key = r.Id.ToString(),
|
||||
Title = r.Name
|
||||
});
|
||||
|
||||
if (SelectedAllowedRoles != null)
|
||||
AllowedRolesTargetKeys = SelectedAllowedRoles.Select(i => i.Id.ToString()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
async Task OnChangeAllowedRoles(TransferChangeArgs e)
|
||||
{
|
||||
SelectedAllowedRoles = Roles.Where(r => e.TargetKeys.Contains(r.Id.ToString())).ToList();
|
||||
|
||||
Settings.VPN.AllowedRoles = SelectedAllowedRoles.Select(r => r.Id);
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
SettingService.SaveSettings(Settings);
|
||||
MessageService.Success("Settings saved!");
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageService.Error("An unknown error occurred.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue