Families.Web 1.0.0.0
사진, 동영상, 글, 댓글과 반응을 가족끼리만 공유하는 비공개 앨범·타임라인 서비스입니다.
로딩중...
검색중...
일치하는것 없음
FamilyHomeViewModel.cs
이 파일의 문서화 페이지로 가기
1using Dreamine.Identity;
4
6
15public sealed class FamilyHomeViewModel
16{
25 private readonly IFamilyTenantStore _tenants;
34 private readonly FamilyOptions _opts;
44
78 {
79 _tenants = tenants;
80 _opts = opts;
81 _globalSettings = globalSettings;
82 }
83
92 public int MaxImageSizeMb { get; set; } = 20;
101 public int MaxVideoSizeMb { get; set; } = 500;
102
127 public async Task LoadGlobalSettingsAsync(CancellationToken ct = default)
128 {
129 var settings = await _globalSettings.GetAsync(ct).ConfigureAwait(false);
130 MaxImageSizeMb = settings.MaxImageSizeMb;
131 MaxVideoSizeMb = settings.MaxVideoSizeMb;
132 }
133
158 public async Task SaveGlobalSettingsAsync(CancellationToken ct = default)
159 {
160 await _globalSettings.SaveAsync(
162 .ConfigureAwait(false);
163 StatusMessage = "✅ 전체 설정이 저장되었습니다.";
164 }
165
174 public bool IsAuthenticated { get; private set; }
183 public string LoginPassword { get; set; } = "";
184
201 public Task<bool> LoginAsync()
202 {
203 IsAuthenticated = DreaminePasswordHasher.VerifyPassword(LoginPassword, _opts.SuperAdminPassword);
204 StatusMessage = IsAuthenticated ? "" : "비밀번호가 틀렸습니다.";
205 return Task.FromResult(IsAuthenticated);
206 }
207
216 public IReadOnlyList<FamilyConfig> Tenants { get; private set; } = [];
225 public string StatusMessage { get; private set; } = "";
234 public bool IsLoaded { get; private set; }
235
244 public string NewSlug { get; set; } = "";
253 public string NewFamilyName { get; set; } = "";
262 public string NewPassword { get; set; } = "";
263
288 public async Task LoadAsync(CancellationToken ct = default)
289 {
290 Tenants = await _tenants.GetAllAsync(ct).ConfigureAwait(false);
291 await LoadGlobalSettingsAsync(ct).ConfigureAwait(false);
292 IsLoaded = true;
293 StatusMessage = "";
294 }
295
328 public async Task<bool> CreateTenantAsync(FamilyCurrentUser? owner = null, CancellationToken ct = default)
329 {
330 var slug = NewSlug.Trim().ToLowerInvariant();
331
332 if (string.IsNullOrWhiteSpace(slug))
333 { StatusMessage = "슬러그(URL ID)를 입력해주세요."; return false; }
334
335 if (string.IsNullOrWhiteSpace(NewFamilyName))
336 { StatusMessage = "가족 이름을 입력해주세요."; return false; }
337
338 if (string.IsNullOrWhiteSpace(NewPassword))
339 { StatusMessage = "어드민 비밀번호를 입력해주세요."; return false; }
340
341 if (NewPassword.Length < 8)
342 { StatusMessage = "어드민 비밀번호는 8자 이상이어야 합니다."; return false; }
343
344 if (slug == "admin")
345 { StatusMessage = "'admin'은 슬러그로 사용할 수 없습니다."; return false; }
346
347 if (await _tenants.ExistsAsync(slug, ct).ConfigureAwait(false))
348 { StatusMessage = $"이미 존재하는 슬러그입니다: {slug}"; return false; }
349
350 var config = new FamilyConfig
351 {
352 Slug = slug,
353 FamilyName = NewFamilyName.Trim(),
354 PasswordHash = DreaminePasswordHasher.HashPassword(NewPassword),
355 IsPublished = true
356 };
357
358 if (owner?.IsAuthenticated == true)
359 {
360 config.OwnerUserId = owner.Id;
361 config.OwnerProvider = owner.Provider;
362 config.OwnerEmail = owner.Email;
363 config.OwnerDisplayName = owner.DisplayName;
364 config.OwnerLinkedAt = DateTime.Now;
365 config.AdminUsers.Add(new FamilyAdminUser
366 {
367 UserId = owner.Id,
368 Provider = owner.Provider,
369 Email = owner.Email,
370 DisplayName = owner.DisplayName,
371 Role = "Owner",
372 AddedAt = DateTime.Now
373 });
374 }
375
376 await _tenants.SaveAsync(config, ct).ConfigureAwait(false);
377 await LoadAsync(ct).ConfigureAwait(false);
378
379 NewSlug = "";
380 NewFamilyName = "";
381 NewPassword = "";
382
383 StatusMessage = $"✅ '{slug}' 앨범이 생성되었습니다.";
384 return true;
385 }
386
435 public async Task SetDisplayAsync(string slug, bool showOnHome, int pinOrder, CancellationToken ct = default)
436 {
437 var config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
438 if (config is null) return;
439 config.ShowOnHome = showOnHome;
440 config.PinOrder = pinOrder;
441 await _tenants.SaveAsync(config, ct).ConfigureAwait(false);
442 await LoadAsync(ct).ConfigureAwait(false);
443 StatusMessage = $"✅ '{slug}' 노출 설정 저장됨";
444 }
445
478 public async Task DeleteTenantAsync(string slug, CancellationToken ct = default)
479 {
480 try
481 {
482 await _tenants.DeleteAsync(slug, ct).ConfigureAwait(false);
483 await LoadAsync(ct).ConfigureAwait(false);
484 StatusMessage = $"🗑 '{slug}' 삭제 완료.";
485 }
486 catch (Exception ex)
487 {
488 StatusMessage = $"삭제 오류: {ex.Message}";
489 }
490 }
491
532 public async Task SetMaxImageSizeAsync(string slug, int? maxImageSizeMb, CancellationToken ct = default)
533 {
534 var config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
535 if (config is null) return;
536 config.MaxImageSizeMb = maxImageSizeMb;
537 await _tenants.SaveAsync(config, ct).ConfigureAwait(false);
538 await LoadAsync(ct).ConfigureAwait(false);
539 StatusMessage = $"✅ '{slug}' 이미지 용량 제한 저장됨";
540 }
541
582 public async Task SetMaxVideoSizeAsync(string slug, int? maxVideoSizeMb, CancellationToken ct = default)
583 {
584 var config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
585 if (config is null) return;
586 config.MaxVideoSizeMb = maxVideoSizeMb;
587 await _tenants.SaveAsync(config, ct).ConfigureAwait(false);
588 await LoadAsync(ct).ConfigureAwait(false);
589 StatusMessage = $"✅ '{slug}' 동영상 용량 제한 저장됨";
590 }
591}
record FamilyCurrentUser(string Id, string Provider, string Email, string DisplayName)
async Task LoadGlobalSettingsAsync(CancellationToken ct=default)
async Task LoadAsync(CancellationToken ct=default)
async Task SetMaxImageSizeAsync(string slug, int? maxImageSizeMb, CancellationToken ct=default)
async Task< bool > CreateTenantAsync(FamilyCurrentUser? owner=null, CancellationToken ct=default)
async Task DeleteTenantAsync(string slug, CancellationToken ct=default)
readonly IGlobalSettingsStore _globalSettings
FamilyHomeViewModel(IFamilyTenantStore tenants, FamilyOptions opts, IGlobalSettingsStore globalSettings)
async Task SaveGlobalSettingsAsync(CancellationToken ct=default)
async Task SetDisplayAsync(string slug, bool showOnHome, int pinOrder, CancellationToken ct=default)
async Task SetMaxVideoSizeAsync(string slug, int? maxVideoSizeMb, CancellationToken ct=default)