feat: device reset via RST token + Postgres code-first migrations
Device reset: Device.ResetRequested is a one-shot flag claimed atomically with a single UPDATE, so a queued reset is delivered exactly once. GET api/telemetry/AddData answers it with the bare token RST and nothing else; subsequent requests resume the normal routine. Adds POST api/admin/devices/{id}/request-reset (audited) plus an admin panel button, pending badge and confirm dialog.
Postgres migrations: PostgresGreenHomeDbContext owns Data/Migrations/Postgres while the SqlServer set stays untouched. Registers one context per provider with the base type forwarded, replaces EnsureCreated() with Migrate() for both, adds a complete InitialPostgres migration and an incremental AddDeviceResetRequested for SqlServer, and adds design-time factories so dotnet ef does not have to boot the API host.
Timestamps: Postgres DateTime columns are now timestamp with time zone, because Npgsql rejects Kind=Utc values on a naive timestamp column, which broke every write path (auth, settings, posts, checklists, alerts, audit logs). Removes the SpecifyKind(Unspecified) workarounds, fixes a 3:30 offset where already-UTC filters were passed through ToLocalTime(), and makes DataCopy migrate instead of EnsureCreated while passing timestamps through verbatim.
Tests: Test/GreenHome.SelfCheck applies the Postgres migrations and asserts that a queued reset is consumed exactly once and that timestamps round-trip as Utc.
This commit is contained in:
@@ -19,6 +19,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenHome.AI.DeepSeek", "Gr
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenHome.DataCopy", "GreenHome.DataCopy\GreenHome.DataCopy.csproj", "{0F5C7A31-54F9-4C29-8E05-66CECAF520C7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{0C88DD14-F956-CE84-757C-A364CCF449FC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenHome.SelfCheck", "Test\GreenHome.SelfCheck\GreenHome.SelfCheck.csproj", "{7210CF1A-6103-48D7-869B-890958132534}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -125,8 +129,23 @@ Global
|
||||
{0F5C7A31-54F9-4C29-8E05-66CECAF520C7}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0F5C7A31-54F9-4C29-8E05-66CECAF520C7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0F5C7A31-54F9-4C29-8E05-66CECAF520C7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7210CF1A-6103-48D7-869B-890958132534}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{7210CF1A-6103-48D7-869B-890958132534} = {0C88DD14-F956-CE84-757C-A364CCF449FC}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Reference in New Issue
Block a user