X\choro преди 10 месеца
родител
ревизия
34f035eec7
променени са 51 файла, в които са добавени 2453 реда и са изтрити 710 реда
  1. BIN
      backend/.vs/ProjectEvaluation/bitforum.metadata.v9.bin
  2. BIN
      backend/.vs/ProjectEvaluation/bitforum.projects.v9.bin
  3. BIN
      backend/.vs/ProjectEvaluation/bitforum.strings.v9.bin
  4. BIN
      backend/.vs/bitforum/CopilotIndices/17.12.38.29086/CodeChunks.db
  5. BIN
      backend/.vs/bitforum/CopilotIndices/17.12.38.29086/SemanticSymbols.db
  6. BIN
      backend/.vs/bitforum/CopilotIndices/17.12.38.29086/SemanticSymbols.db-shm
  7. BIN
      backend/.vs/bitforum/CopilotIndices/17.12.38.29086/SemanticSymbols.db-wal
  8. BIN
      backend/.vs/bitforum/DesignTimeBuild/.dtbcache.v2
  9. BIN
      backend/.vs/bitforum/v17/.futdcache.v2
  10. BIN
      backend/.vs/bitforum/v17/.suo
  11. 9 94
      backend/.vs/bitforum/v17/DocumentLayout.backup.json
  12. 10 78
      backend/.vs/bitforum/v17/DocumentLayout.json
  13. 7 1
      backend/Constants/MenuData.cs
  14. 11 0
      backend/Constants/UserData.cs
  15. 1 2
      backend/Controllers/Director/UserController.cs
  16. 8 1
      backend/Controllers/Setting/BasicController.cs
  17. 7 0
      backend/Database/DefaultDbContext.cs
  18. 668 0
      backend/Migrations/DefaultDb/20250124015524_AddMember.Designer.cs
  19. 191 0
      backend/Migrations/DefaultDb/20250124015524_AddMember.cs
  20. 668 0
      backend/Migrations/DefaultDb/20250124020320_UpdateMember.Designer.cs
  21. 22 0
      backend/Migrations/DefaultDb/20250124020320_UpdateMember.cs
  22. 305 1
      backend/Migrations/DefaultDb/DefaultDbContextModelSnapshot.cs
  23. 4 3
      backend/Models/Page/Banner/Item.cs
  24. 4 2
      backend/Models/Page/Banner/Position.cs
  25. 2 0
      backend/Models/Page/Document.cs
  26. 4 2
      backend/Models/Page/Faq/Category.cs
  27. 4 3
      backend/Models/Page/Faq/Item.cs
  28. 2 0
      backend/Models/Page/Popup.cs
  29. 152 0
      backend/Models/User/Member.cs
  30. 37 0
      backend/Models/User/MemberApprove.cs
  31. 61 0
      backend/Models/User/MemberGrade.cs
  32. 31 9
      backend/Services/EmailSender.cs
  33. 14 1
      backend/Views/Setting/Basic.cshtml
  34. 7 0
      backend/appsettings.json
  35. 7 0
      backend/bin/Debug/net8.0/appsettings.json
  36. BIN
      backend/bin/Debug/net8.0/bitforum.dll
  37. BIN
      backend/bin/Debug/net8.0/bitforum.exe
  38. BIN
      backend/bin/Debug/net8.0/bitforum.pdb
  39. 2 2
      backend/bitforum.csproj
  40. BIN
      backend/obj/Debug/net8.0/apphost.exe
  41. 1 1
      backend/obj/Debug/net8.0/bitforum.AssemblyInfo.cs
  42. 1 1
      backend/obj/Debug/net8.0/bitforum.AssemblyInfoInputs.cache
  43. 1 1
      backend/obj/Debug/net8.0/bitforum.csproj.CoreCompileInputs.cache
  44. 0 1
      backend/obj/Debug/net8.0/bitforum.csproj.FileListAbsolute.txt
  45. BIN
      backend/obj/Debug/net8.0/bitforum.dll
  46. BIN
      backend/obj/Debug/net8.0/bitforum.pdb
  47. BIN
      backend/obj/Debug/net8.0/ref/bitforum.dll
  48. BIN
      backend/obj/Debug/net8.0/refint/bitforum.dll
  49. 212 212
      backend/obj/Debug/net8.0/staticwebassets.build.json
  50. 0 1
      backend/obj/Debug/net8.0/staticwebassets.removed.txt
  51. 0 294
      backend/obj/Debug/net8.0/staticwebassets.upToDateCheck.txt

BIN
backend/.vs/ProjectEvaluation/bitforum.metadata.v9.bin


BIN
backend/.vs/ProjectEvaluation/bitforum.projects.v9.bin


BIN
backend/.vs/ProjectEvaluation/bitforum.strings.v9.bin


BIN
backend/.vs/bitforum/CopilotIndices/17.12.38.29086/CodeChunks.db


BIN
backend/.vs/bitforum/CopilotIndices/17.12.38.29086/SemanticSymbols.db


BIN
backend/.vs/bitforum/CopilotIndices/17.12.38.29086/SemanticSymbols.db-shm


BIN
backend/.vs/bitforum/CopilotIndices/17.12.38.29086/SemanticSymbols.db-wal


BIN
backend/.vs/bitforum/DesignTimeBuild/.dtbcache.v2


BIN
backend/.vs/bitforum/v17/.futdcache.v2


BIN
backend/.vs/bitforum/v17/.suo


+ 9 - 94
backend/.vs/bitforum/v17/DocumentLayout.backup.json

@@ -3,28 +3,8 @@
   "WorkspaceRootPath": "E:\\workspace\\bitforum\\backend\\",
   "Documents": [
     {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\faq\\item\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\faq\\item\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\faq\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\faq\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\controllers\\page\\banner\\itemcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:controllers\\page\\banner\\itemcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\banner\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\banner\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\banner\\item\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\banner\\item\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\banner\\item\\index.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\banner\\item\\index.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
+      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\models\\user\\member.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:models\\user\\member.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     }
   ],
   "DocumentGroupContainers": [
@@ -59,79 +39,14 @@
             {
               "$type": "Document",
               "DocumentIndex": 0,
-              "Title": "Edit.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "RelativeToolTip": "Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "ViewState": "AgIAACcAAAAAAAAAAAAAAE8AAAAjAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:10:00.435Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 1,
-              "Title": "Write.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Write.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Faq\\Item\\Write.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Write.cshtml",
-              "RelativeToolTip": "Views\\Page\\Faq\\Item\\Write.cshtml",
-              "ViewState": "AgIAAA8AAAAAAAAAAAAAADgAAAAeAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:09:13.483Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 5,
-              "Title": "Index.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Index.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Banner\\Item\\Index.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Index.cshtml",
-              "RelativeToolTip": "Views\\Page\\Banner\\Item\\Index.cshtml",
-              "ViewState": "AgIAABUAAAAAAAAAAAAAACQAAAAnAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:00:44.979Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 4,
-              "Title": "Edit.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Edit.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Banner\\Item\\Edit.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Edit.cshtml",
-              "RelativeToolTip": "Views\\Page\\Banner\\Item\\Edit.cshtml",
-              "ViewState": "AgIAAAAAAAAAAAAAAAAAAAoAAAAlAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:00:18.225Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 3,
-              "Title": "Write.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Write.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Banner\\Item\\Write.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Write.cshtml",
-              "RelativeToolTip": "Views\\Page\\Banner\\Item\\Write.cshtml",
-              "ViewState": "AgIAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T15:59:49.056Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 2,
-              "Title": "ItemController.cs",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Controllers\\Page\\Banner\\ItemController.cs",
-              "RelativeDocumentMoniker": "Controllers\\Page\\Banner\\ItemController.cs",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Controllers\\Page\\Banner\\ItemController.cs",
-              "RelativeToolTip": "Controllers\\Page\\Banner\\ItemController.cs",
-              "ViewState": "AgIAAC0AAAAAAAAAAAAAADwAAABPAAAAAAAAAA==",
+              "Title": "Member.cs",
+              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Models\\User\\Member.cs",
+              "RelativeDocumentMoniker": "Models\\User\\Member.cs",
+              "ToolTip": "E:\\workspace\\bitforum\\backend\\Models\\User\\Member.cs",
+              "RelativeToolTip": "Models\\User\\Member.cs",
+              "ViewState": "AgIAAAEAAAAAAAAAAAAAABIAAAAAAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2025-01-20T15:59:35.594Z",
+              "WhenOpened": "2025-01-22T19:33:26.617Z",
               "EditorCaption": ""
             }
           ]

+ 10 - 78
backend/.vs/bitforum/v17/DocumentLayout.json

@@ -3,24 +3,8 @@
   "WorkspaceRootPath": "E:\\workspace\\bitforum\\backend\\",
   "Documents": [
     {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\popup\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\popup\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\popup\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\popup\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\banner\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\banner\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\faq\\item\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\faq\\item\\edit.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\views\\page\\faq\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}",
-      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:views\\page\\faq\\item\\write.cshtml||{40D31677-CBC0-4297-A9EF-89D907823A98}"
+      "AbsoluteMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|e:\\workspace\\bitforum\\backend\\models\\user\\member.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+      "RelativeMoniker": "D:0:0:{07B22B2C-9DC6-4B8E-AA16-8F826E758BDD}|bitforum.csproj|solutionrelative:models\\user\\member.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     }
   ],
   "DocumentGroupContainers": [
@@ -55,66 +39,14 @@
             {
               "$type": "Document",
               "DocumentIndex": 0,
-              "Title": "Write.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Popup\\Write.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Popup\\Write.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Popup\\Write.cshtml",
-              "RelativeToolTip": "Views\\Page\\Popup\\Write.cshtml",
-              "ViewState": "AgIAACcAAAAAAAAAAAAAAEIAAABVAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:18:20.61Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 1,
-              "Title": "Edit.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Popup\\Edit.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Popup\\Edit.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Popup\\Edit.cshtml",
-              "RelativeToolTip": "Views\\Page\\Popup\\Edit.cshtml",
-              "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:18:13.432Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 2,
-              "Title": "Write.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Write.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Banner\\Item\\Write.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Banner\\Item\\Write.cshtml",
-              "RelativeToolTip": "Views\\Page\\Banner\\Item\\Write.cshtml",
-              "ViewState": "AgIAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:18:08.376Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 4,
-              "Title": "Write.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Write.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Faq\\Item\\Write.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Write.cshtml",
-              "RelativeToolTip": "Views\\Page\\Faq\\Item\\Write.cshtml",
-              "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:17:54.339Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 3,
-              "Title": "Edit.cshtml",
-              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "RelativeDocumentMoniker": "Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "ToolTip": "E:\\workspace\\bitforum\\backend\\Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "RelativeToolTip": "Views\\Page\\Faq\\Item\\Edit.cshtml",
-              "ViewState": "AgIAAAAAAAAAAAAAAAAAACAAAAAjAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
-              "WhenOpened": "2025-01-20T16:17:53.526Z",
+              "Title": "Member.cs",
+              "DocumentMoniker": "E:\\workspace\\bitforum\\backend\\Models\\User\\Member.cs",
+              "RelativeDocumentMoniker": "Models\\User\\Member.cs",
+              "ToolTip": "E:\\workspace\\bitforum\\backend\\Models\\User\\Member.cs*",
+              "RelativeToolTip": "Models\\User\\Member.cs*",
+              "ViewState": "AgIAAF8AAAAAAAAAAAAvwJAAAAAfAAAAAAAAAA==",
+              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+              "WhenOpened": "2025-01-22T19:33:26.617Z",
               "EditorCaption": ""
             }
           ]

+ 7 - 1
backend/Constants/MenuData.cs

@@ -147,12 +147,18 @@ namespace bitforum.Constants
                         new Menu
                         {
                             Id = 404,
+                            Name = "로그인 기록",
+                            Path = "/User/Logs/Login"
+                        },
+                        new Menu
+                        {
+                            Id = 405,
                             Name = "별명 변경 내역",
                             Path = "/User/Logs/Name"
                         },
                         new Menu
                         {
-                            Id = 405,
+                            Id = 406,
                             Name = "이메일 변경 내역",
                             Path = "/User/Logs/Email"
                         }

+ 11 - 0
backend/Constants/UserData.cs

@@ -0,0 +1,11 @@
+namespace bitforum.Constants
+{
+    /// <summary>
+    /// 성별을 나타내는 열거형
+    /// </summary>
+    public enum Gender
+    {
+        Male = 1,
+        Female = 2
+    }
+}

+ 1 - 2
backend/Controllers/Director/UserController.cs

@@ -34,8 +34,7 @@ namespace bitforum.Controllers.Director
         public async Task<IActionResult> Index()
         {
             var currentUser = await _userManager.GetUserAsync(User);
-            var allUsers = await _userManager.Users.Where(a => a.Id != currentUser.Id).ToListAsync();
-
+            var allUsers = await _userManager.Users.ToListAsync();
 
             // 사용자와 역할 정보를 매핑
             var userViewModels = new List<UserViewModel>();

+ 8 - 1
backend/Controllers/Setting/BasicController.cs

@@ -4,6 +4,8 @@ using bitforum.Repository;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using bitforum.Helpers;
+using bitforum.Models.User;
+using Microsoft.AspNetCore.Identity;
 
 namespace bitforum.Controllers.Setting
 {
@@ -13,12 +15,14 @@ namespace bitforum.Controllers.Setting
     {
         private readonly ILogger<BasicController> _logger;
         private readonly ConfigRepository _configRepository;
+        private readonly UserManager<ApplicationUser> _userManager;
         private readonly string _ViewPath = "~/Views/Setting/Basic.cshtml";
 
-        public BasicController(ILogger<BasicController> logger, ConfigRepository configRepository)
+        public BasicController(ILogger<BasicController> logger, ConfigRepository configRepository, UserManager<ApplicationUser> userManager)
         {
             _logger = logger;
             _configRepository = configRepository;
+            _userManager = userManager;
         }
 
         [HttpGet("Basic")]
@@ -26,6 +30,9 @@ namespace bitforum.Controllers.Setting
         {
             ViewBag.config = _configRepository.GetAll();
 
+            // 최고 관리자
+            ViewBag.Admin = _userManager.GetUsersInRoleAsync("Admin").Result?.ToList();
+
             return View(_ViewPath);
         }
 

+ 7 - 0
backend/Database/DefaultDbContext.cs

@@ -3,11 +3,13 @@ using bitforum.Models;
 using bitforum.Models.Page;
 using bitforum.Models.Page.Faq;
 using bitforum.Models.Page.Banner;
+using bitforum.Models.User;
 
 public class DefaultDbContext : DbContext
 {
     public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options) { }
 
+    // 공통 사항
     public DbSet<Config> Config { get; set; }
     public DbSet<Document> Document { get; set; }
     public DbSet<FaqCategory> FaqCategory { get; set; }
@@ -15,4 +17,9 @@ public class DefaultDbContext : DbContext
     public DbSet<Popup> Popup { get; set; }
     public DbSet<BannerPosition> BannerPosition { get; set; }
     public DbSet<BannerItem> BannerItem { get; set; }
+
+    // 회원
+    public DbSet<Member> Member { get; set; }
+    public DbSet<MemberApprove> MemberApprove { get; set; }
+    public DbSet<MemberGrade> MemberGrade { get; set; }
 }

+ 668 - 0
backend/Migrations/DefaultDb/20250124015524_AddMember.Designer.cs

@@ -0,0 +1,668 @@
+// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace bitforum.Migrations.DefaultDb
+{
+    [DbContext(typeof(DefaultDbContext))]
+    [Migration("20250124015524_AddMember")]
+    partial class AddMember
+    {
+        /// <inheritdoc />
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "8.0.0")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+            SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+            modelBuilder.Entity("bitforum.Models.Config", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Key")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(450)");
+
+                    b.Property<string>("Value")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("Key")
+                        .IsUnique();
+
+                    b.ToTable("Config");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerItem", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("EndAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Height")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Image")
+                        .HasMaxLength(1024)
+                        .HasColumnType("nvarchar(1024)");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Link")
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<int>("PositionID")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("StartAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.Property<int>("Width")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("PositionID");
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_BannerItem_IsActive");
+
+                    b.HasIndex(new[] { "Order" }, "IX_BannerItem_Order");
+
+                    b.ToTable("BannerItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerPosition", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("nvarchar(30)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "Code" }, "IX_BannerPosition_Code")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_BannerPosition_IsActive");
+
+                    b.ToTable("BannerPosition");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Document", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("nvarchar(30)");
+
+                    b.Property<string>("Content")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "Code" }, "IX_Document_Code")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_Document_IsActive");
+
+                    b.ToTable("Document");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqCategory", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("nvarchar(30)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "Code" }, "IX_FaqCategory_Code")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "Order" }, "IX_FaqCategory_Order");
+
+                    b.ToTable("FaqCategory");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqItem", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Answer")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<int>("CategoryID")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Question")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("CategoryID");
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_FaqItem_IsActive");
+
+                    b.HasIndex(new[] { "Order" }, "IX_FaqItem_Order");
+
+                    b.ToTable("FaqItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Popup", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Content")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("EndAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Link")
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("StartAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_Popup_IsActive");
+
+                    b.ToTable("Popup");
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.Member", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("PK");
+
+                    b.Property<DateTime?>("AuthCertifiedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("본인인증 일시");
+
+                    b.Property<DateOnly?>("Birthday")
+                        .HasMaxLength(10)
+                        .HasColumnType("date")
+                        .HasComment("생년월일");
+
+                    b.Property<long>("Coin")
+                        .HasColumnType("bigint")
+                        .HasComment("코인");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("가입 일시");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("탈퇴 일시");
+
+                    b.Property<string>("DeviceInfo")
+                        .HasMaxLength(400)
+                        .HasColumnType("nvarchar(400)")
+                        .HasComment("로그인 단말기 정보");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("이메일");
+
+                    b.Property<DateTime?>("EmailVerifiedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("이메일 인증 일시");
+
+                    b.Property<int>("Exp")
+                        .HasColumnType("int")
+                        .HasComment("경험치");
+
+                    b.Property<string>("FirstName")
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("본명(성)");
+
+                    b.Property<int>("Followed")
+                        .HasColumnType("int")
+                        .HasComment("구독자");
+
+                    b.Property<int>("Following")
+                        .HasColumnType("int")
+                        .HasComment("구독 중");
+
+                    b.Property<string>("FullName")
+                        .HasMaxLength(40)
+                        .HasColumnType("nvarchar(40)")
+                        .HasComment("본명");
+
+                    b.Property<int?>("Gender")
+                        .HasMaxLength(6)
+                        .HasColumnType("int")
+                        .HasComment("성별");
+
+                    b.Property<int?>("GradeID")
+                        .HasColumnType("int")
+                        .HasComment("회원등급 ID");
+
+                    b.Property<string>("Intro")
+                        .HasMaxLength(1000)
+                        .HasColumnType("nvarchar(1000)")
+                        .HasComment("자기소개");
+
+                    b.Property<bool>("IsAdmin")
+                        .HasColumnType("bit")
+                        .HasComment("운영진 여부");
+
+                    b.Property<bool>("IsAuthCertified")
+                        .HasColumnType("bit")
+                        .HasComment("본인 인증 여부");
+
+                    b.Property<bool>("IsDenied")
+                        .HasColumnType("bit")
+                        .HasComment("차단 여부");
+
+                    b.Property<bool>("IsEmailVerified")
+                        .HasColumnType("bit")
+                        .HasComment("이메일 인증 여부");
+
+                    b.Property<bool>("IsWithdraw")
+                        .HasColumnType("bit")
+                        .HasComment("탈퇴 여부");
+
+                    b.Property<DateTime?>("LastLoginAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("마지막 로그인 일시");
+
+                    b.Property<string>("LastLoginIp")
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("마지막 로그인 IP");
+
+                    b.Property<string>("LastName")
+                        .HasMaxLength(40)
+                        .HasColumnType("nvarchar(40)")
+                        .HasComment("본명(이름)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("별명");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("비밀번호");
+
+                    b.Property<DateTime>("PasswordUpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("비밀번호 변경 일시");
+
+                    b.Property<string>("Phone")
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("연락처");
+
+                    b.Property<string>("Photo")
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("사진");
+
+                    b.Property<string>("SID")
+                        .IsRequired()
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("SID");
+
+                    b.Property<string>("SignupIP")
+                        .IsRequired()
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("회원가입 시 IP");
+
+                    b.Property<string>("Summary")
+                        .HasMaxLength(50)
+                        .HasColumnType("nvarchar(50)")
+                        .HasComment("한마디");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("수정 일시");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("GradeID");
+
+                    b.HasIndex(new[] { "Email" }, "IX_Member_Email")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "Name" }, "IX_Member_Name")
+                        .IsUnique()
+                        .HasFilter("[Name] IS NOT NULL");
+
+                    b.HasIndex(new[] { "SID" }, "IX_Member_SID")
+                        .IsUnique();
+
+                    b.ToTable("Member", t =>
+                        {
+                            t.HasComment("회원 정보");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberApprove", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("회원 ID");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<bool>("IsDisclosureInvest")
+                        .HasColumnType("bit")
+                        .HasComment("투자 현황 공개 여부");
+
+                    b.Property<bool>("IsReceiveEmail")
+                        .HasColumnType("bit")
+                        .HasComment("E-MAIL 수신 여부");
+
+                    b.Property<bool>("IsReceiveNote")
+                        .HasColumnType("bit")
+                        .HasComment("쪽지 수신 여부");
+
+                    b.Property<bool>("IsReceiveSMS")
+                        .HasColumnType("bit")
+                        .HasComment("SMS 수신 여부");
+
+                    b.HasKey("ID");
+
+                    b.ToTable("MemberApprove", t =>
+                        {
+                            t.HasComment("회원 동의 및 수신 여부");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberGrade", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("PK");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("등록 일시");
+
+                    b.Property<string>("Description")
+                        .HasMaxLength(1000)
+                        .HasColumnType("nvarchar(1000)")
+                        .HasComment("설명");
+
+                    b.Property<string>("EngName")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)")
+                        .HasComment("영문 명");
+
+                    b.Property<string>("Image")
+                        .HasColumnType("nvarchar(max)")
+                        .HasComment("이미지");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit")
+                        .HasComment("사용 여부");
+
+                    b.Property<string>("KorName")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)")
+                        .HasComment("한글 명");
+
+                    b.Property<short>("Order")
+                        .HasColumnType("smallint")
+                        .HasComment("순서");
+
+                    b.Property<int>("RequiredCoin")
+                        .HasColumnType("int")
+                        .HasComment("최소 코인(Coin)");
+
+                    b.Property<int>("RequiredExp")
+                        .HasColumnType("int")
+                        .HasComment("최소 경험치(Exp)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("수정 일시");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "EngName" }, "IX_MemberGrade_EngName")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "KorName" }, "IX_MemberGrade_KorName")
+                        .IsUnique();
+
+                    b.ToTable("MemberGrade", t =>
+                        {
+                            t.HasComment("회원 등급");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerItem", b =>
+                {
+                    b.HasOne("bitforum.Models.Page.Banner.BannerPosition", "BannerPosition")
+                        .WithMany("BannerItem")
+                        .HasForeignKey("PositionID")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("BannerPosition");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqItem", b =>
+                {
+                    b.HasOne("bitforum.Models.Page.Faq.FaqCategory", "FaqCategory")
+                        .WithMany("FaqItem")
+                        .HasForeignKey("CategoryID")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("FaqCategory");
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.Member", b =>
+                {
+                    b.HasOne("bitforum.Models.User.MemberGrade", "MemberGrade")
+                        .WithMany()
+                        .HasForeignKey("GradeID");
+
+                    b.HasOne("bitforum.Models.User.MemberApprove", "MemberApproves")
+                        .WithOne("Member")
+                        .HasForeignKey("bitforum.Models.User.Member", "ID")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("MemberApproves");
+
+                    b.Navigation("MemberGrade");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerPosition", b =>
+                {
+                    b.Navigation("BannerItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqCategory", b =>
+                {
+                    b.Navigation("FaqItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberApprove", b =>
+                {
+                    b.Navigation("Member")
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 191 - 0
backend/Migrations/DefaultDb/20250124015524_AddMember.cs

@@ -0,0 +1,191 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace bitforum.Migrations.DefaultDb
+{
+    /// <inheritdoc />
+    public partial class AddMember : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AlterColumn<string>(
+                name: "Image",
+                table: "BannerItem",
+                type: "nvarchar(1024)",
+                maxLength: 1024,
+                nullable: true,
+                oldClrType: typeof(string),
+                oldType: "nvarchar(1024)",
+                oldMaxLength: 1024);
+
+            migrationBuilder.CreateTable(
+                name: "MemberApprove",
+                columns: table => new
+                {
+                    ID = table.Column<int>(type: "int", nullable: false, comment: "회원 ID")
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    IsReceiveSMS = table.Column<bool>(type: "bit", nullable: false, comment: "SMS 수신 여부"),
+                    IsReceiveEmail = table.Column<bool>(type: "bit", nullable: false, comment: "E-MAIL 수신 여부"),
+                    IsReceiveNote = table.Column<bool>(type: "bit", nullable: false, comment: "쪽지 수신 여부"),
+                    IsDisclosureInvest = table.Column<bool>(type: "bit", nullable: false, comment: "투자 현황 공개 여부")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_MemberApprove", x => x.ID);
+                },
+                comment: "회원 동의 및 수신 여부");
+
+            migrationBuilder.CreateTable(
+                name: "MemberGrade",
+                columns: table => new
+                {
+                    ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    KorName = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false, comment: "한글 명"),
+                    EngName = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false, comment: "영문 명"),
+                    Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true, comment: "설명"),
+                    Order = table.Column<short>(type: "smallint", nullable: false, comment: "순서"),
+                    Image = table.Column<string>(type: "nvarchar(max)", nullable: true, comment: "이미지"),
+                    RequiredExp = table.Column<int>(type: "int", nullable: false, comment: "최소 경험치(Exp)"),
+                    RequiredCoin = table.Column<int>(type: "int", nullable: false, comment: "최소 코인(Coin)"),
+                    IsActive = table.Column<bool>(type: "bit", nullable: false, comment: "사용 여부"),
+                    UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "수정 일시"),
+                    CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "등록 일시")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_MemberGrade", x => x.ID);
+                },
+                comment: "회원 등급");
+
+            migrationBuilder.CreateTable(
+                name: "Member",
+                columns: table => new
+                {
+                    ID = table.Column<int>(type: "int", nullable: false, comment: "PK"),
+                    GradeID = table.Column<int>(type: "int", nullable: true, comment: "회원등급 ID"),
+                    SID = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false, comment: "SID"),
+                    Email = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false, comment: "이메일"),
+                    Name = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true, comment: "별명"),
+                    FullName = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true, comment: "본명"),
+                    FirstName = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true, comment: "본명(성)"),
+                    LastName = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true, comment: "본명(이름)"),
+                    Password = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false, comment: "비밀번호"),
+                    Intro = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true, comment: "자기소개"),
+                    Summary = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true, comment: "한마디"),
+                    Coin = table.Column<long>(type: "bigint", nullable: false, comment: "코인"),
+                    Exp = table.Column<int>(type: "int", nullable: false, comment: "경험치"),
+                    Phone = table.Column<string>(type: "nvarchar(15)", maxLength: 15, nullable: true, comment: "연락처"),
+                    Birthday = table.Column<DateOnly>(type: "date", maxLength: 10, nullable: true, comment: "생년월일"),
+                    Gender = table.Column<int>(type: "int", maxLength: 6, nullable: true, comment: "성별"),
+                    Photo = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: true, comment: "사진"),
+                    IsEmailVerified = table.Column<bool>(type: "bit", nullable: false, comment: "이메일 인증 여부"),
+                    IsAuthCertified = table.Column<bool>(type: "bit", nullable: false, comment: "본인 인증 여부"),
+                    IsDenied = table.Column<bool>(type: "bit", nullable: false, comment: "차단 여부"),
+                    IsAdmin = table.Column<bool>(type: "bit", nullable: false, comment: "운영진 여부"),
+                    IsWithdraw = table.Column<bool>(type: "bit", nullable: false, comment: "탈퇴 여부"),
+                    Following = table.Column<int>(type: "int", nullable: false, comment: "구독 중"),
+                    Followed = table.Column<int>(type: "int", nullable: false, comment: "구독자"),
+                    DeviceInfo = table.Column<string>(type: "nvarchar(400)", maxLength: 400, nullable: true, comment: "로그인 단말기 정보"),
+                    SignupIP = table.Column<string>(type: "nvarchar(15)", maxLength: 15, nullable: false, comment: "회원가입 시 IP"),
+                    LastLoginIp = table.Column<string>(type: "nvarchar(15)", maxLength: 15, nullable: true, comment: "마지막 로그인 IP"),
+                    LastLoginAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "마지막 로그인 일시"),
+                    EmailVerifiedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "이메일 인증 일시"),
+                    AuthCertifiedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "본인인증 일시"),
+                    PasswordUpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "비밀번호 변경 일시"),
+                    CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "가입 일시"),
+                    UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "수정 일시"),
+                    DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "탈퇴 일시")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Member", x => x.ID);
+                    table.ForeignKey(
+                        name: "FK_Member_MemberApprove_ID",
+                        column: x => x.ID,
+                        principalTable: "MemberApprove",
+                        principalColumn: "ID",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_Member_MemberGrade_GradeID",
+                        column: x => x.GradeID,
+                        principalTable: "MemberGrade",
+                        principalColumn: "ID");
+                },
+                comment: "회원 정보");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_BannerPosition_IsActive",
+                table: "BannerPosition",
+                column: "IsActive");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Member_Email",
+                table: "Member",
+                column: "Email",
+                unique: true);
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Member_GradeID",
+                table: "Member",
+                column: "GradeID");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Member_Name",
+                table: "Member",
+                column: "Name",
+                unique: true,
+                filter: "[Name] IS NOT NULL");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Member_SID",
+                table: "Member",
+                column: "SID",
+                unique: true);
+
+            migrationBuilder.CreateIndex(
+                name: "IX_MemberGrade_EngName",
+                table: "MemberGrade",
+                column: "EngName",
+                unique: true);
+
+            migrationBuilder.CreateIndex(
+                name: "IX_MemberGrade_KorName",
+                table: "MemberGrade",
+                column: "KorName",
+                unique: true);
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "Member");
+
+            migrationBuilder.DropTable(
+                name: "MemberApprove");
+
+            migrationBuilder.DropTable(
+                name: "MemberGrade");
+
+            migrationBuilder.DropIndex(
+                name: "IX_BannerPosition_IsActive",
+                table: "BannerPosition");
+
+            migrationBuilder.AlterColumn<string>(
+                name: "Image",
+                table: "BannerItem",
+                type: "nvarchar(1024)",
+                maxLength: 1024,
+                nullable: false,
+                defaultValue: "",
+                oldClrType: typeof(string),
+                oldType: "nvarchar(1024)",
+                oldMaxLength: 1024,
+                oldNullable: true);
+        }
+    }
+}

+ 668 - 0
backend/Migrations/DefaultDb/20250124020320_UpdateMember.Designer.cs

@@ -0,0 +1,668 @@
+// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace bitforum.Migrations.DefaultDb
+{
+    [DbContext(typeof(DefaultDbContext))]
+    [Migration("20250124020320_UpdateMember")]
+    partial class UpdateMember
+    {
+        /// <inheritdoc />
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "8.0.0")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+            SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+            modelBuilder.Entity("bitforum.Models.Config", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Key")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(450)");
+
+                    b.Property<string>("Value")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("Key")
+                        .IsUnique();
+
+                    b.ToTable("Config");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerItem", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("EndAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Height")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Image")
+                        .HasMaxLength(1024)
+                        .HasColumnType("nvarchar(1024)");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Link")
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<int>("PositionID")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("StartAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.Property<int>("Width")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("PositionID");
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_BannerItem_IsActive");
+
+                    b.HasIndex(new[] { "Order" }, "IX_BannerItem_Order");
+
+                    b.ToTable("BannerItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerPosition", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("nvarchar(30)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "Code" }, "IX_BannerPosition_Code")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_BannerPosition_IsActive");
+
+                    b.ToTable("BannerPosition");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Document", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("nvarchar(30)");
+
+                    b.Property<string>("Content")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "Code" }, "IX_Document_Code")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_Document_IsActive");
+
+                    b.ToTable("Document");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqCategory", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("nvarchar(30)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "Code" }, "IX_FaqCategory_Code")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "Order" }, "IX_FaqCategory_Order");
+
+                    b.ToTable("FaqCategory");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqItem", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Answer")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<int>("CategoryID")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Question")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("CategoryID");
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_FaqItem_IsActive");
+
+                    b.HasIndex(new[] { "Order" }, "IX_FaqItem_Order");
+
+                    b.ToTable("FaqItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Popup", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<string>("Content")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime?>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("EndAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("Link")
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("StartAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Subject")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<int>("Views")
+                        .HasColumnType("int");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "IsActive" }, "IX_Popup_IsActive");
+
+                    b.ToTable("Popup");
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.Member", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("PK");
+
+                    b.Property<DateTime?>("AuthCertifiedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("본인인증 일시");
+
+                    b.Property<DateOnly?>("Birthday")
+                        .HasMaxLength(10)
+                        .HasColumnType("date")
+                        .HasComment("생년월일");
+
+                    b.Property<long>("Coin")
+                        .HasColumnType("bigint")
+                        .HasComment("코인");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("가입 일시");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("탈퇴 일시");
+
+                    b.Property<string>("DeviceInfo")
+                        .HasMaxLength(400)
+                        .HasColumnType("nvarchar(400)")
+                        .HasComment("로그인 단말기 정보");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("이메일");
+
+                    b.Property<DateTime?>("EmailVerifiedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("이메일 인증 일시");
+
+                    b.Property<int>("Exp")
+                        .HasColumnType("int")
+                        .HasComment("경험치");
+
+                    b.Property<string>("FirstName")
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("본명(성)");
+
+                    b.Property<int>("Followed")
+                        .HasColumnType("int")
+                        .HasComment("구독자");
+
+                    b.Property<int>("Following")
+                        .HasColumnType("int")
+                        .HasComment("구독 중");
+
+                    b.Property<string>("FullName")
+                        .HasMaxLength(40)
+                        .HasColumnType("nvarchar(40)")
+                        .HasComment("본명");
+
+                    b.Property<int?>("Gender")
+                        .HasMaxLength(6)
+                        .HasColumnType("int")
+                        .HasComment("성별");
+
+                    b.Property<int?>("GradeID")
+                        .HasColumnType("int")
+                        .HasComment("회원등급 ID");
+
+                    b.Property<string>("Intro")
+                        .HasMaxLength(1000)
+                        .HasColumnType("nvarchar(1000)")
+                        .HasComment("자기소개");
+
+                    b.Property<bool>("IsAdmin")
+                        .HasColumnType("bit")
+                        .HasComment("운영진 여부");
+
+                    b.Property<bool>("IsAuthCertified")
+                        .HasColumnType("bit")
+                        .HasComment("본인 인증 여부");
+
+                    b.Property<bool>("IsDenied")
+                        .HasColumnType("bit")
+                        .HasComment("차단 여부");
+
+                    b.Property<bool>("IsEmailVerified")
+                        .HasColumnType("bit")
+                        .HasComment("이메일 인증 여부");
+
+                    b.Property<bool>("IsWithdraw")
+                        .HasColumnType("bit")
+                        .HasComment("탈퇴 여부");
+
+                    b.Property<DateTime?>("LastLoginAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("마지막 로그인 일시");
+
+                    b.Property<string>("LastLoginIp")
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("마지막 로그인 IP");
+
+                    b.Property<string>("LastName")
+                        .HasMaxLength(40)
+                        .HasColumnType("nvarchar(40)")
+                        .HasComment("본명(이름)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("별명");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("비밀번호");
+
+                    b.Property<DateTime>("PasswordUpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("비밀번호 변경 일시");
+
+                    b.Property<string>("Phone")
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("연락처");
+
+                    b.Property<string>("Photo")
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("사진");
+
+                    b.Property<string>("SID")
+                        .IsRequired()
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("SID");
+
+                    b.Property<string>("SignupIP")
+                        .IsRequired()
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("회원가입 시 IP");
+
+                    b.Property<string>("Summary")
+                        .HasMaxLength(50)
+                        .HasColumnType("nvarchar(50)")
+                        .HasComment("한마디");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("수정 일시");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("GradeID");
+
+                    b.HasIndex(new[] { "Email" }, "IX_Member_Email")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "Name" }, "IX_Member_Name")
+                        .IsUnique()
+                        .HasFilter("[Name] IS NOT NULL");
+
+                    b.HasIndex(new[] { "SID" }, "IX_Member_SID")
+                        .IsUnique();
+
+                    b.ToTable("Member", t =>
+                        {
+                            t.HasComment("회원 정보");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberApprove", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("회원 ID");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<bool>("IsDisclosureInvest")
+                        .HasColumnType("bit")
+                        .HasComment("투자 현황 공개 여부");
+
+                    b.Property<bool>("IsReceiveEmail")
+                        .HasColumnType("bit")
+                        .HasComment("E-MAIL 수신 여부");
+
+                    b.Property<bool>("IsReceiveNote")
+                        .HasColumnType("bit")
+                        .HasComment("쪽지 수신 여부");
+
+                    b.Property<bool>("IsReceiveSMS")
+                        .HasColumnType("bit")
+                        .HasComment("SMS 수신 여부");
+
+                    b.HasKey("ID");
+
+                    b.ToTable("MemberApprove", t =>
+                        {
+                            t.HasComment("회원 동의 및 수신 여부");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberGrade", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("PK");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("등록 일시");
+
+                    b.Property<string>("Description")
+                        .HasMaxLength(1000)
+                        .HasColumnType("nvarchar(1000)")
+                        .HasComment("설명");
+
+                    b.Property<string>("EngName")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)")
+                        .HasComment("영문 명");
+
+                    b.Property<string>("Image")
+                        .HasColumnType("nvarchar(max)")
+                        .HasComment("이미지");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit")
+                        .HasComment("사용 여부");
+
+                    b.Property<string>("KorName")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)")
+                        .HasComment("한글 명");
+
+                    b.Property<short>("Order")
+                        .HasColumnType("smallint")
+                        .HasComment("순서");
+
+                    b.Property<int>("RequiredCoin")
+                        .HasColumnType("int")
+                        .HasComment("최소 코인(Coin)");
+
+                    b.Property<int>("RequiredExp")
+                        .HasColumnType("int")
+                        .HasComment("최소 경험치(Exp)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("수정 일시");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "EngName" }, "IX_MemberGrade_EngName")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "KorName" }, "IX_MemberGrade_KorName")
+                        .IsUnique();
+
+                    b.ToTable("MemberGrade", t =>
+                        {
+                            t.HasComment("회원 등급");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerItem", b =>
+                {
+                    b.HasOne("bitforum.Models.Page.Banner.BannerPosition", "BannerPosition")
+                        .WithMany("BannerItem")
+                        .HasForeignKey("PositionID")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("BannerPosition");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqItem", b =>
+                {
+                    b.HasOne("bitforum.Models.Page.Faq.FaqCategory", "FaqCategory")
+                        .WithMany("FaqItem")
+                        .HasForeignKey("CategoryID")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("FaqCategory");
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.Member", b =>
+                {
+                    b.HasOne("bitforum.Models.User.MemberGrade", "MemberGrade")
+                        .WithMany()
+                        .HasForeignKey("GradeID");
+
+                    b.HasOne("bitforum.Models.User.MemberApprove", "MemberApproves")
+                        .WithOne("Member")
+                        .HasForeignKey("bitforum.Models.User.Member", "ID")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("MemberApproves");
+
+                    b.Navigation("MemberGrade");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Banner.BannerPosition", b =>
+                {
+                    b.Navigation("BannerItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.Page.Faq.FaqCategory", b =>
+                {
+                    b.Navigation("FaqItem");
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberApprove", b =>
+                {
+                    b.Navigation("Member")
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 22 - 0
backend/Migrations/DefaultDb/20250124020320_UpdateMember.cs

@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace bitforum.Migrations.DefaultDb
+{
+    /// <inheritdoc />
+    public partial class UpdateMember : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+
+        }
+    }
+}

+ 305 - 1
backend/Migrations/DefaultDb/DefaultDbContextModelSnapshot.cs

@@ -68,7 +68,6 @@ namespace bitforum.Migrations.DefaultDb
                         .HasColumnType("int");
 
                     b.Property<string>("Image")
-                        .IsRequired()
                         .HasMaxLength(1024)
                         .HasColumnType("nvarchar(1024)");
 
@@ -145,6 +144,8 @@ namespace bitforum.Migrations.DefaultDb
                     b.HasIndex(new[] { "Code" }, "IX_BannerPosition_Code")
                         .IsUnique();
 
+                    b.HasIndex(new[] { "IsActive" }, "IX_BannerPosition_IsActive");
+
                     b.ToTable("BannerPosition");
                 });
 
@@ -324,6 +325,286 @@ namespace bitforum.Migrations.DefaultDb
                     b.ToTable("Popup");
                 });
 
+            modelBuilder.Entity("bitforum.Models.User.Member", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("PK");
+
+                    b.Property<DateTime?>("AuthCertifiedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("본인인증 일시");
+
+                    b.Property<DateOnly?>("Birthday")
+                        .HasMaxLength(10)
+                        .HasColumnType("date")
+                        .HasComment("생년월일");
+
+                    b.Property<long>("Coin")
+                        .HasColumnType("bigint")
+                        .HasComment("코인");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("가입 일시");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("탈퇴 일시");
+
+                    b.Property<string>("DeviceInfo")
+                        .HasMaxLength(400)
+                        .HasColumnType("nvarchar(400)")
+                        .HasComment("로그인 단말기 정보");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("이메일");
+
+                    b.Property<DateTime?>("EmailVerifiedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("이메일 인증 일시");
+
+                    b.Property<int>("Exp")
+                        .HasColumnType("int")
+                        .HasComment("경험치");
+
+                    b.Property<string>("FirstName")
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("본명(성)");
+
+                    b.Property<int>("Followed")
+                        .HasColumnType("int")
+                        .HasComment("구독자");
+
+                    b.Property<int>("Following")
+                        .HasColumnType("int")
+                        .HasComment("구독 중");
+
+                    b.Property<string>("FullName")
+                        .HasMaxLength(40)
+                        .HasColumnType("nvarchar(40)")
+                        .HasComment("본명");
+
+                    b.Property<int?>("Gender")
+                        .HasMaxLength(6)
+                        .HasColumnType("int")
+                        .HasComment("성별");
+
+                    b.Property<int?>("GradeID")
+                        .HasColumnType("int")
+                        .HasComment("회원등급 ID");
+
+                    b.Property<string>("Intro")
+                        .HasMaxLength(1000)
+                        .HasColumnType("nvarchar(1000)")
+                        .HasComment("자기소개");
+
+                    b.Property<bool>("IsAdmin")
+                        .HasColumnType("bit")
+                        .HasComment("운영진 여부");
+
+                    b.Property<bool>("IsAuthCertified")
+                        .HasColumnType("bit")
+                        .HasComment("본인 인증 여부");
+
+                    b.Property<bool>("IsDenied")
+                        .HasColumnType("bit")
+                        .HasComment("차단 여부");
+
+                    b.Property<bool>("IsEmailVerified")
+                        .HasColumnType("bit")
+                        .HasComment("이메일 인증 여부");
+
+                    b.Property<bool>("IsWithdraw")
+                        .HasColumnType("bit")
+                        .HasComment("탈퇴 여부");
+
+                    b.Property<DateTime?>("LastLoginAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("마지막 로그인 일시");
+
+                    b.Property<string>("LastLoginIp")
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("마지막 로그인 IP");
+
+                    b.Property<string>("LastName")
+                        .HasMaxLength(40)
+                        .HasColumnType("nvarchar(40)")
+                        .HasComment("본명(이름)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("별명");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("비밀번호");
+
+                    b.Property<DateTime>("PasswordUpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("비밀번호 변경 일시");
+
+                    b.Property<string>("Phone")
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("연락처");
+
+                    b.Property<string>("Photo")
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)")
+                        .HasComment("사진");
+
+                    b.Property<string>("SID")
+                        .IsRequired()
+                        .HasMaxLength(20)
+                        .HasColumnType("nvarchar(20)")
+                        .HasComment("SID");
+
+                    b.Property<string>("SignupIP")
+                        .IsRequired()
+                        .HasMaxLength(15)
+                        .HasColumnType("nvarchar(15)")
+                        .HasComment("회원가입 시 IP");
+
+                    b.Property<string>("Summary")
+                        .HasMaxLength(50)
+                        .HasColumnType("nvarchar(50)")
+                        .HasComment("한마디");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("수정 일시");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex("GradeID");
+
+                    b.HasIndex(new[] { "Email" }, "IX_Member_Email")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "Name" }, "IX_Member_Name")
+                        .IsUnique()
+                        .HasFilter("[Name] IS NOT NULL");
+
+                    b.HasIndex(new[] { "SID" }, "IX_Member_SID")
+                        .IsUnique();
+
+                    b.ToTable("Member", t =>
+                        {
+                            t.HasComment("회원 정보");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberApprove", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("회원 ID");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<bool>("IsDisclosureInvest")
+                        .HasColumnType("bit")
+                        .HasComment("투자 현황 공개 여부");
+
+                    b.Property<bool>("IsReceiveEmail")
+                        .HasColumnType("bit")
+                        .HasComment("E-MAIL 수신 여부");
+
+                    b.Property<bool>("IsReceiveNote")
+                        .HasColumnType("bit")
+                        .HasComment("쪽지 수신 여부");
+
+                    b.Property<bool>("IsReceiveSMS")
+                        .HasColumnType("bit")
+                        .HasComment("SMS 수신 여부");
+
+                    b.HasKey("ID");
+
+                    b.ToTable("MemberApprove", t =>
+                        {
+                            t.HasComment("회원 동의 및 수신 여부");
+                        });
+                });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberGrade", b =>
+                {
+                    b.Property<int>("ID")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasComment("PK");
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"));
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("등록 일시");
+
+                    b.Property<string>("Description")
+                        .HasMaxLength(1000)
+                        .HasColumnType("nvarchar(1000)")
+                        .HasComment("설명");
+
+                    b.Property<string>("EngName")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)")
+                        .HasComment("영문 명");
+
+                    b.Property<string>("Image")
+                        .HasColumnType("nvarchar(max)")
+                        .HasComment("이미지");
+
+                    b.Property<bool>("IsActive")
+                        .HasColumnType("bit")
+                        .HasComment("사용 여부");
+
+                    b.Property<string>("KorName")
+                        .IsRequired()
+                        .HasMaxLength(120)
+                        .HasColumnType("nvarchar(120)")
+                        .HasComment("한글 명");
+
+                    b.Property<short>("Order")
+                        .HasColumnType("smallint")
+                        .HasComment("순서");
+
+                    b.Property<int>("RequiredCoin")
+                        .HasColumnType("int")
+                        .HasComment("최소 코인(Coin)");
+
+                    b.Property<int>("RequiredExp")
+                        .HasColumnType("int")
+                        .HasComment("최소 경험치(Exp)");
+
+                    b.Property<DateTime?>("UpdatedAt")
+                        .HasColumnType("datetime2")
+                        .HasComment("수정 일시");
+
+                    b.HasKey("ID");
+
+                    b.HasIndex(new[] { "EngName" }, "IX_MemberGrade_EngName")
+                        .IsUnique();
+
+                    b.HasIndex(new[] { "KorName" }, "IX_MemberGrade_KorName")
+                        .IsUnique();
+
+                    b.ToTable("MemberGrade", t =>
+                        {
+                            t.HasComment("회원 등급");
+                        });
+                });
+
             modelBuilder.Entity("bitforum.Models.Page.Banner.BannerItem", b =>
                 {
                     b.HasOne("bitforum.Models.Page.Banner.BannerPosition", "BannerPosition")
@@ -346,6 +627,23 @@ namespace bitforum.Migrations.DefaultDb
                     b.Navigation("FaqCategory");
                 });
 
+            modelBuilder.Entity("bitforum.Models.User.Member", b =>
+                {
+                    b.HasOne("bitforum.Models.User.MemberGrade", "MemberGrade")
+                        .WithMany()
+                        .HasForeignKey("GradeID");
+
+                    b.HasOne("bitforum.Models.User.MemberApprove", "MemberApproves")
+                        .WithOne("Member")
+                        .HasForeignKey("bitforum.Models.User.Member", "ID")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("MemberApproves");
+
+                    b.Navigation("MemberGrade");
+                });
+
             modelBuilder.Entity("bitforum.Models.Page.Banner.BannerPosition", b =>
                 {
                     b.Navigation("BannerItem");
@@ -355,6 +653,12 @@ namespace bitforum.Migrations.DefaultDb
                 {
                     b.Navigation("FaqItem");
                 });
+
+            modelBuilder.Entity("bitforum.Models.User.MemberApprove", b =>
+                {
+                    b.Navigation("Member")
+                        .IsRequired();
+                });
 #pragma warning restore 612, 618
         }
     }

+ 4 - 3
backend/Models/Page/Banner/Item.cs

@@ -6,10 +6,14 @@ using System.ComponentModel.DataAnnotations.Schema;
 
 namespace bitforum.Models.Page.Banner
 {
+    [Table("BannerItem")]
     [Index(nameof(Order), Name = "IX_BannerItem_Order")]
     [Index(nameof(IsActive), Name = "IX_BannerItem_IsActive")]
     public class BannerItem
     {
+        [ValidateNever]
+        public virtual BannerPosition? BannerPosition { get; set; } = null;
+
         [Key]
         public int ID { get; set; }
 
@@ -68,8 +72,5 @@ namespace bitforum.Models.Page.Banner
         [DisplayName("등록일시")]
         [DataType(DataType.DateTime)]
         public DateTime? CreatedAt { get; set; } = null;
-
-        [ValidateNever]
-        public virtual BannerPosition? BannerPosition { get; set; } = null;
     }
 }

+ 4 - 2
backend/Models/Page/Banner/Position.cs

@@ -1,13 +1,17 @@
 using Microsoft.EntityFrameworkCore;
 using System.ComponentModel;
 using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
 
 namespace bitforum.Models.Page.Banner
 {
+    [Table("BannerPosition")]
     [Index(nameof(Code), Name = "IX_BannerPosition_Code", IsUnique = true)]
     [Index(nameof(IsActive), Name = "IX_BannerPosition_IsActive")]
     public class BannerPosition
     {
+        public virtual ICollection<BannerItem> BannerItem { get; set; } = new List<BannerItem>();
+
         [Key]
         public int ID { get; set; }
 
@@ -35,7 +39,5 @@ namespace bitforum.Models.Page.Banner
         [DisplayName("등록일시")]
         [DataType(DataType.DateTime)]
         public DateTime? CreatedAt { get; set; } = null;
-
-        public virtual ICollection<BannerItem> BannerItem { get; set; } = new List<BannerItem>();
     }
 }

+ 2 - 0
backend/Models/Page/Document.cs

@@ -1,9 +1,11 @@
 using Microsoft.EntityFrameworkCore;
 using System.ComponentModel;
 using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
 
 namespace bitforum.Models.Page
 {
+    [Table("Document")]
     [Index(nameof(Code), Name = "IX_Document_Code", IsUnique = true)]
     [Index(nameof(IsActive), Name = "IX_Document_IsActive")]
     public class Document

+ 4 - 2
backend/Models/Page/Faq/Category.cs

@@ -1,13 +1,17 @@
 using Microsoft.EntityFrameworkCore;
 using System.ComponentModel;
 using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
 
 namespace bitforum.Models.Page.Faq
 {
+    [Table("FaqCategory")]
     [Index(nameof(Code), Name = "IX_FaqCategory_Code", IsUnique = true)]
     [Index(nameof(Order), Name = "IX_FaqCategory_Order")]
     public class FaqCategory
     {
+        public virtual List<FaqItem> FaqItem { get; set; } = new List<FaqItem>();
+
         [Key]
         public int ID { get; set; }
 
@@ -39,7 +43,5 @@ namespace bitforum.Models.Page.Faq
         [Display(Name = "등록일시")]
         [DataType(DataType.DateTime)]
         public DateTime? CreatedAt { get; set; } = null;
-
-        public virtual List<FaqItem> FaqItem { get; set; } = new List<FaqItem>();
     }
 }

+ 4 - 3
backend/Models/Page/Faq/Item.cs

@@ -6,10 +6,14 @@ using System.ComponentModel.DataAnnotations.Schema;
 
 namespace bitforum.Models.Page.Faq
 {
+    [Table("FaqItem")]
     [Index(nameof(Order), Name = "IX_FaqItem_Order")]
     [Index(nameof(IsActive), Name = "IX_FaqItem_IsActive")]
     public class FaqItem
     {
+        [ValidateNever]
+        public virtual FaqCategory FaqCategory { get; set; } = null;
+
         [Key]
         public int ID { get; set; }
 
@@ -46,8 +50,5 @@ namespace bitforum.Models.Page.Faq
         [DisplayName("등록일시")]
         [DataType(DataType.DateTime)]
         public DateTime? CreatedAt { get; set; } = null;
-
-        [ValidateNever]
-        public virtual FaqCategory FaqCategory { get; set; } = null;
     }
 }

+ 2 - 0
backend/Models/Page/Popup.cs

@@ -1,9 +1,11 @@
 using Microsoft.EntityFrameworkCore;
 using System.ComponentModel;
 using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
 
 namespace bitforum.Models.Page
 {
+    [Table("Popup")]
     [Index(nameof(IsActive), Name = "IX_Popup_IsActive")]
     public class Popup
     {

+ 152 - 0
backend/Models/User/Member.cs

@@ -0,0 +1,152 @@
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.EntityFrameworkCore;
+using bitforum.Constants;
+
+/// <summary>
+/// 사용자단 일반 회원 정보
+/// </summary>
+namespace bitforum.Models.User
+{
+    [Table("Member")]
+    [Comment("회원 정보")]
+    [Index(nameof(SID), Name = "IX_Member_SID", IsUnique = true)]
+    [Index(nameof(Email), Name = "IX_Member_Email", IsUnique = true)]
+    [Index(nameof(Name), Name = "IX_Member_Name", IsUnique = true)]
+    public class Member
+    {
+        [ForeignKey("ID")]
+        public virtual MemberApprove MemberApproves { get; set; }
+
+        [ForeignKey("GradeID")]
+        public virtual MemberGrade MemberGrade { get; set; }
+
+        [Key]
+        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+        [Comment("PK")]
+        public int ID { get; set; }
+
+        [Comment("회원등급 ID")]
+        public int? GradeID { get; set; } = null;
+
+        [Required]
+        [MaxLength(20)]
+        [Comment("SID")]
+        public string SID { get; set; } // 무작위 문자열
+
+        [Required]
+        [MaxLength(255)]
+        [Comment("이메일")]
+        [DataType(DataType.EmailAddress)]
+        public string Email { get; set; }
+
+        [MaxLength(20)]
+        [Comment("별명")]
+        public string? Name { get; set; } = null;
+
+        [MaxLength(40)]
+        [Comment("본명")]
+        public string? FullName { get; set; } = null;
+
+        [MaxLength(20)]
+        [Comment("본명(성)")]
+        public string? FirstName { get; set; } = null;
+
+        [MaxLength(40)]
+        [Comment("본명(이름)")]
+        public string? LastName { get; set; } = null;
+
+        [Required]
+        [MaxLength(255)]
+        [Comment("비밀번호")]
+        [DataType(DataType.Password)]
+        public string Password { get; set; }
+
+        [MaxLength(1000)]
+        [Comment("자기소개")]
+        public string? Intro { get; set; } = null;
+
+        [MaxLength(50)]
+        [Comment("한마디")]
+        public string? Summary { get; set; } = null;
+
+        [Comment("코인")]
+        public long Coin { get; set; } = 0;
+
+        [Comment("경험치")]
+        public int Exp { get; set; } = 0;
+
+        [MaxLength(15)]
+        [Comment("연락처")]
+        public string? Phone { get; set; } = null;
+
+        [MaxLength(10)]
+        [Comment("생년월일")]
+        public DateOnly? Birthday { get; set; } = null;
+
+        [MaxLength(6)]
+        [Comment("성별")]
+        public Gender? Gender { get; set; } = null;
+
+        [MaxLength(255)]
+        [Comment("사진")]
+        public string? Photo { get; set; } = null;
+   
+        [Comment("이메일 인증 여부")]
+        public bool IsEmailVerified { get; set; } = false;
+
+        [Comment("본인 인증 여부")]
+        public bool IsAuthCertified { get; set; } = false;
+
+        [Comment("차단 여부")]
+        public bool IsDenied { get; set; } = false;
+
+        [Comment("운영진 여부")]
+        public bool IsAdmin { get; set; } = false;
+
+        [Comment("탈퇴 여부")]
+        public bool IsWithdraw { get; set; } = false;
+
+        [Comment("구독 중")]
+        public int Following { get; set; } = 0;
+
+        [Comment("구독자")]
+        public int Followed { get; set; } = 0;
+
+        [MaxLength(400)]
+        [Comment("로그인 단말기 정보")]
+        public string? DeviceInfo { get; set; } = null;
+
+        [Required]
+        [MaxLength(15)]
+        [Comment("회원가입 시 IP")]
+        public string SignupIP { get; set; }
+
+        [MaxLength(15)]
+        [Comment("마지막 로그인 IP")]
+        public string? LastLoginIp { get; set; } = null;
+
+        [Comment("마지막 로그인 일시")]
+        public DateTime? LastLoginAt { get; set; } = null;
+
+        [Comment("이메일 인증 일시")]
+        public DateTime? EmailVerifiedAt { get; set; } = null;
+
+        [Comment("본인인증 일시")]
+        public DateTime? AuthCertifiedAt { get; set; } = null;
+
+        [Required]
+        [Comment("비밀번호 변경 일시")]
+        public DateTime PasswordUpdatedAt { get; set; }
+
+        [Required]
+        [Comment("가입 일시")]
+        public DateTime CreatedAt { get; set; }
+
+        [Comment("수정 일시")]
+        public DateTime? UpdatedAt { get; set; } = null;
+
+        [Comment("탈퇴 일시")]
+        public DateTime? DeletedAt { get; set; } = null;
+    }
+}

+ 37 - 0
backend/Models/User/MemberApprove.cs

@@ -0,0 +1,37 @@
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.EntityFrameworkCore;
+
+/// <summary>
+/// 사용자단 회원 수신, 알림 각종 동의 여부 모음
+/// </summary>
+namespace bitforum.Models.User
+{
+    [Table("MemberApprove")]
+    [Comment("회원 동의 및 수신 여부")]
+    public class MemberApprove
+    {
+        [Key]
+        [ForeignKey("Member")]
+        [Comment("회원 ID")]
+        public int ID { get; set; }
+
+        [Required]
+        [Comment("SMS 수신 여부")]
+        public bool IsReceiveSMS { get; set; } = false;
+
+        [Required]
+        [Comment("E-MAIL 수신 여부")]
+        public bool IsReceiveEmail { get; set; } = false;
+
+        [Required]
+        [Comment("쪽지 수신 여부")]
+        public bool IsReceiveNote { get; set; } = false;
+
+        [Required]
+        [Comment("투자 현황 공개 여부")]
+        public bool IsDisclosureInvest { get; set; } = false;
+
+        public Member Member { get; set; }
+    }
+}

+ 61 - 0
backend/Models/User/MemberGrade.cs

@@ -0,0 +1,61 @@
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.EntityFrameworkCore;
+
+/// <summary>
+/// 사용자단 회원 등급 조건 세부 정보
+/// </summary>
+namespace bitforum.Models.User
+{
+    [Table("MemberGrade")]
+    [Comment("회원 등급")]
+    [Index(nameof(KorName), Name = "IX_MemberGrade_KorName", IsUnique = true)]
+    [Index(nameof(EngName), Name = "IX_MemberGrade_EngName", IsUnique = true)]
+    public class MemberGrade
+    {
+        [Key]
+        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+        [Comment("PK")]
+        public int ID { get; set; }
+
+        [Required]
+        [MaxLength(120)]
+        [Comment("한글 명")]
+        public string KorName { get; set; }
+
+        [Required]
+        [MaxLength(120)]
+        [Comment("영문 명")]
+        public string EngName { get; set; }
+
+        [MaxLength(1000)]
+        [Comment("설명")]
+        public string? Description { get; set; } = null;
+
+        [Required]
+        [Comment("순서")]
+        public short Order { get; set; } = 0;
+
+        [DataType(DataType.ImageUrl)]
+        [Comment("이미지")]
+        public string? Image { get; set; } = null;
+
+        [Required]
+        [Comment("최소 경험치(Exp)")]
+        public int RequiredExp { get; set; } = 0;
+
+        [Required]
+        [Comment("최소 코인(Coin)")]
+        public int RequiredCoin { get; set; } = 0;
+
+        [Comment("사용 여부")]
+        public bool IsActive { get; set; } = false;
+
+        [Comment("수정 일시")]
+        public DateTime? UpdatedAt { get; set; } = null;
+
+        [Required]
+        [Comment("등록 일시")]
+        public DateTime CreatedAt { get; set; }
+    }
+}

+ 31 - 9
backend/Services/EmailSender.cs

@@ -1,29 +1,51 @@
-using Azure.Core;
+using bitforum.Repository;
 using Microsoft.AspNetCore.Identity.UI.Services;
-using Microsoft.Extensions.Options;
 using System.Net;
 using System.Net.Mail;
-using System.Threading.Tasks;
 
 namespace bitforum.Services
 {
     public class EmailSender : IEmailSender
     {
         private readonly ILogger _logger;
+        private readonly ConfigRepository _configRepository;
 
         private readonly string _smtpServer;
         private readonly int _smtpPort;
         private readonly string _fromEmail;
         private readonly string _emailPassword;
 
-        public EmailSender(IConfiguration configuration, ILogger<EmailSender> logger)
+        public EmailSender(IConfiguration configuration, ILogger<EmailSender> logger, ConfigRepository configRepository)
         {
-            var emailSettings = configuration.GetSection("EmailSettings");
-            _smtpServer = emailSettings["SmtpServer"];
-            _smtpPort = int.Parse(emailSettings["SmtpPort"]);
-            _fromEmail = emailSettings["FromEmail"];
-            _emailPassword = emailSettings["EmailPassword"];
+            _configRepository = configRepository;
             _logger = logger;
+
+            // 1차로 Config 값 SMTP 조회
+            _smtpServer = _configRepository.GetByKey("smtp_server")?.Value ?? string.Empty;
+            _smtpPort = int.TryParse(_configRepository.GetByKey("smtp_port")?.Value, out var port) ? port : 0;
+            _fromEmail = _configRepository.GetByKey("smtp_from_email")?.Value ?? string.Empty;
+            _emailPassword = _configRepository.GetByKey("smtp_email_password")?.Value ?? string.Empty;
+
+
+            // 2차로 appsettings.json 값 SMTP 조회
+            var emailSettings = configuration.GetSection("EmailSettings");
+
+            if (string.IsNullOrEmpty(_smtpServer))
+            {
+                _smtpServer = emailSettings["SmtpServer"] ?? string.Empty;
+            }
+            if (_smtpPort <= 0)
+            {
+                _smtpPort = int.TryParse(emailSettings["SmtpPort"], out var smtpPort) ? smtpPort : 0;
+            }
+            if (string.IsNullOrEmpty(_fromEmail))
+            {
+                _fromEmail = emailSettings["FromEmail"] ?? string.Empty;
+            }
+            if (string.IsNullOrEmpty(_emailPassword))
+            {
+                _emailPassword = emailSettings["EmailPassword"] ?? string.Empty;
+            }
         }
 
         public async Task SendEmailAsync(string email, string subject, string message)

+ 14 - 1
backend/Views/Setting/Basic.cshtml

@@ -1,8 +1,10 @@
-@using bitforum.Helpers
+@using bitforum.Helpers;
+@using bitforum.Models.User;
 
 @{
     ViewData["Title"] = "기본 설정";
     var config = ViewBag.Config as Dictionary<string, string>;
+    var admins = ViewBag.Admin as List<ApplicationUser>;
 }
 
 <div id="settingBasic" class="container">
@@ -22,6 +24,17 @@
         <div class="row mb-3">
             <label for="rootID" class="col-sm-2 col-form-label">최고 관리자</label>
             <div class="col-sm-10">
+                @if (admins != null) {
+                    <select name="root_id" id="rootID" class="form-select w-auto">
+                        <option value="" selected="@(config.GetConfig("root_id") == null)">선택하세요.</option>
+                        @foreach (var admin in admins as List<ApplicationUser>)
+                        {
+                            <option value="@admin.Id" selected="@(config.GetConfig("root_id") == admin.Id)">
+                                @admin.Email - @admin.FullName
+                            </option>
+                        }
+                    </select>
+                }
             </div>
         </div>
         <div class="row mb-3">

+ 7 - 0
backend/appsettings.json

@@ -19,5 +19,12 @@
     "ConnectionStrings": {
         //"DefaultConnection": "Server=192.168.0.110;Database=bitforum;Trusted_Connection=True;MultipleActiveResultSets=true"
         "DefaultConnection": "Server=192.168.0.110;Database=bitforum;User ID=sa;Password=@@20120726KKh;Encrypt=False;"
+    },
+
+    "EmailSettings": {
+        "SmtpServer": "smtp.gmail.com",
+        "SmtpPort": 587,
+        "FromEmail": "chorongski@gmail.com",
+        "EmailPassword": "lfxciuwuopjlfdzc"
     }
 }

+ 7 - 0
backend/bin/Debug/net8.0/appsettings.json

@@ -19,5 +19,12 @@
     "ConnectionStrings": {
         //"DefaultConnection": "Server=192.168.0.110;Database=bitforum;Trusted_Connection=True;MultipleActiveResultSets=true"
         "DefaultConnection": "Server=192.168.0.110;Database=bitforum;User ID=sa;Password=@@20120726KKh;Encrypt=False;"
+    },
+
+    "EmailSettings": {
+        "SmtpServer": "smtp.gmail.com",
+        "SmtpPort": 587,
+        "FromEmail": "chorongski@gmail.com",
+        "EmailPassword": "lfxciuwuopjlfdzc"
     }
 }

BIN
backend/bin/Debug/net8.0/bitforum.dll


BIN
backend/bin/Debug/net8.0/bitforum.exe


BIN
backend/bin/Debug/net8.0/bitforum.pdb


+ 2 - 2
backend/bitforum.csproj

@@ -33,8 +33,8 @@
 	</ItemGroup>
 
 	<ItemGroup>
-	  <Folder Include="Models\Board\Comment\" />
-	  <Folder Include="Models\Board\Post\" />
+	  <Folder Include="Models\BBS\Comment\" />
+	  <Folder Include="Models\BBS\Post\" />
 	  <Folder Include="wwwroot\editor\popup\" />
 	  <Folder Include="wwwroot\editor\faq\" />
 	  <Folder Include="wwwroot\editor\document\" />

BIN
backend/obj/Debug/net8.0/apphost.exe


+ 1 - 1
backend/obj/Debug/net8.0/bitforum.AssemblyInfo.cs

@@ -15,7 +15,7 @@ using System.Reflection;
 [assembly: System.Reflection.AssemblyCompanyAttribute("bitforum")]
 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
 [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
-[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3cea9e312c3937845f9ab1910ca8e39bcadbc7ac")]
+[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+14d5fe7a6422dd596f25673dc939d2df0229da97")]
 [assembly: System.Reflection.AssemblyProductAttribute("bitforum")]
 [assembly: System.Reflection.AssemblyTitleAttribute("bitforum")]
 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

+ 1 - 1
backend/obj/Debug/net8.0/bitforum.AssemblyInfoInputs.cache

@@ -1 +1 @@
-1c2586375e8b8ba845e40954ba4cde413881a797fce7b0065b18aa37cdb0cb59
+f069be6199c3729a6159e28c220afa64dd1433d8cc4c3612f6ce685fff8d759c

+ 1 - 1
backend/obj/Debug/net8.0/bitforum.csproj.CoreCompileInputs.cache

@@ -1 +1 @@
-020718fb23fd63cdc0277b5cb0884a557956d61d5e3249e5cb4a695c2c8c2851
+cb057725851a14b97cf3cd284d7cd6bbb790136610984a3a2c643cc42009e4e6

+ 0 - 1
backend/obj/Debug/net8.0/bitforum.csproj.FileListAbsolute.txt

@@ -262,4 +262,3 @@ E:\workspace\bitforum\backend\obj\Debug\net8.0\refint\bitforum.dll
 E:\workspace\bitforum\backend\obj\Debug\net8.0\bitforum.pdb
 E:\workspace\bitforum\backend\obj\Debug\net8.0\bitforum.genruntimeconfig.cache
 E:\workspace\bitforum\backend\obj\Debug\net8.0\ref\bitforum.dll
-E:\workspace\bitforum\backend\obj\Debug\net8.0\staticwebassets.upToDateCheck.txt

BIN
backend/obj/Debug/net8.0/bitforum.dll


BIN
backend/obj/Debug/net8.0/bitforum.pdb


BIN
backend/obj/Debug/net8.0/ref/bitforum.dll


BIN
backend/obj/Debug/net8.0/refint/bitforum.dll


Файловите разлики са ограничени, защото са твърде много
+ 212 - 212
backend/obj/Debug/net8.0/staticwebassets.build.json


+ 0 - 1
backend/obj/Debug/net8.0/staticwebassets.removed.txt

@@ -1 +0,0 @@
-E:\workspace\bitforum\backend\wwwroot\upload\banner\e35f9044-43ce-4dd5-bd76-6d8e2c0b66b6.png

+ 0 - 294
backend/obj/Debug/net8.0/staticwebassets.upToDateCheck.txt

@@ -1,294 +0,0 @@
-wwwroot\css\account.css
-wwwroot\css\account.min.css
-wwwroot\css\admin.css
-wwwroot\css\admin.min.css
-wwwroot\css\site.css
-wwwroot\css\site.min.css
-wwwroot\editor\banner\a83814d0-245e-42d0-9871-c3aa9c0a2a0a.png
-wwwroot\images\favicon.ico
-wwwroot\js\func.js
-wwwroot\js\site.js
-wwwroot\lib\bootstrap\dist\css\bootstrap.css
-wwwroot\lib\bootstrap\dist\css\bootstrap.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.css
-wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.min.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.min.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.min.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.min.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.min.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.min.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.css.map
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.min.css
-wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.min.css.map
-wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.js
-wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.js.map
-wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.min.js
-wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.min.js.map
-wwwroot\lib\bootstrap\dist\js\bootstrap.esm.js
-wwwroot\lib\bootstrap\dist\js\bootstrap.esm.js.map
-wwwroot\lib\bootstrap\dist\js\bootstrap.esm.min.js
-wwwroot\lib\bootstrap\dist\js\bootstrap.esm.min.js.map
-wwwroot\lib\bootstrap\dist\js\bootstrap.js
-wwwroot\lib\bootstrap\dist\js\bootstrap.js.map
-wwwroot\lib\bootstrap\dist\js\bootstrap.min.js
-wwwroot\lib\bootstrap\dist\js\bootstrap.min.js.map
-wwwroot\lib\bootstrap\LICENSE
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5.css
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5.css.map
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5.js
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5.js.map
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5.umd.js
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5.umd.js.map
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5-content.css
-wwwroot\lib\ckeditor\ckeditor5\ckeditor5-editor.css
-wwwroot\lib\ckeditor\ckeditor5\translations\af.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\af.js
-wwwroot\lib\ckeditor\ckeditor5\translations\af.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ar.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ar.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ar.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ast.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ast.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ast.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\az.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\az.js
-wwwroot\lib\ckeditor\ckeditor5\translations\az.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\bg.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\bg.js
-wwwroot\lib\ckeditor\ckeditor5\translations\bg.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\bn.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\bn.js
-wwwroot\lib\ckeditor\ckeditor5\translations\bn.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\bs.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\bs.js
-wwwroot\lib\ckeditor\ckeditor5\translations\bs.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ca.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ca.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ca.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\cs.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\cs.js
-wwwroot\lib\ckeditor\ckeditor5\translations\cs.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\da.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\da.js
-wwwroot\lib\ckeditor\ckeditor5\translations\da.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\de.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\de.js
-wwwroot\lib\ckeditor\ckeditor5\translations\de.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\de-ch.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\de-ch.js
-wwwroot\lib\ckeditor\ckeditor5\translations\de-ch.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\el.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\el.js
-wwwroot\lib\ckeditor\ckeditor5\translations\el.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\en.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\en.js
-wwwroot\lib\ckeditor\ckeditor5\translations\en.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\en-au.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\en-au.js
-wwwroot\lib\ckeditor\ckeditor5\translations\en-au.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\en-gb.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\en-gb.js
-wwwroot\lib\ckeditor\ckeditor5\translations\en-gb.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\eo.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\eo.js
-wwwroot\lib\ckeditor\ckeditor5\translations\eo.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\es.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\es.js
-wwwroot\lib\ckeditor\ckeditor5\translations\es.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\es-co.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\es-co.js
-wwwroot\lib\ckeditor\ckeditor5\translations\es-co.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\et.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\et.js
-wwwroot\lib\ckeditor\ckeditor5\translations\et.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\eu.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\eu.js
-wwwroot\lib\ckeditor\ckeditor5\translations\eu.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\fa.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\fa.js
-wwwroot\lib\ckeditor\ckeditor5\translations\fa.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\fi.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\fi.js
-wwwroot\lib\ckeditor\ckeditor5\translations\fi.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\fr.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\fr.js
-wwwroot\lib\ckeditor\ckeditor5\translations\fr.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\gl.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\gl.js
-wwwroot\lib\ckeditor\ckeditor5\translations\gl.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\gu.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\gu.js
-wwwroot\lib\ckeditor\ckeditor5\translations\gu.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\he.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\he.js
-wwwroot\lib\ckeditor\ckeditor5\translations\he.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hi.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\hi.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hi.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hr.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\hr.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hr.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hu.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\hu.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hu.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hy.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\hy.js
-wwwroot\lib\ckeditor\ckeditor5\translations\hy.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\id.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\id.js
-wwwroot\lib\ckeditor\ckeditor5\translations\id.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\it.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\it.js
-wwwroot\lib\ckeditor\ckeditor5\translations\it.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ja.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ja.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ja.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\jv.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\jv.js
-wwwroot\lib\ckeditor\ckeditor5\translations\jv.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\kk.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\kk.js
-wwwroot\lib\ckeditor\ckeditor5\translations\kk.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\km.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\km.js
-wwwroot\lib\ckeditor\ckeditor5\translations\km.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\kn.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\kn.js
-wwwroot\lib\ckeditor\ckeditor5\translations\kn.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ko.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ko.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ko.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ku.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ku.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ku.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\lt.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\lt.js
-wwwroot\lib\ckeditor\ckeditor5\translations\lt.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\lv.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\lv.js
-wwwroot\lib\ckeditor\ckeditor5\translations\lv.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ms.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ms.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ms.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\nb.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\nb.js
-wwwroot\lib\ckeditor\ckeditor5\translations\nb.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ne.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ne.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ne.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\nl.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\nl.js
-wwwroot\lib\ckeditor\ckeditor5\translations\nl.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\no.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\no.js
-wwwroot\lib\ckeditor\ckeditor5\translations\no.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\oc.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\oc.js
-wwwroot\lib\ckeditor\ckeditor5\translations\oc.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\pl.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\pl.js
-wwwroot\lib\ckeditor\ckeditor5\translations\pl.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\pt.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\pt.js
-wwwroot\lib\ckeditor\ckeditor5\translations\pt.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\pt-br.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\pt-br.js
-wwwroot\lib\ckeditor\ckeditor5\translations\pt-br.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ro.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ro.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ro.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ru.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ru.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ru.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\si.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\si.js
-wwwroot\lib\ckeditor\ckeditor5\translations\si.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sk.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\sk.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sk.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sl.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\sl.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sl.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sq.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\sq.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sq.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sr.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\sr.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sr.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sr-latn.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\sr-latn.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sr-latn.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sv.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\sv.js
-wwwroot\lib\ckeditor\ckeditor5\translations\sv.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\th.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\th.js
-wwwroot\lib\ckeditor\ckeditor5\translations\th.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ti.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ti.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ti.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\tk.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\tk.js
-wwwroot\lib\ckeditor\ckeditor5\translations\tk.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\tr.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\tr.js
-wwwroot\lib\ckeditor\ckeditor5\translations\tr.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\tt.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\tt.js
-wwwroot\lib\ckeditor\ckeditor5\translations\tt.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ug.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ug.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ug.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\uk.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\uk.js
-wwwroot\lib\ckeditor\ckeditor5\translations\uk.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ur.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\ur.js
-wwwroot\lib\ckeditor\ckeditor5\translations\ur.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\uz.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\uz.js
-wwwroot\lib\ckeditor\ckeditor5\translations\uz.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\vi.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\vi.js
-wwwroot\lib\ckeditor\ckeditor5\translations\vi.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\zh.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\zh.js
-wwwroot\lib\ckeditor\ckeditor5\translations\zh.umd.js
-wwwroot\lib\ckeditor\ckeditor5\translations\zh-cn.d.ts
-wwwroot\lib\ckeditor\ckeditor5\translations\zh-cn.js
-wwwroot\lib\ckeditor\ckeditor5\translations\zh-cn.umd.js
-wwwroot\lib\ckeditor\index.html
-wwwroot\lib\ckeditor\LICENSE.md
-wwwroot\lib\ckeditor\README.md
-wwwroot\lib\jquery\dist\jquery.js
-wwwroot\lib\jquery\dist\jquery.min.js
-wwwroot\lib\jquery\dist\jquery.min.map
-wwwroot\lib\jquery\LICENSE.txt
-wwwroot\lib\jquery-validation\dist\additional-methods.js
-wwwroot\lib\jquery-validation\dist\additional-methods.min.js
-wwwroot\lib\jquery-validation\dist\jquery.validate.js
-wwwroot\lib\jquery-validation\dist\jquery.validate.min.js
-wwwroot\lib\jquery-validation\LICENSE.md
-wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js
-wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js
-wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt

Някои файлове не бяха показани, защото твърде много файлове са промени