Example #1
0
        private static bool ProcessNode(RightsRule rule, ExecuteContext ctx)
        {
            // check if node matches
            if (!rule.HasMatcher() ||
                (ctx.Host != null && rule.MatchHost.Contains(ctx.Host)) ||
                (ctx.ClientUid != null && rule.MatchClientUid.Contains(ctx.ClientUid)) ||
                (ctx.AvailableGroups.Length > 0 && rule.MatchClientGroupId.Overlaps(ctx.AvailableGroups)) ||
                (ctx.ChannelGroupId.HasValue && rule.MatchChannelGroupId.Contains(ctx.ChannelGroupId.Value)) ||
                (ctx.ApiToken != null && rule.MatchToken.Contains(ctx.ApiToken)) ||
                (ctx.IsApi == rule.MatchIsApi) ||
                (ctx.Visibiliy.HasValue && rule.MatchVisibility.Contains(ctx.Visibiliy.Value)))
            {
                bool hasMatchingChild = false;
                foreach (var child in rule.ChildrenRules)
                {
                    hasMatchingChild |= ProcessNode(child, ctx);
                }

                if (!hasMatchingChild)
                {
                    ctx.MatchingRules.Add(rule);
                }
                return(true);
            }
            return(false);
        }
Example #2
0
 public ParseContext(ISet <string> registeredRights)
 {
     Declarations     = new List <RightsDecl>();
     RootRule         = new RightsRule();
     Errors           = new List <string>();
     Warnings         = new List <string>();
     RegisteredRights = registeredRights;
 }
Example #3
0
 public ParseContext(ISet <string> registeredRights)
 {
     Declarations     = new List <RightsDecl>();
     RootRule         = new RightsRule();
     Errors           = new List <string>();
     Warnings         = new List <string>();
     RegisteredRights = registeredRights;
     Groups           = Array.Empty <RightsGroup>();
     Rules            = Array.Empty <RightsRule>();
 }
Example #4
0
        /// <summary>
        /// Sums up all includes and parent rule declarations for each rule and includes them
        /// directly into the <see cref="RightsDecl.DeclAdd"/> and <see cref="RightsDecl.DeclDeny"/>.
        /// </summary>
        /// <param name="root">The root element of the hierarchy tree.</param>
        private static void FlattenRules(RightsRule root)
        {
            if (root.Parent != null)
            {
                root.MergeGroups(root.Parent);
            }
            root.MergeGroups(root.Includes);
            root.Includes = null;

            foreach (var child in root.ChildrenRules)
            {
                FlattenRules(child);
            }
        }
Example #5
0
        private static bool ProcessNode(RightsRule rule, ExecuteContext ctx)
        {
            // check if node matches
            if (rule.Matches(ctx))
            {
                bool hasMatchingChild = false;
                foreach (var child in rule.ChildrenRules)
                {
                    hasMatchingChild |= ProcessNode(child, ctx);
                }

                if (!hasMatchingChild)
                {
                    ctx.MatchingRules.Add(rule);
                }
                return(true);
            }
            return(false);
        }
Example #6
0
        private void RecalculateRights(TomlTable table, ParseContext parseCtx)
        {
            rules = Array.Empty <RightsRule>();

            rootRule = new RightsRule();
            if (!rootRule.ParseChilden(table, parseCtx))
            {
                return;
            }

            parseCtx.SplitDeclarations();

            if (!ValidateUniqueGroupNames(parseCtx))
            {
                return;
            }

            if (!ResolveIncludes(parseCtx))
            {
                return;
            }

            if (!CheckCyclicGroupDependencies(parseCtx))
            {
                return;
            }

            BuildLevel(rootRule);

            LintDeclarations(parseCtx);

            if (!NormalizeRule(parseCtx))
            {
                return;
            }

            FlattenGroups(parseCtx);

            FlattenRules(rootRule);

            rules = parseCtx.Rules;
        }
Example #7
0
        private RightsRule TryGetRootSafe()
        {
            var localRootRule = rootRule;

            if (localRootRule != null && !needsRecalculation)
            {
                return(localRootRule);
            }

            lock (rootRuleLock)
            {
                if (rootRule != null && !needsRecalculation)
                {
                    return(rootRule);
                }

                rootRule = ReadFile();
                return(rootRule);
            }
        }
Example #8
0
        private void RecalculateRights(TomlTable table, ParseContext parseCtx)
        {
            Rules = new RightsRule[0];

            RootRule = new RightsRule();
            if (!RootRule.ParseChilden(table, parseCtx))
            {
                return;
            }

            parseCtx.SplitDeclarations();

            if (!ValidateUniqueGroupNames(parseCtx))
            {
                return;
            }

            if (!ResolveIncludes(parseCtx))
            {
                return;
            }

            if (!CheckCyclicGroupDependencies(parseCtx))
            {
                return;
            }

            BuildLevel(RootRule);

            LintDeclarations(parseCtx);

            SanitizeRules(parseCtx);

            FlattenGroups(parseCtx);

            FlattenRules(RootRule);

            Rules = parseCtx.Rules;
        }
Example #9
0
        public override bool ParseKey(string key, TomlObject tomlObj, ParseContext ctx)
        {
            if (base.ParseKey(key, tomlObj, ctx))
            {
                return(true);
            }

            switch (key)
            {
            case "host":
                var host = TomlTools.GetValues <string>(tomlObj);
                if (host == null)
                {
                    ctx.Errors.Add("<host> Field has invalid data.");
                }
                else
                {
                    MatchHost = new HashSet <string>(host);
                }
                return(true);

            case "groupid":
                var groupid = TomlTools.GetValues <ulong>(tomlObj);
                if (groupid == null)
                {
                    ctx.Errors.Add("<groupid> Field has invalid data.");
                }
                else
                {
                    MatchClientGroupId = new HashSet <ulong>(groupid);
                }
                return(true);

            case "channelgroupid":
                var cgroupid = TomlTools.GetValues <ulong>(tomlObj);
                if (cgroupid == null)
                {
                    ctx.Errors.Add("<channelgroupid> Field has invalid data.");
                }
                else
                {
                    MatchChannelGroupId = new HashSet <ulong>(cgroupid);
                }
                return(true);

            case "useruid":
                var useruid = TomlTools.GetValues <string>(tomlObj);
                if (useruid == null)
                {
                    ctx.Errors.Add("<useruid> Field has invalid data.");
                }
                else
                {
                    MatchClientUid = new HashSet <string>(useruid);
                }
                return(true);

            case "perm":
                var perm = TomlTools.GetValues <string>(tomlObj);
                if (perm == null)
                {
                    ctx.Errors.Add("<perm> Field has invalid data.");
                }
                else
                {
                    MatchPermission = new HashSet <string>(perm);
                }
                return(true);

            case "visibility":
                var visibility = TomlTools.GetValues <TextMessageTargetMode>(tomlObj);
                if (visibility == null)
                {
                    ctx.Errors.Add("<visibility> Field has invalid data.");
                }
                else
                {
                    MatchVisibility = visibility;
                }
                return(true);

            case "rule":
                if (tomlObj.TomlType == TomlObjectType.ArrayOfTables)
                {
                    var childTables = (TomlTableArray)tomlObj;
                    foreach (var childTable in childTables.Items)
                    {
                        var rule = new RightsRule();
                        Children.Add(rule);
                        rule.Parent = this;
                        rule.ParseChilden(childTable, ctx);
                    }
                    return(true);
                }
                else
                {
                    ctx.Errors.Add("Misused key with reserved name \"rule\".");
                    return(false);
                }

            default:
                // group
                if (key.StartsWith("$"))
                {
                    if (tomlObj.TomlType == TomlObjectType.Table)
                    {
                        var childTable = (TomlTable)tomlObj;
                        var group      = new RightsGroup(key);
                        Children.Add(group);
                        group.Parent = this;
                        group.ParseChilden(childTable, ctx);
                        return(true);
                    }
                    else
                    {
                        ctx.Errors.Add($"Misused key for group declaration: {key}.");
                    }
                }
                return(false);
            }
        }
Example #10
0
        public override bool ParseKey(string key, TomlObject tomlObj, ParseContext ctx)
        {
            if (base.ParseKey(key, tomlObj, ctx))
            {
                return(true);
            }

            switch (key)
            {
            case "host":
                if (tomlObj.TryGetValueArray <string>(out var host))
                {
                    Matcher.Add(new MatchHost(host));
                }
                else
                {
                    ctx.Errors.Add("<host> Field has invalid data.");
                }
                return(true);

            case "groupid":
                if (tomlObj.TryGetValueArray <ulong>(out var servergroupid))
                {
                    Matcher.Add(new MatchServerGroupId(servergroupid.Select(ServerGroupId.To)));
                }
                else
                {
                    ctx.Errors.Add("<groupid> Field has invalid data.");
                }
                return(true);

            case "channelgroupid":
                if (tomlObj.TryGetValueArray <ulong>(out var channelgroupid))
                {
                    Matcher.Add(new MatchChannelGroupId(channelgroupid.Select(ChannelGroupId.To)));
                }
                else
                {
                    ctx.Errors.Add("<channelgroupid> Field has invalid data.");
                }
                return(true);

            case "useruid":
                if (tomlObj.TryGetValueArray <string>(out var useruid))
                {
                    Matcher.Add(new MatchClientUid(useruid.Select(Uid.To)));
                }
                else
                {
                    ctx.Errors.Add("<useruid> Field has invalid data.");
                }
                return(true);

            case "perm":
                if (tomlObj.TryGetValueArray <string>(out var perm))
                {
                    Matcher.Add(new MatchPermission(perm, ctx));
                }
                else
                {
                    ctx.Errors.Add("<perm> Field has invalid data.");
                }
                return(true);

            case "apitoken":
                if (tomlObj.TryGetValueArray <string>(out var apitoken))
                {
                    Matcher.Add(new MatchToken(apitoken));
                }
                else
                {
                    ctx.Errors.Add("<apitoken> Field has invalid data.");
                }
                return(true);

            case "bot":
                if (tomlObj.TryGetValueArray <string>(out var bot))
                {
                    Matcher.Add(new MatchBot(bot));
                }
                else
                {
                    ctx.Errors.Add("<bot> Field has invalid data.");
                }
                return(true);

            case "isapi":
                if (tomlObj.TryGetValue <bool>(out var isapi))
                {
                    Matcher.Add(new MatchIsApi(isapi));
                }
                else
                {
                    ctx.Errors.Add("<isapi> Field has invalid data.");
                }
                return(true);

            case "ip":
                if (tomlObj.TryGetValueArray <string>(out var ip))
                {
                    Matcher.Add(new MatchApiCallerIp(ip.Select(x =>
                    {
                        if (IPAddress.TryParse(x, out var ipa))
                        {
                            return(ipa);
                        }
                        ctx.Errors.Add($"<ip> Field value '{x}' could not be parsed.");
                        return(null !);
                    }).Where(x => x != null)));
                }
                else
                {
                    ctx.Errors.Add("<ip> Field has invalid data.");
                }
                return(true);

            case "visibility":
                if (tomlObj.TryGetValueArray <TextMessageTargetMode>(out var visibility))
                {
                    Matcher.Add(new MatchVisibility(visibility));
                }
                else
                {
                    ctx.Errors.Add("<visibility> Field has invalid data.");
                }
                return(true);

            case "rule":
                if (tomlObj.TomlType == TomlObjectType.ArrayOfTables)
                {
                    var childTables = (TomlTableArray)tomlObj;
                    foreach (var childTable in childTables.Items)
                    {
                        var rule = new RightsRule();
                        Children.Add(rule);
                        rule.Parent = this;
                        rule.ParseChilden(childTable, ctx);
                    }
                    return(true);
                }
                else
                {
                    ctx.Errors.Add("Misused key with reserved name \"rule\".");
                    return(false);
                }

            default:
                // group
                if (key.StartsWith("$"))
                {
                    if (tomlObj.TomlType == TomlObjectType.Table)
                    {
                        var childTable = (TomlTable)tomlObj;
                        var group      = new RightsGroup(key);
                        Children.Add(group);
                        group.Parent = this;
                        group.ParseChilden(childTable, ctx);
                        return(true);
                    }
                    else
                    {
                        ctx.Errors.Add($"Misused key for group declaration: {key}.");
                    }
                }
                return(false);
            }
        }