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." }); }
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." }); }
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); } }
public Task SaveAirplaneToSlot(ReservedSlot slot, Airplane airplane) { throw new System.NotImplementedException(); }
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())); }
public static void RemoveReservedSlot([NotNull] Player player) { ReservedSlot slot = GetPluginReservedSlot(player.SteamId); slot?.RemoveSlotFromFile(); }
public static ReservedSlot GetReservedSlot(string steamId) { return(ReservedSlot.GetSlots().FirstOrDefault(slot => slot.SteamID == steamId.Trim())); }