private IResponse Query <T>(IRequestContext ctx, Route route, IQuery <T> query, NameValueCollection p) { IQuery <T> wrappedQuery = WrapInJoinQueryIfFound(query, this.Database, p); // Ensure the table exists and set it on the query string tableName = GetAndValidateTableName(route); if (!this.Database.TableExists(tableName)) { return(ArribaResponse.NotFound("Table not found to query.")); } query.TableName = tableName; // Correct the query with default correctors using (ctx.Monitor(MonitorEventLevel.Verbose, "Correct", type: "Table", identity: tableName, detail: query.Where.ToString())) { query.Correct(this.CurrentCorrectors(ctx)); } // Execute and return results for the query using (ctx.Monitor(MonitorEventLevel.Information, query.GetType().Name, type: "Table", identity: tableName, detail: query.Where.ToString())) { T result = this.Database.Query(wrappedQuery, (si) => this.IsInIdentity(ctx.Request.User, si)); return(ArribaResponse.Ok(result)); } }
private async Task<IResponse> Select(IRequestContext ctx, Route route) { string tableName = GetAndValidateTableName(route); if (!this.Database.TableExists(tableName)) { return ArribaResponse.NotFound("Table not found to select from."); } string outputFormat = ctx.Request.ResourceParameters["fmt"]; SelectQuery query = await SelectQueryFromRequest(this.Database, ctx); query.TableName = tableName; Table table = this.Database[tableName]; SelectResult result = null; // If no columns were requested or this is RSS, get only the ID column if(query.Columns == null || query.Columns.Count == 0 || String.Equals(outputFormat, "rss", StringComparison.OrdinalIgnoreCase)) { query.Columns = new string[] { table.IDColumn.Name }; } // Read Joins, if passed IQuery<SelectResult> wrappedQuery = WrapInJoinQueryIfFound(query, this.Database, ctx); ICorrector correctors = this.CurrentCorrectors(ctx); using (ctx.Monitor(MonitorEventLevel.Verbose, "Correct", type: "Table", identity: tableName, detail: query.Where.ToString())) { // Run server correctors wrappedQuery.Correct(correctors); } using (ctx.Monitor(MonitorEventLevel.Information, "Select", type: "Table", identity: tableName, detail: query.Where.ToString())) { // Run the query result = this.Database.Query(wrappedQuery, (si) => this.IsInIdentity(ctx.Request.User, si)); } // Format the result in the return format switch((outputFormat ?? "").ToLowerInvariant()) { case "": case "json": return ArribaResponse.Ok(result); case "csv": return ToCsvResponse(result, $"{tableName}-{DateTime.Now:yyyyMMdd}.csv"); case "rss": return ToRssResponse(result, "", query.TableName + ": " + query.Where, ctx.Request.ResourceParameters["iURL"]); default: throw new ArgumentException($"OutputFormat [fmt] passed, '{outputFormat}', was invalid."); } }
protected IResponse ValidateTableAccess(IRequestContext ctx, Route routeData, PermissionScope scope, bool overrideLocalHostSameUser = false) { string tableName = GetAndValidateTableName(routeData); if (!this.Database.TableExists(tableName)) { return(ArribaResponse.NotFound("Table requested does not exist.")); } var currentUser = ctx.Request.User; // If we are asked if override auth, check if the request was made from a loopback address (local) and the // current process identity matches the request identity if (overrideLocalHostSameUser && IsRequestOriginLoopback(ctx.Request) && IsProcessUserSame(currentUser.Identity)) { // Log for auditing that we skipped out on checking table auth. this.EventSource.Raise(MonitorEventLevel.Warning, MonitorEventOpCode.Mark, entityType: "Table", entityIdentity: tableName, name: "Authentication Override", user: ctx.Request.User.Identity.Name, detail: "Skipping table authentication for local loopback user on request"); return(ContinueToNextHandlerResponse); } if (!HasTableAccess(tableName, currentUser, scope)) { return(ArribaResponse.Forbidden(String.Format("Access to {0} denied for {1}.", tableName, currentUser.Identity.Name))); } else { return(ContinueToNextHandlerResponse); } }