Пример #1
0
        public static Scaffold.Command JsonToModel(JSON.Command command, short worldId, int accessGroupId, Scaffold.Command existingCommand, DateTime currentTime, Scaffold.VaultContext context = null)
        {
            if (command == null)
            {
                if (existingCommand != null && context != null)
                {
                    context.Remove(existingCommand);
                }

                return(null);
            }

            Scaffold.Command result;
            if (existingCommand != null)
            {
                result = existingCommand;
            }
            else
            {
                result               = new Scaffold.Command();
                result.CommandId     = command.CommandId.Value;
                result.WorldId       = worldId;
                result.AccessGroupId = accessGroupId;
                if (context != null)
                {
                    context.Add(result);
                }
            }

            result.CommandId       = command.CommandId.Value;
            result.UserLabel       = result.UserLabel ?? command.UserLabel;  // Don't overwrite existing labels
            result.SourcePlayerId  = command.SourcePlayerId.Value;
            result.SourceVillageId = command.SourceVillageId.Value;
            result.TargetPlayerId  = command.TargetPlayerId;
            result.TargetVillageId = command.TargetVillageId.Value;
            result.LandsAt         = command.LandsAt.Value;
            result.FirstSeenAt     = result.FirstSeenAt == DateTime.MinValue ? currentTime : result.FirstSeenAt;
            result.IsAttack        = command.CommandType == JSON.CommandType.Attack;
            result.IsReturning     = command.IsReturning.Value;

            result.Army = ArmyConvert.JsonToArmy(command.Troops, worldId, result.Army, context);

            if (result.TroopType == null)
            {
                result.TroopType = TroopTypeConvert.TroopTypeToString(command.TroopType);
            }
            else if (command.TroopType != null)
            {
                var currentType = result.TroopType.ToTroopType();
                var updatedType = command.TroopType.Value;

                if (Native.ArmyStats.TravelSpeed[currentType] < Native.ArmyStats.TravelSpeed[updatedType])
                {
                    result.TroopType = updatedType.ToTroopString();
                }
            }

            return(result);
        }
Пример #2
0
        public static Scaffold.ReportBuilding JsonToReportBuilding(JSON.BuildingLevels buildingLevels, short worldId, Scaffold.ReportBuilding existingBuildings = null, Scaffold.VaultContext context = null)
        {
            if (buildingLevels == null || buildingLevels.Count == 0)
            {
                if (existingBuildings != null && context != null)
                {
                    context.Remove(existingBuildings);
                }

                return(null);
            }

            Scaffold.ReportBuilding result;
            if (existingBuildings != null)
            {
                result = existingBuildings;
            }
            else
            {
                result         = new Scaffold.ReportBuilding();
                result.WorldId = worldId;
                context.Add(result);
            }

            result.Barracks   = GetOrNull(buildingLevels, "barracks");
            result.Church     = GetOrNull(buildingLevels, "church");
            result.Farm       = GetOrNull(buildingLevels, "farm");
            result.Garage     = GetOrNull(buildingLevels, "garage");
            result.Hide       = GetOrNull(buildingLevels, "hide");
            result.Iron       = GetOrNull(buildingLevels, "iron");
            result.Main       = GetOrNull(buildingLevels, "main");
            result.Market     = GetOrNull(buildingLevels, "market");
            result.Place      = GetOrNull(buildingLevels, "place");
            result.Smith      = GetOrNull(buildingLevels, "smith");
            result.Snob       = GetOrNull(buildingLevels, "snob");
            result.Stable     = GetOrNull(buildingLevels, "stable");
            result.Statue     = GetOrNull(buildingLevels, "statue");
            result.Stone      = GetOrNull(buildingLevels, "stone");
            result.Storage    = GetOrNull(buildingLevels, "storage");
            result.Wall       = GetOrNull(buildingLevels, "wall");
            result.Watchtower = GetOrNull(buildingLevels, "watchtower");
            result.Wood       = GetOrNull(buildingLevels, "wood");

            // ?
            //result.FirstChurch = GetOrNull(buildingLevels, "First church");

            return(result);
        }
Пример #3
0
        public ActionResult Post([FromBody] UserInfo userInfo)
        {
            var world = context.World.Where(w => w.Id == userInfo.WorldId).SingleOrDefault();

            if (world == null)
            {
                return(Ok(new { error = "No world exists with that id" }));
            }

            var encodedPlayerName = userInfo.Name.UrlEncode();
            var player            = context.Player.Where(p => p.WorldId == userInfo.WorldId && p.PlayerName == encodedPlayerName).SingleOrDefault();

            if (player == null)
            {
                return(Ok(new { error = $"No user exists with that name on world {world.Hostname} (Name is Case-Sensitive).\n\nIf you just registered, you'll need to wait up to 60 minutes for the world data to refresh." }));
            }

            var remoteIp = HttpContext.Connection.RemoteIpAddress;

            try
            {
                var captchaPrivateKey = Configuration.Instance["CaptchaSecretKey"];
                var captchaUrl        = $"https://www.google.com/recaptcha/api/siteverify?secret={captchaPrivateKey}&response={userInfo.CaptchaToken}&remoteip={remoteIp}";
                var captchaRequest    = (HttpWebRequest)WebRequest.Create(captchaUrl);
                using (var response = captchaRequest.GetResponse())
                    using (var stream = new StreamReader(response.GetResponseStream()))
                    {
                        var responseObject = JObject.Parse(stream.ReadToEnd());
                        var success        = responseObject.Value <bool>("success");
                        if (!success)
                        {
                            var errorCodes = responseObject.GetValue("error-codes").Values <string>();
                            logger.LogWarning("Got error codes from captcha when verifying for remote IP {0}: [{1}]", remoteIp, string.Join(", ", errorCodes));
                            return(Ok(new { error = "Captcha verification failed" }));
                        }
                    }
            }
            catch (Exception e)
            {
                logger.LogError("Captcha error occured: {ex}", e);
                return(Ok(new { error = "An error occurred while verifying captcha" }));
            }

            var tx = new Scaffold.Transaction
            {
                OccurredAt = DateTime.UtcNow,
                WorldId    = world.Id,
                Ip         = remoteIp
            };

            context.Add(tx);

            var accessGroup = new Scaffold.AccessGroup();

            accessGroup.WorldId = userInfo.WorldId;
            accessGroup.Label   = userInfo.Name;
            context.AccessGroup.Add(accessGroup);
            context.SaveChanges();

            var authToken = Guid.NewGuid();
            var user      = new Scaffold.User
            {
                AccessGroupId    = accessGroup.Id,
                WorldId          = (short)userInfo.WorldId,
                PlayerId         = player.PlayerId,
                Enabled          = true,
                PermissionsLevel = 2,
                AuthToken        = authToken,
                TransactionTime  = DateTime.UtcNow,
                Label            = $"{world.Name} - {userInfo.Name}",
                Tx = tx
            };

            context.User.Add(user);

            context.SaveChanges();

            logger.LogInformation("Creating user for {0} on world {1} from {2}", player.PlayerName, world.Hostname, remoteIp);

            return(Ok(new { token = authToken.ToString() }));
        }
Пример #4
0
        private static T JsonToArmy <T>(JSON.Army armyCounts, short worldId, T existingArmy = null, Scaffold.VaultContext context = null, bool emptyIfNull = false) where T : class, new()
        {
            if (Object.ReferenceEquals(armyCounts, null))
            {
                if (emptyIfNull)
                {
                    armyCounts = JSON.Army.Empty;
                }
                else
                {
                    if (existingArmy != null && context != null)
                    {
                        context.Remove(existingArmy);
                    }

                    return(null);
                }
            }

            T result;

            if (existingArmy != null)
            {
                result = existingArmy;
            }
            else
            {
                result = new T();
            }

            var scaffoldArmyType = typeof(T);

            foreach (var troopType in Enum.GetValues(typeof(JSON.TroopType)).Cast <JSON.TroopType>())
            {
                var troopCount    = GetOrNull(armyCounts, troopType);
                var troopProperty = scaffoldArmyType.GetProperty(troopType.ToString(), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                var currentCount  = (int?)troopProperty.GetValue(result);

                if (currentCount == troopCount)
                {
                    continue;
                }

                if (typeof(short?).IsAssignableFrom(troopProperty.PropertyType))
                {
                    troopProperty.SetValue(result, troopCount?.ToShort());
                }
                else
                {
                    troopProperty.SetValue(result, troopCount);
                }
            }

            var worldIdProperty = scaffoldArmyType.GetProperty("WorldId", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

            if (worldIdProperty != null)
            {
                worldIdProperty.SetValue(result, worldId);
            }

            if (existingArmy == null && context != null)
            {
                context.Add(result);
            }

            return(result);
        }
Пример #5
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var failedAuthMessage = $"Say hello to our log files, Mr. or Ms. {context.HttpContext.Connection.RemoteIpAddress.ToString()}";

            AuthHeaders authHeaders = null;

            authHeaders = AuthenticationUtil.ParseHeaders(context.HttpContext.Request.Headers);

            if (!authHeaders.IsValid)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = "Invalid authentication headers: ";
                var exactReasons = new List <String>();
                if (authHeaders.AuthToken == null)
                {
                    exactReasons.Add("AuthToken missing or invalid");
                }
                if (authHeaders.PlayerId == null)
                {
                    exactReasons.Add("PlayerId missing or invalid");
                }
                if (authHeaders.TribeId == null)
                {
                    exactReasons.Add("TribeId missing or invalid");
                }

                failedRequest.Reason += String.Join(", ", exactReasons);

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);

                context.Result = new ContentResult {
                    Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                };
                return;
            }

            var requestedWorld = context.RouteData.Values["worldName"] as String;

            if (requestedWorld == null)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = "Attempted to request a protected endpoint without worldName [programmer error]";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);

                context.Result = new StatusCodeResult(401);
                return;
            }

            var world = dbContext.World.Where(w => w.Name == requestedWorld).FirstOrDefault();

            if (world == null)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = "Attempted to request a protected endpoint for a world that does not exist";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);

                context.Result = new StatusCodeResult(401);
                return;
            }

            var authToken      = authHeaders.AuthToken;
            var discoveredUser = (
                from user in dbContext.User
                where user.AuthToken == authToken && (user.WorldId == null || user.WorldId == world.Id)
                select user
                ).FirstOrDefault();

            if (discoveredUser == null || !discoveredUser.Enabled)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                if (discoveredUser == null)
                {
                    failedRequest.Reason = $"No user found with given token: '{authToken}'";
                    context.Result       = new ContentResult {
                        Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                    };
                }
                else
                {
                    var disablingEvent = dbContext.UserLog.Where(u => u.Id == discoveredUser.Uid).OrderByDescending(l => l.TransactionTime).FirstOrDefault();
                    var disablingAdmin = disablingEvent?.AdminPlayerId == null
                        ? null
                        : dbContext.Player.Where(p => p.PlayerId == disablingEvent.AdminPlayerId.Value).FirstOrDefault();

                    failedRequest.Reason = "Requested by disabled user";
                    context.Result       = new ContentResult
                    {
                        Content = JsonConvert.SerializeObject(new
                        {
                            Enabled    = false,
                            DisabledBy = disablingAdmin?.PlayerName ?? "Unknown",
                            DisabledAt = disablingEvent?.TransactionTime
                        }),
                        ContentType = MediaTypeNames.Application.Json,
                        StatusCode  = 401
                    };
                }

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);
                return;
            }

            if (discoveredUser.PlayerId != authHeaders.PlayerId.Value)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = $"Player ID {authHeaders.PlayerId.Value} did not match the player ID associated with for token, got PID {discoveredUser.PlayerId}";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();
                context.Result = new ContentResult {
                    Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                };
                return;
            }

            if (discoveredUser.PermissionsLevel < Configuration.Security.MinimumRequiredPriveleges)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = $"User privileges '{discoveredUser.PermissionsLevel}' was less than the minimum '{Configuration.Security.MinimumRequiredPriveleges}'";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();
                context.Result = new ContentResult {
                    Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                };
                return;
            }

            context.HttpContext.Items["UserId"]       = discoveredUser.Uid;
            context.HttpContext.Items["UserIsSitter"] = authHeaders.IsSitter;

            context.HttpContext.Items["UserPermissions"] =
                authHeaders.IsSitter && Configuration.Security.RestrictSitterAccess
                    ? (short)PermissionLevel.Default
                    : discoveredUser.PermissionsLevel;

            context.HttpContext.Items["PlayerId"]      = authHeaders.PlayerId.Value;
            context.HttpContext.Items["TribeId"]       = authHeaders.TribeId.Value;
            context.HttpContext.Items["AuthToken"]     = authHeaders.AuthToken.Value;
            context.HttpContext.Items["AccessGroupId"] = discoveredUser.AccessGroupId;

            context.HttpContext.Items["User"] = discoveredUser;
        }