generated from Ed-Fi-Exchange-OSS/Template-for-GitHub
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[RND-698] add postgresql insert and get support
- Loading branch information
1 parent
a2a1df2
commit fc074bf
Showing
16 changed files
with
389 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -396,3 +396,6 @@ FodyWeavers.xsd | |
|
||
# JetBrains Rider | ||
*.sln.iml | ||
|
||
# DotNetEnv | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#### PostgreSQL backend options | ||
|
||
POSTGRES_USER= | ||
POSTGRES_PASSWORD= |
4 changes: 4 additions & 0 deletions
4
Meadowlark.net/Meadowlark.Net.Core/Backend/Model/GetRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
using Meadowlark.Net.Core.Model; | ||
namespace Meadowlark.Net.Core.Backend.Model; | ||
|
||
public record GetRequest(DocumentUuid DocumentUuid, ResourceInfo ResourceInfo); |
4 changes: 4 additions & 0 deletions
4
Meadowlark.net/Meadowlark.Net.Core/Backend/Model/GetResponse.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
using Meadowlark.Net.Core.Model; | ||
namespace Meadowlark.Net.Core.Backend.Model; | ||
|
||
public record GetResponse(string EdfiDoc); |
5 changes: 5 additions & 0 deletions
5
Meadowlark.net/Meadowlark.Net.Core/Backend/Model/InsertRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
using Meadowlark.Net.Core.Model; | ||
using Newtonsoft.Json.Linq; | ||
namespace Meadowlark.Net.Core.Backend.Model; | ||
|
||
public record InsertRequest(DocumentUuid DocumentUuid, ResourceInfo ResourceInfo, JObject EdfiDoc); |
101 changes: 101 additions & 0 deletions
101
Meadowlark.net/Meadowlark.Net.Core/Backend/Postgresql/Db.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
using Meadowlark.Net.Core.Backend.Model; | ||
using Meadowlark.Net.Core.Model; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
using Npgsql; | ||
using NpgsqlTypes; | ||
|
||
namespace Meadowlark.Net.Core.Backend.Postgresql; | ||
|
||
public static class Db | ||
{ | ||
// TODO: Get .env loading working | ||
private static readonly string connectionString = "Server=localhost;Port=5432;User Id=postgres;Password=abcdefgh1!;Database=MeadowlarkNet;"; | ||
|
||
// static Db() | ||
// { | ||
// Load .env file with Postgresql username/password | ||
// DotNetEnv.Env.TraversePath().Load(); | ||
// connectionString: $"Server=localhost;Port=5432;User Id={Environment.GetEnvironmentVariable("POSTGRES_USER")};Password={Environment.GetEnvironmentVariable("POSTGRES_PASSWORD")};Database=MeadowlarkNet;"); | ||
// } | ||
|
||
private static async Task TryCreateTable(ResourceInfo resourceInfo) | ||
{ | ||
// Note: ProjectName and ResourceName have been validated against the ApiSchema, so SQL injection is not a concern here | ||
string schemaName = resourceInfo.ProjectName.Value.Replace("-", ""); | ||
string tableName = resourceInfo.ResourceName.Value.Replace("-", ""); | ||
|
||
using var con = new NpgsqlConnection(connectionString); | ||
con.Open(); | ||
using var cmd = new NpgsqlCommand(); | ||
cmd.Connection = con; | ||
|
||
cmd.CommandText = $"CREATE SCHEMA IF NOT EXISTS {schemaName}"; | ||
await cmd.ExecuteNonQueryAsync(); | ||
cmd.CommandText = $@"CREATE TABLE IF NOT EXISTS {schemaName}.{tableName}( | ||
id bigserial PRIMARY KEY, | ||
document_uuid UUID NOT NULL, | ||
project_name VARCHAR NOT NULL, | ||
resource_name VARCHAR NOT NULL, | ||
resource_version VARCHAR NOT NULL, | ||
is_descriptor BOOLEAN NOT NULL, | ||
edfi_doc JSONB NOT NULL);"; | ||
await cmd.ExecuteNonQueryAsync(); | ||
} | ||
|
||
public static async Task InsertDocument(InsertRequest insertRequest) | ||
{ | ||
await TryCreateTable(insertRequest.ResourceInfo); | ||
|
||
// Note: ProjectName and ResourceName have been validated against the ApiSchema, so SQL injection is not a concern here | ||
string schemaName = insertRequest.ResourceInfo.ProjectName.Value.Replace("-", ""); | ||
string tableName = insertRequest.ResourceInfo.ResourceName.Value.Replace("-", ""); | ||
var (documentUuid, resourceInfo, edfiDoc) = insertRequest; | ||
|
||
// Add the new documentUuid to the document | ||
edfiDoc.Add(new JProperty("id", documentUuid.Value)); | ||
|
||
using var con = new NpgsqlConnection(connectionString); | ||
con.Open(); | ||
|
||
var commandText = $@" INSERT INTO {schemaName}.{tableName} | ||
(document_uuid, project_name, resource_name, resource_version, is_descriptor, edfi_doc) | ||
VALUES ($1, $2, $3, $4, $5, $6)"; | ||
await using var cmd = new NpgsqlCommand(commandText, con) | ||
{ | ||
Parameters = { | ||
new() {Value = new Guid(documentUuid.Value), NpgsqlDbType = NpgsqlDbType.Uuid }, | ||
new() {Value = resourceInfo.ProjectName.Value }, | ||
new() {Value = resourceInfo.ResourceName.Value }, | ||
new() {Value = resourceInfo.ResourceVersion.Value }, | ||
new() {Value = resourceInfo.IsDescriptor }, | ||
new() {Value = JsonConvert.SerializeObject(edfiDoc), NpgsqlDbType = NpgsqlDbType.Jsonb } | ||
} | ||
}; | ||
await cmd.ExecuteNonQueryAsync(); | ||
} | ||
|
||
public static async Task<GetResponse> FindDocumentByDocumentUuid(GetRequest getRequest) | ||
{ | ||
await TryCreateTable(getRequest.ResourceInfo); | ||
|
||
// Note: ProjectName and ResourceName have been validated against the ApiSchema, so SQL injection is not a concern here | ||
string schemaName = getRequest.ResourceInfo.ProjectName.Value.Replace("-", ""); | ||
string tableName = getRequest.ResourceInfo.ResourceName.Value.Replace("-", ""); | ||
|
||
using var con = new NpgsqlConnection(connectionString); | ||
con.Open(); | ||
|
||
var commandText = $@"SELECT edfi_doc FROM {schemaName}.{tableName} WHERE document_uuid = $1;"; | ||
|
||
await using var cmd = new NpgsqlCommand(commandText, con) | ||
{ | ||
Parameters = { | ||
new() { Value = new Guid(getRequest.DocumentUuid.Value), NpgsqlDbType = NpgsqlDbType.Uuid } | ||
} | ||
}; | ||
|
||
var result = await cmd.ExecuteScalarAsync(); | ||
return new(result == null ? "" : result.ToString() ?? ""); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Meadowlark.net/Meadowlark.Net.Core/Backend/Postgresql/GetById.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Meadowlark.Net.Core.Backend.Model; | ||
using static Meadowlark.Net.Core.Backend.Postgresql.Db; | ||
|
||
namespace Meadowlark.Net.Core.Backend.Postgresql; | ||
|
||
public static class GetById | ||
{ | ||
public static async Task<FrontendResponse> GetByIdDb(GetRequest getRequest) | ||
{ | ||
GetResponse result = await FindDocumentByDocumentUuid(getRequest); | ||
return new(StatusCode: 200, Body: $"Success: {result.EdfiDoc}"); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Meadowlark.net/Meadowlark.Net.Core/Backend/Postgresql/Upsert.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Meadowlark.Net.Core.Backend.Model; | ||
using static Meadowlark.Net.Core.Backend.Postgresql.Db; | ||
|
||
namespace Meadowlark.Net.Core.Backend.Postgresql; | ||
|
||
public static class Upsert | ||
{ | ||
public static async Task<FrontendResponse> UpsertDb(InsertRequest insertRequest) | ||
{ | ||
await InsertDocument(insertRequest); | ||
return new(StatusCode: 200, Body: $"Success: {insertRequest.ToString()}"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
namespace Meadowlark.Net.Backend.Postgresql; | ||
|
||
public static class Utility | ||
{ | ||
|
||
/** | ||
* Simple only-once guard for a function with no parameters | ||
*/ | ||
public static Action Once(Action fn){ | ||
var called = false; | ||
|
||
void guardedFunction() | ||
{ | ||
if (!called) | ||
{ | ||
fn(); | ||
called = true; | ||
} | ||
} | ||
|
||
return guardedFunction; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
Meadowlark.net/Meadowlark.Net.Core/Middleware/ValidateDocumentMiddleware.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using Meadowlark.Net.Core.Model; | ||
using static Meadowlark.Net.Core.Validation.DocumentValidator; | ||
|
||
namespace Meadowlark.Net.Core.Middleware; | ||
|
||
public static class ValidateDocumentMiddleware | ||
{ | ||
/** | ||
* Validates JSON document shape | ||
*/ | ||
public static MiddlewareModel DocumentValidation(MiddlewareModel middlewareModel) | ||
{ | ||
var (requestModel, frontendResponse) = middlewareModel; | ||
|
||
// if there is a response already posted, we are done | ||
if (frontendResponse != null) return middlewareModel; | ||
|
||
// if the body is null, this middleware shouldn't be involved | ||
if (requestModel.FrontendRequest.Body == null) throw new Exception("requestModel.FrontendRequest.Body is null"); | ||
|
||
string[] errors = ValidateDocument(requestModel.ResourceSchema, requestModel.FrontendRequest.Body); | ||
|
||
if (errors.Length > 0) | ||
{ | ||
return middlewareModel with { FrontendResponse = new(StatusCode: 400, Body: String.Join(", ", errors)) }; | ||
} | ||
|
||
return middlewareModel; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.