Пример #1
0
        public ActionResult Save(string sql, string title, string description, int siteId, int?querySetId, bool?textResults, bool?withExecutionPlan, TargetSites?targetSites)
        {
            if (CurrentUser.IsAnonymous && !CaptchaController.CaptchaPassed(GetRemoteIP()))
            {
                return(Json(new { captcha = true }));
            }

            ActionResult response = null;

            try
            {
                if (!ValidateTargetSites(targetSites))
                {
                    throw new ApplicationException("Invalid target sites selection");
                }

                QuerySet querySet = null;

                if (querySetId.HasValue)
                {
                    querySet = Current.DB.QuerySets.Get(querySetId.Value);

                    if (querySet == null)
                    {
                        throw new ApplicationException("Invalid query set ID");
                    }
                }

                var parsedQuery = new ParsedQuery(
                    sql,
                    Request.Params,
                    withExecutionPlan == true,
                    targetSites ?? TargetSites.Current
                    );

                QueryResults results = null;
                Site         site    = GetSite(siteId);
                ValidateQuery(parsedQuery, site);

                if (title.HasValue() && title.Length > 100)
                {
                    throw new ApplicationException("Title must be no more than 100 characters");
                }

                if (description.HasValue() && description.Length > 1000)
                {
                    throw new ApplicationException("Description must be no more than 1000 characters");
                }

                var contextData = new QueryContextData
                {
                    Title       = title,
                    Description = description,
                    IsText      = textResults == true,
                    QuerySet    = querySet
                };

                var asyncResults = AsyncQueryRunner.Execute(parsedQuery, CurrentUser, site, contextData);

                if (asyncResults.State == AsyncQueryRunner.AsyncState.Failure)
                {
                    throw asyncResults.Exception;
                }

                if (asyncResults.State == AsyncQueryRunner.AsyncState.Success || asyncResults.State == AsyncQueryRunner.AsyncState.Cancelled)
                {
                    results = asyncResults.QueryResults;
                }
                else
                {
                    return(Json(new { running = true, job_id = asyncResults.JobId }));
                }

                response = CompleteResponse(results, parsedQuery, contextData, siteId);
            }
            catch (Exception ex)
            {
                response = TransformExecutionException(ex);
            }

            return(response);
        }
Пример #2
0
        private ActionResult CompleteResponse(
            QueryResults results,
            ParsedQuery parsedQuery,
            QueryContextData context,
            int siteId
            )
        {
            results = TranslateResults(parsedQuery, context.IsText, results);

            var query = Current.DB.Query <Query>(
                "SELECT * FROM Queries WHERE QueryHash = @hash",
                new
            {
                hash = parsedQuery.Hash
            }
                ).FirstOrDefault();

            int      revisionId = 0;
            DateTime saveTime;

            // We only create revisions if something actually changed.
            // We'll log it as an execution anyway if applicable, so the user will
            // still get a link in their profile, just not their own revision.
            if (context.Revision == null && (context.QuerySet == null || query == null || context.QuerySet.CurrentRevision == null || context.QuerySet.CurrentRevision.QueryId != query.Id))
            {
                int queryId;
                if (query == null)
                {
                    queryId = (int)Current.DB.Queries.Insert(
                        new
                    {
                        QueryHash = parsedQuery.Hash,
                        QueryBody = parsedQuery.Sql
                    }
                        );
                }
                else
                {
                    queryId = query.Id;
                }

                revisionId = (int)Current.DB.Revisions.Insert(
                    new
                {
                    QueryId            = queryId,
                    OwnerId            = CurrentUser.IsAnonymous ? null : (int?)CurrentUser.Id,
                    OwnerIP            = GetRemoteIP(),
                    CreationDate       = saveTime = DateTime.UtcNow,
                    OriginalQuerySetId = context.QuerySet != null ? context.QuerySet.Id : (int?)null
                }
                    );

                int querySetId;
                // brand new queryset
                if (context.QuerySet == null)
                {
                    // insert it
                    querySetId = (int)Current.DB.QuerySets.Insert(new
                    {
                        InitialRevisionId = revisionId,
                        CurrentRevisionId = revisionId,
                        context.Title,
                        context.Description,
                        LastActivity = DateTime.UtcNow,
                        Votes        = 0,
                        Views        = 0,
                        Featured     = false,
                        Hidden       = false,
                        CreationDate = DateTime.UtcNow,
                        OwnerIp      = CurrentUser.IPAddress,
                        OwnerId      = CurrentUser.IsAnonymous?(int?)null:CurrentUser.Id
                    });

                    Current.DB.Revisions.Update(revisionId, new { OriginalQuerySetId = querySetId });
                }
                else if (
                    (CurrentUser.IsAnonymous && context.QuerySet.OwnerIp == CurrentUser.IPAddress) || context.QuerySet.OwnerId != CurrentUser.Id)
                {
                    // fork it
                    querySetId = (int)Current.DB.QuerySets.Insert(new
                    {
                        InitialRevisionId = context.QuerySet.InitialRevisionId,
                        CurrentRevisionId = revisionId,
                        context.Title,
                        context.Description,
                        LastActivity     = DateTime.UtcNow,
                        Votes            = 0,
                        Views            = 0,
                        Featured         = false,
                        Hidden           = false,
                        CreationDate     = DateTime.UtcNow,
                        OwnerIp          = CurrentUser.IPAddress,
                        OwnerId          = CurrentUser.IsAnonymous ? (int?)null : CurrentUser.Id,
                        ForkedQuerySetId = context.QuerySet.Id
                    });

                    Current.DB.Execute(@"insert QuerySetRevisions(QuerySetId, RevisionId) 
select @newId, RevisionId from QuerySetRevisions where QuerySetId = @oldId", new
                    {
                        newId = querySetId,
                        oldId = context.QuerySet.Id
                    });
                }
                else
                {
                    // update it
                    querySetId = context.QuerySet.Id;

                    context.Title       = context.Title ?? context.QuerySet.Title;
                    context.Description = context.Description ?? context.QuerySet.Description;

                    Current.DB.QuerySets.Update(context.QuerySet.Id, new { context.Title, context.Description, CurrentRevisionId = revisionId, LastActivity = DateTime.UtcNow });
                }

                Current.DB.QuerySetRevisions.Insert(new { QuerySetId = querySetId, RevisionId = revisionId });

                results.RevisionId = revisionId;
                results.Created    = saveTime;
                results.QuerySetId = querySetId;
            }
            else
            {
                results.RevisionId = context.Revision != null ? context.Revision.Id : context.QuerySet.CurrentRevisionId;
                results.QuerySetId = context.QuerySet.Id;
                results.Created    = null;
            }

            if (context.Title != null)
            {
                results.Slug = context.Title.URLFriendly();
            }

            QueryRunner.LogRevisionExecution(CurrentUser, siteId, results.RevisionId);

            // Consider handling this XSS condition (?) in the ToJson() method instead, if possible
            return(Content(results.ToJson().Replace("/", "\\/"), "application/json"));
        }
Пример #3
0
        public ActionResult Execute(int querySetId, int revisionId, int siteId, bool?textResults, bool?withExecutionPlan, TargetSites?targetSites)
        {
            if (CurrentUser.IsAnonymous && !CaptchaController.CaptchaPassed(GetRemoteIP()))
            {
                return(Json(new { captcha = true }));
            }

            ActionResult response = null;

            try
            {
                if (!ValidateTargetSites(targetSites))
                {
                    throw new ApplicationException("Invalid target sites selection");
                }

                QuerySet querySet = null;


                querySet = Current.DB.QuerySets.Get(querySetId);

                if (querySet == null)
                {
                    throw new ApplicationException("Invalid query set ID");
                }

                Revision revision = Current.DB.Revisions.Get(revisionId);
                if (revision == null)
                {
                    throw new ApplicationException("Invalid revision ID");
                }

                Query query = Current.DB.Queries.Get(revision.QueryId);

                var parsedQuery = new ParsedQuery(
                    query.QueryBody,
                    Request.Params,
                    withExecutionPlan == true,
                    targetSites ?? TargetSites.Current
                    );

                QueryResults results = null;
                Site         site    = GetSite(siteId);
                ValidateQuery(parsedQuery, site);

                var contextData = new QueryContextData
                {
                    IsText   = textResults == true,
                    QuerySet = querySet,
                    Revision = revision
                };

                var asyncResults = AsyncQueryRunner.Execute(parsedQuery, CurrentUser, site, contextData);

                if (asyncResults.State == AsyncQueryRunner.AsyncState.Failure)
                {
                    throw asyncResults.Exception;
                }

                if (asyncResults.State == AsyncQueryRunner.AsyncState.Success)
                {
                    results = asyncResults.QueryResults;
                }
                else
                {
                    return(Json(new { running = true, job_id = asyncResults.JobId }));
                }

                response = CompleteResponse(results, parsedQuery, contextData, siteId);
            }
            catch (Exception ex)
            {
                response = TransformExecutionException(ex);
            }

            return(response);
        }
Пример #4
0
        public async Task <ActionResult> Execute(int querySetId, int revisionId, int siteId, bool?textResults, bool?withExecutionPlan, bool?bypassCache, TargetSites?targetSites)
        {
            if (!(await Captcha.ChallengeIsvalidAsync(Request.Form)))
            {
                return(Json(new { captcha = true }));
            }

            ActionResult response;

            try
            {
                if (!ValidateTargetSites(targetSites))
                {
                    throw new ApplicationException("Invalid target sites selection");
                }

                var querySet = Current.DB.QuerySets.Get(querySetId);
                if (querySet == null)
                {
                    throw new ApplicationException("Invalid query set ID");
                }

                var revision = Current.DB.Revisions.Get(revisionId);
                if (revision == null)
                {
                    throw new ApplicationException("Invalid revision ID");
                }

                var query       = Current.DB.Queries.Get(revision.QueryId);
                var parsedQuery = new ParsedQuery(
                    query.QueryBody,
                    Request.Params,
                    withExecutionPlan == true,
                    targetSites ?? TargetSites.Current
                    );

                if (AppSettings.EnableBypassCache && bypassCache.HasValue && bypassCache.Value)
                {
                    QueryUtil.ClearCachedResults(parsedQuery, siteId);
                }

                var site = GetSite(siteId);
                ValidateQuery(parsedQuery, site);

                var contextData = new QueryContextData
                {
                    IsText   = textResults == true,
                    QuerySet = querySet,
                    Revision = revision
                };

                var asyncResults = AsyncQueryRunner.Execute(parsedQuery, CurrentUser, site, contextData);
                if (asyncResults.State == AsyncQueryRunner.AsyncState.Failure)
                {
                    throw asyncResults.Exception;
                }

                QueryResults results;
                if (asyncResults.State == AsyncQueryRunner.AsyncState.Success)
                {
                    results = asyncResults.QueryResults;
                }
                else
                {
                    return(Json(new { running = true, job_id = asyncResults.JobId }));
                }

                response = CompleteResponse(results, parsedQuery, contextData, siteId);
            }
            catch (Exception ex)
            {
                response = TransformExecutionException(ex);
            }

            return(response);
        }