public string[] OnCall(ICommandSender sender, string[] args)
        {
            if (sender is Player admin)
            {
                if (!admin.HasPermission("scpdiscord.grantreservedslot"))
                {
                    return(new[] { "You don't have permission to use that command." });
                }
            }

            if (args.Length <= 0)
            {
                return(new[] { "Invalid arguments." });
            }

            if (ReservedSlot.GetSlots().Any(slot => slot.SteamID == args[0].Trim()))
            {
                return(new[] { "This user already has a reserved slot." });
            }

            try
            {
                Player player = SCPDiscord.plugin.Server.GetPlayers(args[0]).First();
                new ReservedSlot(player.IpAddress, player.SteamId, player.Name + ", added via SCPDiscord " + DateTime.Now).AppendToFile();
            }
            catch (InvalidOperationException)
            {
                new ReservedSlot("", args[0], "Offline player added via SCPDiscord " + DateTime.Now).AppendToFile();
            }
            return(new[] { "Reserved slot added." });
        }
Beispiel #2
0
        public async Task ReserveSlot(ReservedSlot slotReservation, Airplane airplane)
        {
            var isAvailable = await _slotRepository.IsSlotEmpty(slotReservation.SlotId);

            if (!isAvailable)
            {
                throw new SlotAlreadyReservedException();
            }

            await _slotRepository.SaveAirplaneToSlot(slotReservation, airplane);
        }
        public void ReserveSlot_WhenSlotAlreadyReserved_ThrowsSlotAlreadyReservedException()
        {
            var airplane = new Airplane();
            var slotId = It.IsAny<int>();
            var reservedSlot = new ReservedSlot { IsEmpty = true, Size = 1, SlotId = slotId, StartTime = DateTime.Now, ExpiryTime = DateTime.Now.AddHours(7) };
            _mockSlotRepository.Setup(r => r.IsSlotEmpty(slotId)).ReturnsAsync(false);
            var sut = new SlotService(_mockScoreProvider.Object, _mockSlotRepository.Object);

            Func<Task> result = async () => await sut.ReserveSlot(reservedSlot, airplane);

            result.Should().ThrowAsync<SlotAlreadyReservedException>();
        }
        public List <ReservedSlot> GetValidReservedSlotsByFacility(string facility)
        {
            var slots = new List <ReservedSlot>();
            var slot  = new ReservedSlot()
            {
                StartTime   = DateTime.Now,
                EndTime     = DateTime.Now.AddHours(3),
                Reservation = new Reservation(),
                Id          = 1,
                Facility    = "Test Facility"
            };

            slots.Add(slot);
            return(slots);
        }
        public string[] OnCall(ICommandSender sender, string[] args)
        {
            if (sender is Player player)
            {
                if (!player.HasPermission("scpdiscord.removereservedslot"))
                {
                    return(new[] { "You don't have permission to use that command." });
                }
            }

            if (args.Length <= 0)
            {
                return(new[] { "Invalid arguments." });
            }

            if (ReservedSlot.GetSlots().All(slot => slot.SteamID != args[0].Trim()))
            {
                return(new[] { "This user does not have a reserved slot." });
            }

            ReservedSlot.GetSlots().First(slot => slot.SteamID == args[0])?.RemoveSlotFromFile();

            return(new[] { "Reserved slot removed." });
        }
Beispiel #6
0
        private static void HandleConnection(ConnectionRequest request)
        {
            NetDataWriter rejectData = new NetDataWriter();

            try
            {
                byte result1;
                byte result2;
                int  position = request.Data.Position;
                if (!request.Data.TryGetByte(out result1) || !request.Data.TryGetByte(out result2) || result1 != CustomNetworkManager.Major || result2 != CustomNetworkManager.Minor)
                {
                    rejectData.Reset();
                    rejectData.Put(3);
                    request.Reject(rejectData);
                }
                else
                {
                    if (CustomLiteNetLib4MirrorTransport.IpRateLimiting)
                    {
                        if (CustomLiteNetLib4MirrorTransport.IpRateLimit.Contains(request.RemoteEndPoint.Address.ToString()))
                        {
                            ServerConsole.AddLog(string.Format("Incoming connection from endpoint {0} rejected due to exceeding the rate limit.", request.RemoteEndPoint));
                            ServerLogs.AddLog(ServerLogs.Modules.Networking, string.Format("Incoming connection from endpoint {0} rejected due to exceeding the rate limit.", request.RemoteEndPoint), ServerLogs.ServerLogType.RateLimit);
                            rejectData.Reset();
                            rejectData.Put(12);
                            request.Reject(rejectData);
                            return;
                        }
                        CustomLiteNetLib4MirrorTransport.IpRateLimit.Add(request.RemoteEndPoint.Address.ToString());
                    }
                    if (!CharacterClassManager.OnlineMode)
                    {
                        KeyValuePair <BanDetails, BanDetails> keyValuePair = BanHandler.QueryBan(null, request.RemoteEndPoint.Address.ToString());
                        if (keyValuePair.Value != null)
                        {
                            ServerConsole.AddLog(string.Format("Player tried to connect from banned endpoint {0}.", request.RemoteEndPoint));
                            rejectData.Reset();
                            rejectData.Put(6);
                            rejectData.Put(keyValuePair.Value.Expires);
                            rejectData.Put(keyValuePair.Value?.Reason ?? string.Empty);
                            request.Reject(rejectData);
                        }
                        else
                        {
                            request.Accept();
                        }
                    }
                    else
                    {
                        string result3;
                        if (!request.Data.TryGetString(out result3) || result3 == string.Empty)
                        {
                            rejectData.Reset();
                            rejectData.Put(5);
                            request.Reject(rejectData);
                        }
                        else
                        {
                            ulong  result4;
                            byte   result5;
                            string result6;
                            byte[] result7;
                            if (!request.Data.TryGetULong(out result4) || !request.Data.TryGetByte(out result5) || !request.Data.TryGetString(out result6) || !request.Data.TryGetBytesWithLength(out result7))
                            {
                                rejectData.Reset();
                                rejectData.Put(4);
                                request.Reject(rejectData);
                            }
                            else
                            {
                                CentralAuthPreauthFlags flags = (CentralAuthPreauthFlags)result5;
                                try
                                {
                                    if (!ECDSA.VerifyBytes(string.Format("{0};{1};{2};{3}", result3, result5, result6, result4), result7, ServerConsole.PublicKey))
                                    {
                                        ServerConsole.AddLog(string.Format("Player from endpoint {0} sent preauthentication token with invalid digital signature.", request.RemoteEndPoint));
                                        rejectData.Reset();
                                        rejectData.Put(2);
                                        request.Reject(rejectData);
                                    }
                                    else if (TimeBehaviour.CurrentUnixTimestamp > result4)
                                    {
                                        ServerConsole.AddLog(string.Format("Player from endpoint {0} sent expired preauthentication token.", request.RemoteEndPoint));
                                        ServerConsole.AddLog("Make sure that time and timezone set on server is correct. We recommend synchronizing the time.");
                                        rejectData.Reset();
                                        rejectData.Put(11);
                                        request.Reject(rejectData);
                                    }
                                    else
                                    {
                                        if (CustomLiteNetLib4MirrorTransport.UserRateLimiting)
                                        {
                                            if (CustomLiteNetLib4MirrorTransport.UserRateLimit.Contains(result3))
                                            {
                                                ServerConsole.AddLog(string.Format("Incoming connection from {0} ({1}) rejected due to exceeding the rate limit.", result3, request.RemoteEndPoint));
                                                ServerLogs.AddLog(ServerLogs.Modules.Networking, string.Format("Incoming connection from endpoint {0} ({1}) rejected due to exceeding the rate limit.", result3, request.RemoteEndPoint), ServerLogs.ServerLogType.RateLimit);
                                                rejectData.Reset();
                                                rejectData.Put(12);
                                                request.Reject(rejectData);
                                                return;
                                            }
                                            CustomLiteNetLib4MirrorTransport.UserRateLimit.Add(result3);
                                        }
                                        if (!flags.HasFlagFast(CentralAuthPreauthFlags.IgnoreBans) || !ServerStatic.GetPermissionsHandler().IsVerified)
                                        {
                                            KeyValuePair <BanDetails, BanDetails> keyValuePair = BanHandler.QueryBan(result3, request.RemoteEndPoint.Address.ToString());
                                            if (keyValuePair.Key != null || keyValuePair.Value != null)
                                            {
                                                ServerConsole.AddLog(string.Format("{0} {1} tried to connect from {2} endpoint {3}.", keyValuePair.Key == null ? "Player" : "Banned player", result3, keyValuePair.Value == null ? "" : "banned ", request.RemoteEndPoint));
                                                ServerLogs.AddLog(ServerLogs.Modules.Networking, string.Format("{0} {1} tried to connect from {2} endpoint {3}.", keyValuePair.Key == null ? "Player" : "Banned player", result3, keyValuePair.Value == null ? "" : "banned ", request.RemoteEndPoint), ServerLogs.ServerLogType.ConnectionUpdate);
                                                rejectData.Reset();
                                                rejectData.Put(6);
                                                NetDataWriter netDataWriter1 = rejectData;
                                                BanDetails    key            = keyValuePair.Key;
                                                netDataWriter1.Put(key != null ? key.Expires : keyValuePair.Value.Expires);
                                                NetDataWriter netDataWriter2 = rejectData;
                                                string        str;
                                                if ((str = keyValuePair.Key?.Reason) == null)
                                                {
                                                    str = keyValuePair.Value?.Reason ?? string.Empty;
                                                }
                                                netDataWriter2.Put(str);
                                                request.Reject(rejectData);
                                                return;
                                            }
                                        }
                                        if (flags.HasFlagFast(CentralAuthPreauthFlags.GloballyBanned) && !ServerStatic.GetPermissionsHandler().IsVerified)
                                        {
                                            bool useGlobalBans = CustomLiteNetLib4MirrorTransport.UseGlobalBans;
                                        }
                                        if ((!flags.HasFlagFast(CentralAuthPreauthFlags.IgnoreWhitelist) || !ServerStatic.GetPermissionsHandler().IsVerified) && !WhiteList.IsWhitelisted(result3))
                                        {
                                            ServerConsole.AddLog(string.Format("Player {0} tried joined from endpoint {1}, but is not whitelisted.", result3, request.RemoteEndPoint));
                                            rejectData.Reset();
                                            rejectData.Put(7);
                                            request.Reject(rejectData);
                                        }
                                        else if (CustomLiteNetLib4MirrorTransport.Geoblocking != GeoblockingMode.None && (!flags.HasFlagFast(CentralAuthPreauthFlags.IgnoreGeoblock) || !ServerStatic.GetPermissionsHandler().BanTeamBypassGeo) && (!CustomLiteNetLib4MirrorTransport.GeoblockIgnoreWhitelisted || !WhiteList.IsOnWhitelist(result3)) && (CustomLiteNetLib4MirrorTransport.Geoblocking == GeoblockingMode.Whitelist && !CustomLiteNetLib4MirrorTransport.GeoblockingList.Contains(result6.ToUpper()) || CustomLiteNetLib4MirrorTransport.Geoblocking == GeoblockingMode.Blacklist && CustomLiteNetLib4MirrorTransport.GeoblockingList.Contains(result6.ToUpper())))
                                        {
                                            ServerConsole.AddLog(string.Format("Player {0} ({1}) tried joined from blocked country {2}.", result3, request.RemoteEndPoint, result6.ToUpper()));
                                            rejectData.Reset();
                                            rejectData.Put(9);
                                            request.Reject(rejectData);
                                        }
                                        else
                                        {
                                            int num = CustomNetworkManager.slots;
                                            if (flags.HasFlagFast(CentralAuthPreauthFlags.ReservedSlot) && ServerStatic.GetPermissionsHandler().BanTeamSlots)
                                            {
                                                num = LiteNetLib4MirrorNetworkManager.singleton.maxConnections;
                                            }
                                            else if (ConfigFile.ServerConfig.GetBool("use_reserved_slots", true) && ReservedSlot.HasReservedSlot(result3))
                                            {
                                                num += CustomNetworkManager.reservedSlots;
                                            }
                                            if (LiteNetLib4MirrorCore.Host.PeersCount < num)
                                            {
                                                if (CustomLiteNetLib4MirrorTransport.UserIds.ContainsKey(request.RemoteEndPoint))
                                                {
                                                    CustomLiteNetLib4MirrorTransport.UserIds[request.RemoteEndPoint].SetUserId(result3);
                                                }
                                                else
                                                {
                                                    CustomLiteNetLib4MirrorTransport.UserIds.Add(request.RemoteEndPoint, new PreauthItem(result3));
                                                }
                                                bool allow = true;
                                                Events.InvokePreAuth(result3, request, position, result5, result6, ref allow);
                                                if (allow)
                                                {
                                                    request.Accept();
                                                    ServerConsole.AddLog(string.Format("Player {0} preauthenticated from endpoint {1}.", result3, request.RemoteEndPoint));
                                                    ServerLogs.AddLog(ServerLogs.Modules.Networking, string.Format("{0} preauthenticated from endpoint {1}.", result3, request.RemoteEndPoint), ServerLogs.ServerLogType.ConnectionUpdate);
                                                }
                                                else
                                                {
                                                    ServerConsole.AddLog(string.Format("Player {0} tried to preauthenticate from endpoint {1}, but the request has been rejected by a plugin.", result3, request.RemoteEndPoint));
                                                    ServerLogs.AddLog(ServerLogs.Modules.Networking, string.Format("{0} tried to preauthenticate from endpoint {1}, but the request has been rejected by a plugin.", result3, request.RemoteEndPoint), ServerLogs.ServerLogType.ConnectionUpdate);
                                                }
                                            }
                                            else
                                            {
                                                rejectData.Reset();
                                                rejectData.Put(1);
                                                request.Reject(rejectData);
                                            }
                                        }
                                    }
                                }
                                catch (Exception exception)
                                {
                                    ServerConsole.AddLog(string.Format("Player from endpoint {0} sent an invalid preauthentication token. {1}", request.RemoteEndPoint, exception.Message));
                                    rejectData.Reset();
                                    rejectData.Put(2);
                                    request.Reject(rejectData);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                ServerConsole.AddLog(string.Format("Player from endpoint {0} failed to preauthenticate: {1}", request.RemoteEndPoint, exception.Message));
                rejectData.Reset();
                rejectData.Put(4);
                request.Reject(rejectData);
            }
        }
Beispiel #7
0
 public Task SaveAirplaneToSlot(ReservedSlot slot, Airplane airplane)
 {
     throw new System.NotImplementedException();
 }
Beispiel #8
0
        public static void HandleCommand(JObject o)
        {
            try
            {
                string type = (string)o["type"];
                if (type == "IDENT")
                {
                    if ((string)o["data"] == "PASS")
                    {
                        Log.Debug($"Server {ServerConsole.Port} passed identification.");
                    }
                    else if ((string)o["data"] == "FAIL")
                    {
                        Log.Warn($"Server {ServerConsole.Port} failed identification.");
                    }
                }
                else if (type == "UPDATE")
                {
                    EventHandlers.tcp.SendData(new Update());
                }
                else if (type == "ROLESYNC")
                {
                    Log.Warn(o);

                    string userid = (string)o["userid"];

                    if (o["group"] == null)
                    {
                        Log.Debug($"No role sync found for {userid}");
                        SCPDiscord.VerifyReservedSlot(userid);
                        return;
                    }

                    string group = (string)o["group"];

                    UserGroup userGroup = ServerStatic.PermissionsHandler.GetGroup(group);
                    if (userGroup == null)
                    {
                        Log.Error($"Attempted to assign invalid user group {group} to {userid}");
                        return;
                    }

                    Player player = Player.Get(userid);
                    if (player == null)
                    {
                        Log.Error($"Error assigning user group to {userid}, player not found.");
                        return;
                    }

                    if (SCPDiscord.setRoleGroups.Contains(group))
                    {
                        Log.Debug($"Assigning role: {userGroup} to {userid}.");
                        player.Group = userGroup;
                    }

                    string tag = (string)o["tag"];
                    if (SCPDiscord.setTagGroups.Contains(group) && tag != null)
                    {
                        Log.Debug($"Changing tag of {userid} to {tag}.");
                        player.RankName = tag;
                    }

                    if (SCPDiscord.reservedSlotGroups.Contains(group))
                    {
                        // grant reserved slot
                        Log.Debug("Player has necessary rank for reserved slot, checking...");
                        List <string> lines = File.ReadAllLines(SCPDiscord.reservedSlots).ToList();
                        if (!lines.Contains(userid))
                        {
                            Log.Debug("Reserved slot not found, adding player...");
                            lines.Add(userid);
                            File.WriteAllLines(SCPDiscord.reservedSlots, lines);
                            // This only reloads the slots on the current server, change this to reload on every server?
                            // Might not work
                            ReservedSlot.Reload();
                        }
                    }
                    else
                    {
                        SCPDiscord.VerifyReservedSlot(userid);
                    }
                }
                else if (type == "COMMAND")
                {
                    GameCore.Console.singleton.TypeCommand((string)o["command"]);
                }
                else if (type == "BAN")
                {
                    bool   isuid = false;
                    string uid   = (string)o["user"];
                    if (!uid.Contains("@steam") && !uid.Contains("@discord"))
                    {
                        if (!uid.Contains("."))
                        {
                            isuid = true;
                            uid  += "@steam";
                        }
                    }
                    else
                    {
                        isuid = true;
                    }
                    Player player = Player.Get(uid);
                    int    min    = (int)o["min"];
                    string reason = (string)o["reason"];

                    Ban ban = new Ban
                    {
                        player   = null,
                        duration = min,
                        success  = true,
                        offline  = false
                    };

                    if (player != null)
                    {
                        PlayerManager.localPlayer.GetComponent <BanPlayer>().BanUser(player.GameObject, min, reason, "Server");

                        ban.player = new User
                        {
                            name   = player.Nickname,
                            userid = player.UserId
                        };
                    }
                    else
                    {
                        if (isuid)
                        {
                            ban.offline = true;

                            ban.player = new User
                            {
                                name   = "Offline Player",
                                userid = uid
                            };

                            if (SCPDiscord.instance.Config.SteamApiKey != string.Empty)
                            {
                                string data = null;
                                try
                                {
                                    data = webclient.DownloadString($"https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key={SCPDiscord.instance.Config.SteamApiKey}&format=json&steamids={uid.Replace("@steam", "")}");
                                }
                                catch
                                {
                                    Log.Debug("Failed to get profile data from SteamAPI.");
                                }
                                JObject o2 = JObject.Parse(data);

                                if (o2 != null)
                                {
                                    ban.player.name = (string)o2["response"]["players"][0]["personaname"];
                                }
                            }

                            BanHandler.IssueBan(new BanDetails()
                            {
                                OriginalName = ban.player.name,
                                Id           = uid,
                                IssuanceTime = TimeBehaviour.CurrentTimestamp(),
                                Expires      = DateTime.UtcNow.AddMinutes((double)min).Ticks,
                                Reason       = reason,
                                Issuer       = "Server"
                            }, BanHandler.BanType.UserId);
                        }
                        else if (uid.Contains("."))
                        {
                            ban.offline = true;

                            BanHandler.IssueBan(new BanDetails()
                            {
                                OriginalName = "IP Address",
                                Id           = uid,
                                IssuanceTime = TimeBehaviour.CurrentTimestamp(),
                                Expires      = DateTime.UtcNow.AddMinutes((double)min).Ticks,
                                Reason       = reason,
                                Issuer       = "Server"
                            }, BanHandler.BanType.IP);
                        }
                        else
                        {
                            ban.success = false;
                        }
                    }
                    EventHandlers.tcp.SendData(ban);
                }
                else if (type == "KICK")
                {
                    string uid = (string)o["user"];
                    if (!uid.Contains("@steam") && !uid.Contains("@discord"))
                    {
                        uid += "@steam";
                    }
                    Player player = Player.Get(uid);

                    Kick kick = new Kick
                    {
                        player = null
                    };

                    if (player != null)
                    {
                        kick.player = new User
                        {
                            name   = player.Nickname,
                            userid = player.UserId
                        };

                        ServerConsole.Disconnect(player.GameObject, (string)o["reason"]);
                    }
                    EventHandlers.tcp.SendData(kick);
                }
                else if (type == "UNBAN")
                {
                    Unban unban = new Unban();

                    List <string> ipBans     = File.ReadAllLines(SCPDiscord.ipBans).ToList();
                    List <string> userIDBans = File.ReadAllLines(SCPDiscord.useridBans).ToList();

                    string id = (string)o["user"];
                    if (!id.Contains("."))
                    {
                        if (!id.Contains("@steam") && !id.Contains("@discord"))
                        {
                            id += "@steam";
                        }
                    }
                    List <string> matchingIPBans      = ipBans.FindAll(s => s.Contains(id));
                    List <string> matchingSteamIDBans = userIDBans.FindAll(s => s.Contains(id));

                    if (matchingIPBans.Count == 0 && matchingSteamIDBans.Count == 0)
                    {
                        unban.success = false;
                        EventHandlers.tcp.SendData(unban);
                        return;
                    }

                    ipBans.RemoveAll(s => s.Contains(id));
                    userIDBans.RemoveAll(s => s.Contains(id));

                    foreach (var row in matchingIPBans)
                    {
                        userIDBans.RemoveAll(s => s.Contains(row.Split(';').Last()));
                    }
                    foreach (var row in matchingSteamIDBans)
                    {
                        ipBans.RemoveAll(s => s.Contains(row.Split(';').Last()));
                    }

                    File.WriteAllLines(SCPDiscord.ipBans, ipBans);
                    File.WriteAllLines(SCPDiscord.useridBans, userIDBans);

                    EventHandlers.tcp.SendData(unban);
                }
            }
            catch (Exception x)
            {
                Log.Error("SCPDiscord handle command error: " + x.Message);
            }
        }
 public static ReservedSlot[] GetPatronSlots()
 {
     return(ReservedSlot.GetSlots().Where(slot => !string.IsNullOrEmpty(slot.Comment) && slot.Comment.Trim().StartsWith(SlotCommentPrefix)).ToArray());
 }
 public static bool ReservedSlotsContains(string steamId)
 {
     return(ReservedSlot.GetSlots().Any(slot => slot.SteamID == steamId.Trim()));
 }
Beispiel #11
0
        public static void RemoveReservedSlot([NotNull] Player player)
        {
            ReservedSlot slot = GetPluginReservedSlot(player.SteamId);

            slot?.RemoveSlotFromFile();
        }
Beispiel #12
0
 public static ReservedSlot GetReservedSlot(string steamId)
 {
     return(ReservedSlot.GetSlots().FirstOrDefault(slot => slot.SteamID == steamId.Trim()));
 }