mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-10-03 18:53:18 +00:00
Compare commits
15 commits
ed8cb683b2
...
b277d07564
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b277d07564 | ||
|
|
82c75edfa6 | ||
|
|
2959f7bc41 | ||
|
|
ebcece420e | ||
|
|
987f3314bd | ||
|
|
ba1b6bc22b | ||
|
|
a9b0df54da | ||
|
|
4f724531bf | ||
|
|
a71b07db4d | ||
|
|
a330eb39c2 | ||
|
|
57cd85e4c2 | ||
|
|
d3347333b2 | ||
|
|
8691c8a205 | ||
|
|
b23c4be81c | ||
|
|
ae3ad9d823 |
16 changed files with 140 additions and 106 deletions
|
|
@ -37,6 +37,7 @@ public class AuthController : ControllerBase
|
|||
var allowedRedirectUris = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"https://proposals.seahaven.com/callback",
|
||||
"https://d2yevct5e5uuz5.cloudfront.net/callback",
|
||||
};
|
||||
if (_config.GetValue<bool>("Auth:DevMode"))
|
||||
allowedRedirectUris.Add("http://localhost:5173/callback");
|
||||
|
|
@ -136,7 +137,7 @@ public class AuthController : ControllerBase
|
|||
user.Email,
|
||||
user.DisplayName,
|
||||
user.Role.ToString(),
|
||||
tokenResponse.AccessToken
|
||||
tokenResponse.IdToken
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ builder.Services.AddCors(options =>
|
|||
{
|
||||
options.AddDefaultPolicy(policy =>
|
||||
{
|
||||
var origins = new List<string> { "https://proposals.seahaven.com" };
|
||||
var origins = new List<string> { "https://proposals.seahaven.com", "https://d2yevct5e5uuz5.cloudfront.net" };
|
||||
if (builder.Environment.IsDevelopment())
|
||||
origins.Add("http://localhost:5173");
|
||||
policy.WithOrigins(origins.ToArray())
|
||||
|
|
@ -221,11 +221,8 @@ var app = builder.Build();
|
|||
|
||||
app.UseMiddleware<GlobalExceptionHandler>();
|
||||
|
||||
if (!app.Environment.IsProduction())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Proposal System API v1"));
|
||||
}
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Proposal System API v1"));
|
||||
|
||||
app.UseCors();
|
||||
app.UseMiddleware<InternalApiKeyMiddleware>();
|
||||
|
|
@ -243,4 +240,10 @@ app.Use(async (context, next) =>
|
|||
app.MapControllers();
|
||||
app.MapHealthChecks("/api/health");
|
||||
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<ProposalDbContext>();
|
||||
db.Database.Migrate();
|
||||
}
|
||||
|
||||
app.Run();
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ export class ComputeStack extends cdk.Stack {
|
|||
corsPreflight: {
|
||||
allowOrigins: [
|
||||
'https://proposals.seahaven.com',
|
||||
'https://d2yevct5e5uuz5.cloudfront.net',
|
||||
'http://localhost:5173',
|
||||
],
|
||||
allowMethods: [
|
||||
|
|
@ -364,13 +365,31 @@ export class ComputeStack extends cdk.Stack {
|
|||
|
||||
httpApi.addRoutes({
|
||||
path: '/api/auth/{proxy+}',
|
||||
methods: [apigatewayv2.HttpMethod.POST],
|
||||
methods: [apigatewayv2.HttpMethod.POST, apigatewayv2.HttpMethod.OPTIONS],
|
||||
integration: apiIntegration,
|
||||
});
|
||||
|
||||
httpApi.addRoutes({
|
||||
path: '/swagger/{proxy+}',
|
||||
methods: [apigatewayv2.HttpMethod.GET],
|
||||
integration: apiIntegration,
|
||||
});
|
||||
|
||||
httpApi.addRoutes({
|
||||
path: '/swagger',
|
||||
methods: [apigatewayv2.HttpMethod.GET],
|
||||
integration: apiIntegration,
|
||||
});
|
||||
|
||||
httpApi.addRoutes({
|
||||
path: '/{proxy+}',
|
||||
methods: [apigatewayv2.HttpMethod.ANY],
|
||||
methods: [
|
||||
apigatewayv2.HttpMethod.GET,
|
||||
apigatewayv2.HttpMethod.POST,
|
||||
apigatewayv2.HttpMethod.PUT,
|
||||
apigatewayv2.HttpMethod.DELETE,
|
||||
apigatewayv2.HttpMethod.PATCH,
|
||||
],
|
||||
integration: apiIntegration,
|
||||
authorizer: jwtAuthorizer,
|
||||
});
|
||||
|
|
|
|||
8
infra/package-lock.json
generated
8
infra/package-lock.json
generated
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"aws-cdk": "^2.1124.1",
|
||||
"aws-cdk": "^2.1125.0",
|
||||
"typescript": "~5.7.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -76,9 +76,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/aws-cdk": {
|
||||
"version": "2.1124.1",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1124.1.tgz",
|
||||
"integrity": "sha512-sRYdPMdkX+02EHaT946AFV0w0CMfbHKWpLZPv525xTCkaVu1eYu6DzHFuTdimxdSN0uGQ2D4LHrD1sr94tRhow==",
|
||||
"version": "2.1125.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1125.0.tgz",
|
||||
"integrity": "sha512-QAvsE2XQMcyNOjMMqAS7eDADR9t6vcFcMQvhOmtLfDqgfJXSyTkHvzM5zgwZCdJ4FNqWr5Y/zXvL1Cv5ECKXwQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"aws-cdk": "^2.1124.1",
|
||||
"aws-cdk": "^2.1125.0",
|
||||
"typescript": "~5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
boto3>=1.43.14,<2.0
|
||||
boto3>=1.43.18,<2.0
|
||||
httpx>=0.28.1,<1.0
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
pdfplumber>=0.11.9,<1.0
|
||||
boto3>=1.43.14,<2.0
|
||||
boto3>=1.43.18,<2.0
|
||||
httpx>=0.28.1,<1.0
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
reportlab>=4.5.1,<5.0
|
||||
boto3>=1.43.14,<2.0
|
||||
boto3>=1.43.18,<2.0
|
||||
httpx>=0.28.1,<1.0
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
boto3>=1.43.14,<2.0
|
||||
boto3>=1.43.18,<2.0
|
||||
httpx>=0.28.1,<1.0
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ GEM
|
|||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1249.0)
|
||||
aws-sdk-core (3.247.0)
|
||||
aws-partitions (1.1255.0)
|
||||
aws-sdk-core (3.250.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
|
|
@ -32,11 +32,11 @@ GEM
|
|||
bigdecimal
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
logger
|
||||
aws-sdk-kms (1.125.0)
|
||||
aws-sdk-core (~> 3, >= 3.247.0)
|
||||
aws-sdk-kms (1.128.0)
|
||||
aws-sdk-core (~> 3, >= 3.248.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.222.0)
|
||||
aws-sdk-core (~> 3, >= 3.247.0)
|
||||
aws-sdk-s3 (1.224.0)
|
||||
aws-sdk-core (~> 3, >= 3.248.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.12.1)
|
||||
|
|
@ -131,7 +131,7 @@ GEM
|
|||
faraday_middleware (1.2.1)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.4.1)
|
||||
fastlane (2.234.0)
|
||||
fastlane (2.235.0)
|
||||
CFPropertyList (>= 2.3, < 5.0.0)
|
||||
abbrev (~> 0.1)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
|
|
@ -140,7 +140,7 @@ GEM
|
|||
babosa (>= 1.0.3, < 2.0.0)
|
||||
base64 (~> 0.2)
|
||||
benchmark (>= 0.1.0)
|
||||
bundler (>= 1.17.3, < 5.0.0)
|
||||
bundler (>= 2.4.0, < 5.0.0)
|
||||
colored (~> 1.2)
|
||||
commander (~> 4.6)
|
||||
csv (~> 3.3)
|
||||
|
|
@ -155,12 +155,12 @@ GEM
|
|||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-env (>= 1.6.0, <= 2.1.1)
|
||||
google-cloud-env (>= 1.6.0, < 2.3.0)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
http-cookie (~> 1.0.5)
|
||||
json (< 3.0.0)
|
||||
jwt (>= 2.1.0, < 3)
|
||||
jwt (>= 2.1.0, < 4)
|
||||
logger (>= 1.6, < 2.0)
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (>= 2.0.0, < 3.0.0)
|
||||
|
|
@ -196,7 +196,7 @@ GEM
|
|||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.100.0)
|
||||
google-apis-androidpublisher_v3 (0.101.0)
|
||||
google-apis-core (>= 0.15.0, < 2.a)
|
||||
google-apis-core (0.18.0)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
|
|
@ -215,7 +215,8 @@ GEM
|
|||
google-cloud-core (1.8.0)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (2.1.1)
|
||||
google-cloud-env (2.2.2)
|
||||
base64 (~> 0.2)
|
||||
faraday (>= 1.0, < 3.a)
|
||||
google-cloud-errors (1.6.0)
|
||||
google-cloud-storage (1.60.0)
|
||||
|
|
@ -227,10 +228,12 @@ GEM
|
|||
google-cloud-core (~> 1.6)
|
||||
googleauth (~> 1.9)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.11.2)
|
||||
google-logging-utils (0.2.0)
|
||||
googleauth (1.16.2)
|
||||
faraday (>= 1.0, < 3.a)
|
||||
google-cloud-env (~> 2.1)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
google-cloud-env (~> 2.2)
|
||||
google-logging-utils (~> 0.1)
|
||||
jwt (>= 1.4, < 4.0)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
|
|
@ -242,8 +245,8 @@ GEM
|
|||
i18n (1.14.8)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jmespath (1.6.2)
|
||||
json (2.19.5)
|
||||
jwt (2.10.2)
|
||||
json (2.19.7)
|
||||
jwt (3.2.0)
|
||||
base64
|
||||
logger (1.7.0)
|
||||
mini_magick (4.13.2)
|
||||
|
|
@ -268,7 +271,7 @@ GEM
|
|||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.4.1)
|
||||
retriable (3.8.0)
|
||||
rexml (3.4.4)
|
||||
rouge (3.28.0)
|
||||
ruby-macho (2.5.1)
|
||||
|
|
@ -328,7 +331,6 @@ DEPENDENCIES
|
|||
cocoapods
|
||||
fastlane
|
||||
|
||||
CHECKSUMS
|
||||
CFPropertyList (3.0.8) sha256=2c99d0d980536d3d7ab252f7bd59ac8be50fbdd1ff487c98c949bb66bb114261
|
||||
abbrev (0.1.2) sha256=ad1b4eaaaed4cb722d5684d63949e4bde1d34f2a95e20db93aecfe7cbac74242
|
||||
activesupport (7.2.3.1) sha256=11ebed516a43a0bb47346227a35ebae4d9427465a7c9eb197a03d5c8d283cb34
|
||||
|
|
@ -337,10 +339,10 @@ CHECKSUMS
|
|||
artifactory (3.0.17) sha256=3023d5c964c31674090d655a516f38ca75665c15084140c08b7f2841131af263
|
||||
atomos (0.1.3) sha256=7d43b22f2454a36bace5532d30785b06de3711399cb1c6bf932573eda536789f
|
||||
aws-eventstream (1.4.0) sha256=116bf85c436200d1060811e6f5d2d40c88f65448f2125bc77ffce5121e6e183b
|
||||
aws-partitions (1.1249.0) sha256=f0bed070aba353e6ffe439953d6c354b3f51d16770386d2b198e71d34612f2e9
|
||||
aws-sdk-core (3.247.0) sha256=789864594ce8cef05ee3d81fa8ed506099280bda6ea12a7612b8b7c5e5e62851
|
||||
aws-sdk-kms (1.125.0) sha256=23f81bc0838ae6ec2e8de3eae88af521d0e29d3a59b6c9dbb4b21343ba476bc8
|
||||
aws-sdk-s3 (1.222.0) sha256=bae4b06fccf0b81b8d77e7abfc56e5e2146590d43c4ab58db0cee3ff5bbfb7f1
|
||||
aws-partitions (1.1255.0) sha256=490ffc1f032d3eac771cf4a94ab7a3c7999c5edbe6fb7660904e702e291c93b5
|
||||
aws-sdk-core (3.250.0) sha256=8df71164c7e5f2ff411782a3dc3a1ab5c0a73170284409ead111f385e9992963
|
||||
aws-sdk-kms (1.128.0) sha256=20ce3957f80c7b40b3115a7e902af52b15a6eef42fe6b2e19db72f8e8c9e5658
|
||||
aws-sdk-s3 (1.224.0) sha256=7d443c4ae9eda795b60e081d41f49b498e2483f1fc204f3239176ec922ed7879
|
||||
aws-sigv4 (1.12.1) sha256=6973ff95cb0fd0dc58ba26e90e9510a2219525d07620c8babeb70ef831826c00
|
||||
babosa (1.0.4) sha256=18dea450f595462ed7cb80595abd76b2e535db8c91b350f6c4b3d73986c5bc99
|
||||
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
|
||||
|
|
@ -384,7 +386,7 @@ CHECKSUMS
|
|||
faraday-retry (1.0.4) sha256=dc659233777fabf96c69c2ffe56c0a5d2c102af90321a42cc6c90157bcd716aa
|
||||
faraday_middleware (1.2.1) sha256=d45b78c8ee864c4783fbc276f845243d4a7918a67301c052647bacabec0529e9
|
||||
fastimage (2.4.1) sha256=c64bebd46b6fd8943ab70c1e6e85ff728f970f2e48f92ecd249b6bc3a540ad20
|
||||
fastlane (2.234.0) sha256=b74835681ad9a8e9c0931a5727dad1bab433895ac534c864a1ed5749625d26e9
|
||||
fastlane (2.235.0) sha256=7de12cf4c4e242b68836aef859ba8e6b25bb1db7f6c8e2d705b024fb16a2ed65
|
||||
fastlane-sirp (1.1.0) sha256=10bc94f9682efd8e1badfb31452a76dd8981f1f3a33717c765fde6d75b54d847
|
||||
ffi (1.17.4) sha256=bcd1642e06f0d16fc9e09ac6d49c3a7298b9789bcb58127302f934e437d60acf
|
||||
ffi (1.17.4-aarch64-linux-gnu) sha256=b208f06f91ffd8f5e1193da3cae3d2ccfc27fc36fba577baf698d26d91c080df
|
||||
|
|
@ -400,23 +402,24 @@ CHECKSUMS
|
|||
fourflusher (2.3.1) sha256=1b3de61c7c791b6a4e64f31e3719eb25203d151746bb519a0292bff1065ccaa9
|
||||
fuzzy_match (2.0.4) sha256=b5de4f95816589c5b5c3ad13770c0af539b75131c158135b3f3bbba75d0cfca5
|
||||
gh_inspector (1.1.3) sha256=04cca7171b87164e053aa43147971d3b7f500fcb58177698886b48a9fc4a1939
|
||||
google-apis-androidpublisher_v3 (0.100.0) sha256=7a82935bee985190e8fe23bf5e53df3a27d65dd084114bb71b846b617de16489
|
||||
google-apis-androidpublisher_v3 (0.101.0) sha256=047380b54a3741a6b3fe454a859eb30ed5a5c322a897315bdea312dfb44e2ab6
|
||||
google-apis-core (0.18.0) sha256=96b057816feeeab448139ed5b5c78eab7fc2a9d8958f0fbc8217dedffad054ee
|
||||
google-apis-iamcredentials_v1 (0.27.0) sha256=9289f29968610754ef11d98b9ec627f0153f3e2616fef839aef096de529f6d1e
|
||||
google-apis-playcustomapp_v1 (0.17.0) sha256=d5bc90b705f3f862bab4998086449b0abe704ee1685a84821daa90ca7fa95a78
|
||||
google-apis-storage_v1 (0.62.0) sha256=f62467c36df53287fb0252ebb4da85f9e25d7b4c5809d045c2aab1fc307760c1
|
||||
google-cloud-core (1.8.0) sha256=e572edcbf189cfcab16590628a516cec3f4f63454b730e59f0b36575120281cf
|
||||
google-cloud-env (2.1.1) sha256=cf4bb8c7d517ee1ea692baedf06e0b56ce68007549d8d5a66481aa9f97f46999
|
||||
google-cloud-env (2.2.2) sha256=94bed40e05a67e9468ce1cb38389fba9a90aa8fc62fc9e173204c1dca59e21e7
|
||||
google-cloud-errors (1.6.0) sha256=1da8476dd706ad04b9d32e3c4b90d07d3463b37d6407cb56d41342ea7647d0a1
|
||||
google-cloud-storage (1.60.0) sha256=b21b752d37945d678a4533be5ef4303f15d33a964d8bc709c7c41c3600f650db
|
||||
googleauth (1.11.2) sha256=7e6bacaeed7aea3dd66dcea985266839816af6633e9f5983c3c2e0e40a44731e
|
||||
google-logging-utils (0.2.0) sha256=675462b4ea5affa825a3442694ca2d75d0069455a1d0956127207498fca3df7b
|
||||
googleauth (1.16.2) sha256=15009502e2e38af71948cda918f230e27d327f6882a1e47967a5a4664930a638
|
||||
highline (2.0.3) sha256=2ddd5c127d4692721486f91737307236fe005352d12a4202e26c48614f719479
|
||||
http-cookie (1.0.8) sha256=b14fe0445cf24bf9ae098633e9b8d42e4c07c3c1f700672b09fbfe32ffd41aa6
|
||||
httpclient (2.9.0) sha256=4b645958e494b2f86c2f8a2f304c959baa273a310e77a2931ddb986d83e498c8
|
||||
i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
|
||||
jmespath (1.6.2) sha256=238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1
|
||||
json (2.19.5) sha256=218a18553e4801d579ca7e0f5bc72bafd776d7397238a1fb4e74db5b0a812c59
|
||||
jwt (2.10.2) sha256=31e1ee46f7359883d5e622446969fe9c118c3da87a0b1dca765ce269c3a0c4f4
|
||||
json (2.19.7) sha256=fe432c8639f6efff69f9d73b518a3705d9581ab93156f981ea72806e1e5bcc3e
|
||||
jwt (3.2.0) sha256=5419b1fe37b1da0982bd07051f573a8b8789ab724c2aa7e785e4784a3ed217d7
|
||||
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
|
||||
mini_magick (4.13.2) sha256=71d6258e0e8a3d04a9a0a09784d5d857b403a198a51dd4f882510435eb95ddd9
|
||||
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
|
||||
|
|
@ -437,7 +440,7 @@ CHECKSUMS
|
|||
public_suffix (4.0.7) sha256=8be161e2421f8d45b0098c042c06486789731ea93dc3a896d30554ee38b573b8
|
||||
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
|
||||
representable (3.2.0) sha256=cc29bf7eebc31653586849371a43ffe36c60b54b0a6365b5f7d95ec34d1ebace
|
||||
retriable (3.4.1) sha256=fb3f114b7d492121c158c01f3d5152b5a615c5b70d5877d0bc08c7ec3725c3bc
|
||||
retriable (3.8.0) sha256=9f2f1b0207594c7817f17f671587b8ec7587387ac6cebda6c941a802bb98a8e5
|
||||
rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
|
||||
rouge (3.28.0) sha256=0d6de482c7624000d92697772ab14e48dca35629f8ddf3f4b21c99183fd70e20
|
||||
ruby-macho (2.5.1) sha256=9075e52e0f9270b552a90b24fcc6219ad149b0d15eae1bc364ecd0ac8984f5c9
|
||||
|
|
|
|||
32
mobile/package-lock.json
generated
32
mobile/package-lock.json
generated
|
|
@ -13,7 +13,7 @@
|
|||
"@react-native-async-storage/async-storage": "^2.1.0",
|
||||
"@react-native-community/netinfo": "^12.0.1",
|
||||
"@react-navigation/bottom-tabs": "^7.2.0",
|
||||
"@react-navigation/native": "^7.0.0",
|
||||
"@react-navigation/native": "^7.2.5",
|
||||
"@react-navigation/native-stack": "^7.2.0",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@tanstack/react-query": "^5.100.10",
|
||||
|
|
@ -21,12 +21,12 @@
|
|||
"axios": "^1.16.0",
|
||||
"react": "19.2.6",
|
||||
"react-native": "^0.85.3",
|
||||
"react-native-app-auth": "^8.3.0",
|
||||
"react-native-app-auth": "^8.4.0",
|
||||
"react-native-document-picker": "^9.3.0",
|
||||
"react-native-haptic-feedback": "^2.3.0",
|
||||
"react-native-image-picker": "^7.2.0",
|
||||
"react-native-keychain": "^9.2.0",
|
||||
"react-native-paper": "^5.13.0",
|
||||
"react-native-paper": "^5.15.3",
|
||||
"react-native-safe-area-context": "^5.8.0",
|
||||
"react-native-screens": "^4.25.2",
|
||||
"react-native-share": "^11.0.0",
|
||||
|
|
@ -2056,9 +2056,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-navigation/core": {
|
||||
"version": "7.17.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.17.4.tgz",
|
||||
"integrity": "sha512-Rv9E2oNNQEkPGpmu9q+vJwGJRSQR6LBg5L+Yo1QHjtwGbHUbjkIKOdYymDZoZYgNzX2OD4rAIlfuzbDKa3cCeA==",
|
||||
"version": "7.17.5",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.17.5.tgz",
|
||||
"integrity": "sha512-6fDCwDTWC7DJn0SDb9DJGRlipaygHIc+2elpZBJI6Crl/2Pu+Z1d6W4jMJ2gZO6iHKf+Pe5sUiQ/uwepGprZtg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^7.5.5",
|
||||
|
|
@ -2098,12 +2098,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-navigation/native": {
|
||||
"version": "7.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.2.4.tgz",
|
||||
"integrity": "sha512-eWC2D3JjhYLId2fVTZhhCiUpWIaPhO9XyEb7Wq8ElmOHyIODlbOzgZ0rKia02OIsDKr9BzZl2sK1dL70yMxDaw==",
|
||||
"version": "7.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.2.5.tgz",
|
||||
"integrity": "sha512-01AAUQiiHQAfTabq+ZyU1/ZWq+AbB/J3v0CB0UTJSON6M6cuadWNsbChzrZUdqQvHrXvg96U5i2PQLJzK3+zpg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^7.17.4",
|
||||
"@react-navigation/core": "^7.17.5",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"nanoid": "^3.3.11",
|
||||
|
|
@ -5932,9 +5932,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-native-app-auth": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-app-auth/-/react-native-app-auth-8.3.0.tgz",
|
||||
"integrity": "sha512-GdoTfi8121KYH0+ALTNQxiECi0Qblrqx3fw74d3dwH5K+nT2GQJ4KZtmw7kkQm6pGp+cIf/JVu4ZhfZqQPyIUw==",
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-app-auth/-/react-native-app-auth-8.4.0.tgz",
|
||||
"integrity": "sha512-9MCjB2tUyEUVIoqfgxMRoYx5dUgiI15bHEAWi4LgZWPe6S3cqaxqgQ/V22hxirTVIpyufag6WCHISTYGKlm9Og==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"invariant": "2.2.4",
|
||||
|
|
@ -6006,9 +6006,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-native-paper": {
|
||||
"version": "5.15.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.15.2.tgz",
|
||||
"integrity": "sha512-e0HoKG+G85e5ckM28qElaqiDD+y0uHLVCUmOWe5094OuB9NDX4kKTY3twCVb2PPgA6lB0pQylu/O4Bvyg/gIYA==",
|
||||
"version": "5.15.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.15.3.tgz",
|
||||
"integrity": "sha512-GEyNTmWElIZgnYw09AjjCNupRYzCmP79uAAyGSyCEUZz7KBz1wtJcC0wVUkozR1Rn3PK/td/9LlR6+F1hzmYvA==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"example",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
"@react-native-async-storage/async-storage": "^2.1.0",
|
||||
"@react-native-community/netinfo": "^12.0.1",
|
||||
"@react-navigation/bottom-tabs": "^7.2.0",
|
||||
"@react-navigation/native": "^7.0.0",
|
||||
"@react-navigation/native": "^7.2.5",
|
||||
"@react-navigation/native-stack": "^7.2.0",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@tanstack/react-query": "^5.100.10",
|
||||
|
|
@ -22,12 +22,12 @@
|
|||
"axios": "^1.16.0",
|
||||
"react": "19.2.6",
|
||||
"react-native": "^0.85.3",
|
||||
"react-native-app-auth": "^8.3.0",
|
||||
"react-native-app-auth": "^8.4.0",
|
||||
"react-native-document-picker": "^9.3.0",
|
||||
"react-native-haptic-feedback": "^2.3.0",
|
||||
"react-native-image-picker": "^7.2.0",
|
||||
"react-native-keychain": "^9.2.0",
|
||||
"react-native-paper": "^5.13.0",
|
||||
"react-native-paper": "^5.15.3",
|
||||
"react-native-safe-area-context": "^5.8.0",
|
||||
"react-native-screens": "^4.25.2",
|
||||
"react-native-share": "^11.0.0",
|
||||
|
|
|
|||
40
web/package-lock.json
generated
40
web/package-lock.json
generated
|
|
@ -13,19 +13,19 @@
|
|||
"@mui/icons-material": "^7.3.1",
|
||||
"@mui/material": "^7.3.1",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@tanstack/react-query": "^5.100.11",
|
||||
"@tanstack/react-query": "^5.100.14",
|
||||
"axios": "^1.16.0",
|
||||
"react": "^19.1.1",
|
||||
"react-dom": "^19.1.1",
|
||||
"react-redux": "^9.2.0",
|
||||
"react-router-dom": "^7.9.4",
|
||||
"react-router-dom": "^7.16.0",
|
||||
"react-toastify": "^11.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"jsdom": "^29.1.1",
|
||||
|
|
@ -1352,9 +1352,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "5.100.11",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.11.tgz",
|
||||
"integrity": "sha512-lmE0994apShXPj8CUxgx4ch5yUJhE9k/+tVwihBvPOyerACWdBocfFg24t8+0RhtlTd7tEgchDkhlCxNssvDxw==",
|
||||
"version": "5.100.14",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.14.tgz",
|
||||
"integrity": "sha512-5X41dGpxgeaHISCRW2oYwcSycZeULZzAunaudXT9ov1KOTj9xwt0CH6hbwqP1/z74ZWF7rYFnDpyYH07XFcZew==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
|
|
@ -1362,12 +1362,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-query": {
|
||||
"version": "5.100.11",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.100.11.tgz",
|
||||
"integrity": "sha512-J0f9s5x3LE1450nNNfYx+e/n0DMa0uOBdFJUy5r0RvmsXd4nB/n0rbHtHI1vYXhikNFan+wf51p6Tmp4c8ucrg==",
|
||||
"version": "5.100.14",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.100.14.tgz",
|
||||
"integrity": "sha512-oOr6aRdSFEwWhzxEkD/9ZcItM3+LjBSkeVmadWKwUssAHTsqd/7bOjWrX4AbvEkoEhgAxzN0Xk6H/aYzXiYBAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tanstack/query-core": "5.100.11"
|
||||
"@tanstack/query-core": "5.100.14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
|
|
@ -1569,9 +1569,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "19.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
|
||||
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
||||
"version": "19.2.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz",
|
||||
"integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"csstype": "^3.2.2"
|
||||
|
|
@ -3275,9 +3275,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "7.15.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.1.tgz",
|
||||
"integrity": "sha512-R8rl9HhgikFYoPJymnUtPXWbnDb3oget6lQnfIoupbt61aT9aOhRkDsY2XRhZRyX1Z/8a5sL74fXmFNm3NRK5A==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.16.0.tgz",
|
||||
"integrity": "sha512-wArC8lVyJb3+jM9OpDyW6hLCizACWkvQR/sSGqSs+o5uEXEtGlqdZ4v8hENR3Jad6i+LRkK93q/+bQAcvl6V1A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "^1.0.1",
|
||||
|
|
@ -3297,12 +3297,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "7.15.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.15.1.tgz",
|
||||
"integrity": "sha512-AzF62gjY6U9rkMq4RfP/r2EVtQ7DMfNMjyOp/flLTCrtRylLiK4wT4pSq6O8rOXZ2eXdZYJPEYe+ifomiv+Igg==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.16.0.tgz",
|
||||
"integrity": "sha512-kMUAbimWB5FVbF4Bce4bJsiKJWLIUHq/mEG8+CFDnCSgltptBiG5nguducmsJeGKytlCvQud9Qhzpn49iduTlA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-router": "7.15.1"
|
||||
"react-router": "7.16.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
|
|
|
|||
|
|
@ -16,19 +16,19 @@
|
|||
"@mui/icons-material": "^7.3.1",
|
||||
"@mui/material": "^7.3.1",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@tanstack/react-query": "^5.100.11",
|
||||
"@tanstack/react-query": "^5.100.14",
|
||||
"axios": "^1.16.0",
|
||||
"react": "^19.1.1",
|
||||
"react-dom": "^19.1.1",
|
||||
"react-redux": "^9.2.0",
|
||||
"react-router-dom": "^7.9.4",
|
||||
"react-router-dom": "^7.16.0",
|
||||
"react-toastify": "^11.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"jsdom": "^29.1.1",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useParams, useNavigate, useBlocker } from 'react-router-dom';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useQuery, useMutation } from '@tanstack/react-query';
|
||||
import {
|
||||
Box,
|
||||
|
|
@ -109,13 +109,17 @@ export default function AdminWorkspace() {
|
|||
return () => window.removeEventListener('beforeunload', handler);
|
||||
}, [dirty]);
|
||||
|
||||
const blocker = useBlocker(
|
||||
useCallback(
|
||||
({ currentLocation, nextLocation }: { currentLocation: { pathname: string }; nextLocation: { pathname: string } }) =>
|
||||
dirty && currentLocation.pathname !== nextLocation.pathname,
|
||||
[dirty],
|
||||
),
|
||||
);
|
||||
const [navBlocked, setNavBlocked] = useState(false);
|
||||
const pendingNavRef = useRef<string | null>(null);
|
||||
|
||||
const guardedNavigate = useCallback((to: string) => {
|
||||
if (dirty) {
|
||||
pendingNavRef.current = to;
|
||||
setNavBlocked(true);
|
||||
} else {
|
||||
navigate(to);
|
||||
}
|
||||
}, [dirty, navigate]);
|
||||
|
||||
const saveMutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
|
|
@ -258,7 +262,7 @@ export default function AdminWorkspace() {
|
|||
>
|
||||
Failed to load proposal{proposalError instanceof Error ? `: ${proposalError.message}` : '.'}
|
||||
</Alert>
|
||||
<Button startIcon={<ArrowBackIcon />} onClick={() => navigate('/admin')} sx={{ mt: 2 }}>
|
||||
<Button startIcon={<ArrowBackIcon />} onClick={() => guardedNavigate('/admin')} sx={{ mt: 2 }}>
|
||||
Back to Dashboard
|
||||
</Button>
|
||||
</Box>
|
||||
|
|
@ -269,7 +273,7 @@ export default function AdminWorkspace() {
|
|||
return (
|
||||
<Box>
|
||||
<Typography color="error">Proposal not found</Typography>
|
||||
<Button startIcon={<ArrowBackIcon />} onClick={() => navigate('/admin')} sx={{ mt: 2 }}>
|
||||
<Button startIcon={<ArrowBackIcon />} onClick={() => guardedNavigate('/admin')} sx={{ mt: 2 }}>
|
||||
Back to Dashboard
|
||||
</Button>
|
||||
</Box>
|
||||
|
|
@ -305,7 +309,7 @@ export default function AdminWorkspace() {
|
|||
<Link
|
||||
component="button"
|
||||
underline="hover"
|
||||
onClick={() => navigate('/admin')}
|
||||
onClick={() => guardedNavigate('/admin')}
|
||||
sx={{ fontSize: 14, color: '#0B5A73', cursor: 'pointer' }}
|
||||
>
|
||||
Admin Queue
|
||||
|
|
@ -550,14 +554,19 @@ export default function AdminWorkspace() {
|
|||
</Card>
|
||||
|
||||
{/* Unsaved Changes Navigation Guard */}
|
||||
<Dialog open={blocker.state === 'blocked'} onClose={() => blocker.reset?.()}>
|
||||
<Dialog open={navBlocked} onClose={() => setNavBlocked(false)}>
|
||||
<DialogTitle>Unsaved Changes</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography>You have unsaved changes. Are you sure you want to leave?</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => blocker.reset?.()}>Stay</Button>
|
||||
<Button variant="contained" color="error" onClick={() => blocker.proceed?.()}>
|
||||
<Button onClick={() => setNavBlocked(false)}>Stay</Button>
|
||||
<Button variant="contained" color="error" onClick={() => {
|
||||
setNavBlocked(false);
|
||||
const dest = pendingNavRef.current ?? '/admin';
|
||||
pendingNavRef.current = null;
|
||||
navigate(dest);
|
||||
}}>
|
||||
Discard & Leave
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ function buildLoginUrl(): string {
|
|||
response_type: 'code',
|
||||
scope: 'openid email profile',
|
||||
redirect_uri: REDIRECT_URI,
|
||||
identity_provider: 'Google',
|
||||
});
|
||||
return `https://${COGNITO_DOMAIN}/oauth2/authorize?${params.toString()}`;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue