WeddingPlatform.Web
1.0.0.0
지도, 갤러리, 방명록, 계좌 안내와 배경음악을 링크 하나에 담는 무료 모바일 청첩장 서비스입니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
JsonTenantStore.cs
이 파일의 문서화 페이지로 가기
1
using
System.IO;
2
using
System.Text.Json;
3
using
System.Text.Json.Serialization;
4
using
Wedding.Common;
5
using
WeddingPlatform.Models
;
6
7
namespace
WeddingPlatform.Services
;
8
17
public
sealed
class
JsonTenantStore
:
ITenantStore
18
{
27
private
readonly
string
_dataRoot
;
36
private
static
readonly SemaphoreSlim
_gate
=
new
(1, 1);
37
46
private
static
readonly JsonSerializerOptions
_jsonOpts
=
new
()
47
{
48
WriteIndented =
true
,
49
PropertyNameCaseInsensitive =
true
,
50
Converters = {
new
WeddingLayoutModeJsonConverter(),
new
JsonStringEnumConverter() }
51
};
52
69
public
JsonTenantStore
(
WeddingOptions
opts)
70
{
71
_dataRoot
= opts.
ResolvedDataPath
;
72
Directory.CreateDirectory(
_dataRoot
);
73
}
74
99
public
string
GetTenantDataPath
(
string
slug) =>
100
Path.Combine(
_dataRoot
,
Sanitize
(slug));
101
134
public
async Task<TenantConfig?>
GetAsync
(
string
slug, CancellationToken ct =
default
)
135
{
136
var path =
ConfigPath
(slug);
137
if
(!File.Exists(path))
return
null
;
138
139
await
_gate
.WaitAsync(ct).ConfigureAwait(
false
);
140
try
141
{
142
return
await
ReadTenantAsync
(path, ct).ConfigureAwait(
false
);
143
}
144
finally
{
_gate
.Release(); }
145
}
146
171
public
async Task<IReadOnlyList<TenantConfig>>
GetAllAsync
(CancellationToken ct =
default
)
172
{
173
var list =
new
List<TenantConfig>();
174
if
(!Directory.Exists(
_dataRoot
))
return
list;
175
176
foreach
(var dir
in
Directory.GetDirectories(
_dataRoot
))
177
{
178
var cfg = Path.Combine(dir,
"config.json"
);
179
if
(!File.Exists(cfg))
continue
;
180
181
await
_gate
.WaitAsync(ct).ConfigureAwait(
false
);
182
try
183
{
184
var t = await
ReadTenantAsync
(cfg, ct).ConfigureAwait(
false
);
185
if
(t !=
null
) list.Add(t);
186
}
187
catch
(JsonException ex)
188
{
189
LogTenantReadError
(cfg, ex);
190
}
191
finally
{
_gate
.Release(); }
192
}
193
return
list;
194
}
195
228
public
async Task
SaveAsync
(
TenantConfig
config, CancellationToken ct =
default
)
229
{
230
var dir =
GetTenantDataPath
(config.
Slug
);
231
Directory.CreateDirectory(dir);
232
Directory.CreateDirectory(Path.Combine(dir,
"gallery"
));
233
Directory.CreateDirectory(Path.Combine(dir,
"thumb"
));
234
235
var tmp =
ConfigPath
(config.
Slug
) +
".tmp"
;
236
await
_gate
.WaitAsync(ct).ConfigureAwait(
false
);
237
try
238
{
239
await
using
(var fs = File.Create(tmp))
240
await JsonSerializer.SerializeAsync(fs, config,
_jsonOpts
, ct).ConfigureAwait(
false
);
241
242
File.Copy(tmp,
ConfigPath
(config.
Slug
), overwrite:
true
);
243
File.Delete(tmp);
244
}
245
finally
{
_gate
.Release(); }
246
}
247
280
public
Task<bool>
ExistsAsync
(
string
slug, CancellationToken ct =
default
) =>
281
Task.FromResult(File.Exists(
ConfigPath
(slug)));
282
315
public
Task
DeleteAsync
(
string
slug, CancellationToken ct =
default
)
316
{
317
var dir =
GetTenantDataPath
(slug);
318
if
(Directory.Exists(dir))
319
Directory.Delete(dir, recursive:
true
);
320
return
Task.CompletedTask;
321
}
322
347
private
string
ConfigPath
(
string
slug) =>
348
Path.Combine(
GetTenantDataPath
(slug),
"config.json"
);
349
374
private
static
string
Sanitize
(
string
slug) =>
375
string
.Concat(slug.ToLowerInvariant().Split(Path.GetInvalidFileNameChars()));
376
409
private
static
async Task<TenantConfig?>
ReadTenantAsync
(
string
path, CancellationToken ct)
410
{
411
var json = await File.ReadAllTextAsync(path, ct).ConfigureAwait(
false
);
412
LogLegacyLayoutModeFallback
(path, json);
413
return
JsonSerializer.Deserialize<
TenantConfig
>(json,
_jsonOpts
);
414
}
415
440
private
static
void
LogLegacyLayoutModeFallback
(
string
path,
string
json)
441
{
442
var raw =
TryGetDesignLayoutMode
(json);
443
if
(raw is
null
||
IsCanonicalLayoutMode
(raw))
return
;
444
445
Console.Error.WriteLine($
"[JsonTenantStore] Legacy DesignSettings.LayoutMode '{raw}' in '{path}' was loaded with compatibility fallback."
);
446
}
447
472
private
static
string
?
TryGetDesignLayoutMode
(
string
json)
473
{
474
try
475
{
476
using
var doc = JsonDocument.Parse(json);
477
if
(!
TryGetProperty
(doc.RootElement,
"DesignSettings"
, out var design))
return
null
;
478
if
(!
TryGetProperty
(design,
"LayoutMode"
, out var layout))
return
null
;
479
480
return
layout.ValueKind
switch
481
{
482
JsonValueKind.String => layout.GetString(),
483
JsonValueKind.Null =>
""
,
484
JsonValueKind.Number => layout.GetRawText(),
485
_ => layout.GetRawText(),
486
};
487
}
488
catch
(JsonException)
489
{
490
return
null
;
491
}
492
}
493
534
private
static
bool
TryGetProperty
(JsonElement element,
string
name, out JsonElement value)
535
{
536
foreach
(var property
in
element.EnumerateObject())
537
{
538
if
(
string
.Equals(property.Name, name, StringComparison.OrdinalIgnoreCase))
539
{
540
value =
property
.Value;
541
return
true
;
542
}
543
}
544
545
value =
default
;
546
return
false
;
547
}
548
573
private
static
bool
IsCanonicalLayoutMode
(
string
? value) =>
574
value is not
null
575
&& (
string
.Equals(value,
"WebPage"
, StringComparison.Ordinal)
576
||
string
.Equals(value,
"TabMenu"
, StringComparison.Ordinal)
577
||
string
.Equals(value,
"Gallery"
, StringComparison.Ordinal)
578
||
string
.Equals(value,
"Story"
, StringComparison.Ordinal)
579
||
string
.Equals(value,
"Card"
, StringComparison.Ordinal)
580
||
string
.Equals(value,
"PhotoBook"
, StringComparison.Ordinal));
581
606
private
static
void
LogTenantReadError
(
string
path, JsonException ex)
607
{
608
Console.Error.WriteLine($
"[JsonTenantStore] Skipped invalid tenant JSON '{path}': {ex.Message}"
);
609
}
610
}
WeddingPlatform.Models
Definition
AccountInfo.cs:1
WeddingPlatform.Services
Definition
CsvGuestbookStorage.cs:6
WeddingPlatform.Models.TenantConfig
Definition
TenantConfig.cs:12
WeddingPlatform.Models.TenantConfig.Slug
string Slug
Definition
TenantConfig.cs:21
WeddingPlatform.Services.ITenantStore
Definition
ITenantStore.cs:14
WeddingPlatform.Services.JsonTenantStore._gate
static readonly SemaphoreSlim _gate
Definition
JsonTenantStore.cs:36
WeddingPlatform.Services.JsonTenantStore.TryGetDesignLayoutMode
static ? string TryGetDesignLayoutMode(string json)
Definition
JsonTenantStore.cs:472
WeddingPlatform.Services.JsonTenantStore.ReadTenantAsync
static async Task< TenantConfig?> ReadTenantAsync(string path, CancellationToken ct)
Definition
JsonTenantStore.cs:409
WeddingPlatform.Services.JsonTenantStore.IsCanonicalLayoutMode
static bool IsCanonicalLayoutMode(string? value)
Definition
JsonTenantStore.cs:573
WeddingPlatform.Services.JsonTenantStore.GetAllAsync
async Task< IReadOnlyList< TenantConfig > > GetAllAsync(CancellationToken ct=default)
Definition
JsonTenantStore.cs:171
WeddingPlatform.Services.JsonTenantStore.JsonTenantStore
JsonTenantStore(WeddingOptions opts)
Definition
JsonTenantStore.cs:69
WeddingPlatform.Services.JsonTenantStore.GetTenantDataPath
string GetTenantDataPath(string slug)
Definition
JsonTenantStore.cs:99
WeddingPlatform.Services.JsonTenantStore.Sanitize
static string Sanitize(string slug)
Definition
JsonTenantStore.cs:374
WeddingPlatform.Services.JsonTenantStore.TryGetProperty
static bool TryGetProperty(JsonElement element, string name, out JsonElement value)
Definition
JsonTenantStore.cs:534
WeddingPlatform.Services.JsonTenantStore.SaveAsync
async Task SaveAsync(TenantConfig config, CancellationToken ct=default)
Definition
JsonTenantStore.cs:228
WeddingPlatform.Services.JsonTenantStore.ConfigPath
string ConfigPath(string slug)
Definition
JsonTenantStore.cs:347
WeddingPlatform.Services.JsonTenantStore.GetAsync
async Task< TenantConfig?> GetAsync(string slug, CancellationToken ct=default)
Definition
JsonTenantStore.cs:134
WeddingPlatform.Services.JsonTenantStore._jsonOpts
static readonly JsonSerializerOptions _jsonOpts
Definition
JsonTenantStore.cs:46
WeddingPlatform.Services.JsonTenantStore.ExistsAsync
Task< bool > ExistsAsync(string slug, CancellationToken ct=default)
Definition
JsonTenantStore.cs:280
WeddingPlatform.Services.JsonTenantStore._dataRoot
readonly string _dataRoot
Definition
JsonTenantStore.cs:27
WeddingPlatform.Services.JsonTenantStore.LogLegacyLayoutModeFallback
static void LogLegacyLayoutModeFallback(string path, string json)
Definition
JsonTenantStore.cs:440
WeddingPlatform.Services.JsonTenantStore.LogTenantReadError
static void LogTenantReadError(string path, JsonException ex)
Definition
JsonTenantStore.cs:606
WeddingPlatform.Services.JsonTenantStore.DeleteAsync
Task DeleteAsync(string slug, CancellationToken ct=default)
Definition
JsonTenantStore.cs:315
WeddingPlatform.Services.WeddingOptions
Definition
WeddingOptions.cs:15
WeddingPlatform.Services.WeddingOptions.ResolvedDataPath
string ResolvedDataPath
Definition
WeddingOptions.cs:62
Services
JsonTenantStore.cs
다음에 의해 생성됨 :
1.17.0