示例#1
0
        public async Task <int> Handle(CreateClientCommand command, CancellationToken cancellationToken)
        {
            var server = await _context.Servers.AsNoTracking().SingleOrDefaultAsync(x => x.Id == command.ServerId, cancellationToken);

            if (server == null)
            {
                throw new NullReferenceException($"A server with id #{command.ServerId} could not be found.");
            }

            // Ensure client is unique
            await _clientValidator.EnsureUniqueClientOnCreate(
                command.Client.Name,
                command.Client.AssignedIp,
                command.ServerId,
                command.Client.IsIpAutoGenerated == true,
                cancellationToken
                );

            var network = IPNetwork.Parse($"{server.AssignedRange.addr}/{server.AssignedRange.cidr}");

            // Handle IP address
            if (command.Client.IsIpAutoGenerated == true)
            {
                // Get a list of all usable addresses
                var available = network.ListIPAddress(FilterEnum.Usable).ToList();
                available.Remove(network.FirstUsable);

                var addresses = await _context.Clients
                                .AsNoTracking()
                                .Where(x => x.ServerId == command.ServerId)
                                .Select(x => x.AssignedIp)
                                .ToListAsync();

                // Remove the ones that are in use
                foreach (var addr in addresses)
                {
                    available.Remove(addr.addr);
                }

                // Grab the first remaining one
                command.Client.AssignedIp = $"{available.First()}/32";
            }
            else
            {
                // Check that assigned IP is in range
                var isInRange = network.Contains(command.Client.AssignedIp.ToAddress().addr);
                if (!isInRange)
                {
                    throw new ArgumentException($"Assigned IP address was not in range {server.AssignedRange.addr}/{server.AssignedRange.cidr}");
                }
            }

            var client = new WireguardClient
            {
                Name        = command.Client.Name,
                Description = command.Client.Description,
                AssignedIp  = command.Client.AssignedIp.ToAddress(),
                IsRevoked   = command.Client.IsRevoked ?? false,
                PublicKey   = command.Client.PublicKey,
                ServerId    = command.ServerId
            };

            await _context.Clients.AddAsync(client, cancellationToken);

            await _context.SaveChangesAsync(cancellationToken);

            return(client.Id);
        }