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); }
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")); }
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); }
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); }