Пример #1
0
        private void GotSubscribed(object sender, IQ iq, object state)
        {
            if (iq.Type != IQType.result)
            {
                FireError(Op.SUBSCRIBE, "Subscription failed", iq);
                return;
            }

            PubSub ps = iq.Query as PubSub;

            if (ps == null)
            {
                FireError(Op.SUBSCRIBE, "Invalid protocol", iq);
                return;
            }

            PubSubSubscriptionType subType;
            PubSubSubscription     sub = ps["subscription", URI.PUBSUB] as PubSubSubscription;

            if (sub != null)
            {
                subType = sub.Type;
            }
            else
            {
                XmlElement ent = ps["entity", URI.PUBSUB];
                if (ent == null)
                {
                    FireError(Op.SUBSCRIBE, "Invalid protocol", iq);
                    return;
                }
                string s = ent.GetAttribute("subscription");
                if (s == "")
                {
                    subType = PubSubSubscriptionType.NONE_SPECIFIED;
                }
                else
                {
                    subType = (PubSubSubscriptionType)Enum.Parse(typeof(PubSubSubscriptionType), s);
                }
            }

            switch (subType)
            {
            case PubSubSubscriptionType.NONE_SPECIFIED:
            case PubSubSubscriptionType.subscribed:
                break;

            case PubSubSubscriptionType.pending:
                FireError(Op.SUBSCRIBE, "Subscription pending authorization", iq);
                return;

            case PubSubSubscriptionType.unconfigured:
                FireError(Op.SUBSCRIBE, "Subscription configuration required.  Not implemented yet.", iq);
                return;
            }

            this[Op.SUBSCRIBE] = STATE.Running;
            GetItemsIfPending();
        }
Пример #2
0
        protected override Yield FilterRecipients(DispatcherEvent ev, PubSubSubscription subscription, Result <DispatcherEvent> result)
        {
            var    recipients2 = new List <DispatcherRecipient>();
            uint?  pageid      = null;
            string wikiId      = null;

            if (ev.HasDocument)
            {
                var changeDoc = ev.AsDocument();
                pageid = changeDoc["pageid"].AsUInt;
                wikiId = changeDoc["@wikiid"].AsText;
            }
            var userIds = new Dictionary <int, DispatcherRecipient>();

            foreach (var recipient in subscription.Recipients)
            {
                var authtoken = recipient.Doc["@authtoken"].AsText;
                if (string.IsNullOrEmpty(authtoken))
                {
                    // if the recipient has no authtoken, but has a userid, collect the Id so we can authorize it against the page
                    int?userId = recipient.Doc["@userid"].AsInt;
                    if (userId.HasValue)
                    {
                        userIds.Add(userId.Value, recipient);
                    }
                }
                else if (authtoken == _authtoken)
                {
                    // master authtoken means the recipient doesn't need page level authorization (such as lucene)
                    recipients2.Add(recipient);
                }
                else if (!string.IsNullOrEmpty(wikiId))
                {
                    var key = authtoken + ":" + wikiId;
                    if (!_validatedKeys.Contains(key))
                    {
                        // no valid key found, need to check with API to validate
                        XDoc settings = null;
                        yield return(_deki.At("site", "settings")
                                     .With("apikey", _authtoken)
                                     .WithHeader("X-Deki-Site", "id=" + wikiId)
                                     .Get(new Result <DreamMessage>())
                                     .Set(x => settings = x.IsSuccessful ? x.ToDocument() : null));

                        if (settings == null || !authtoken.EqualsInvariant(settings["security/api-key"].AsText))
                        {
                            continue;
                        }
                        _validatedKeys.Add(key);
                    }

                    // instance authtoken means the recipient doesn't need page level authorization (such as lucene)
                    recipients2.Add(recipient);
                }
            }
            if (userIds.Count > 0 && (ev.Channel.Segments.Length <= 2 || !ev.Channel.Segments[2].EqualsInvariantIgnoreCase("delete")))
            {
                // check all userId's against the page to prune set to authorized users
                var users = new XDoc("users");
                foreach (int userid in userIds.Keys)
                {
                    users.Start("user").Attr("id", userid).End();
                }
                if (pageid.HasValue)
                {
                    Result <DreamMessage> userAuthResult;
                    yield return(userAuthResult = _deki.At("pages", pageid.Value.ToString(), "allowed")
                                                  .With("permissions", "read,subscribe")
                                                  .With("filterdisabled", true)
                                                  .WithHeader("X-Deki-Site", "id=" + wikiId)
                                                  .PostAsync(users));

                    DreamMessage userAuth = userAuthResult.Value;
                    if (userAuth.IsSuccessful)
                    {
                        int authorized = 0;
                        foreach (XDoc userid in userAuth.ToDocument()["user/@id"])
                        {
                            DispatcherRecipient recipient;
                            if (!userIds.TryGetValue(userid.AsInt.GetValueOrDefault(), out recipient))
                            {
                                continue;
                            }
                            authorized++;
                            recipients2.Add(recipient);
                        }
                        if (authorized != userIds.Count)
                        {
                            _log.DebugFormat("requested auth on {0} users, received auth on {1} for page {2}", userIds.Count, authorized, pageid.Value);
                        }
                    }
                    else
                    {
                        _log.WarnFormat("unable to retrieve user auth for page '{0}': {1}", pageid, userAuth.Status);
                    }
                }
            }
            result.Return(recipients2.Count == 0 ? null : ev.WithRecipient(true, recipients2.ToArray()));
            yield break;
        }