diff --git a/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs b/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs index 2ed1892..ac31849 100644 --- a/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs +++ b/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs @@ -14,28 +14,36 @@ namespace SheetMe.Core.Catalog; /// (전체 검색 + 감사 로그), 그래서 남기는 쪽이 안전장치의 본체다 — /// 조회 자체를 막지 않는 대신 흔적을 남긴다. /// -/// 조건은 와 같은 축을 쓴다. 환자 기록을 보는 일은 -/// 지금 쓰이는 서식을 제자리에서 고치는 일과 무게가 다르지 않다. +/// 부서 문(전산실)을 걸지 않는다. 처음에는 를 그대로 갖다 썼는데 +/// 그건 레거시에 없는 제약이었다. 레거시가 부서로 가리는 툴은 TK_MODIFY 하나뿐이고 +/// (frmSheetDesigner.vb:1030-1060, MSYS 전용인 TK_ExportXML/ImportXML 은 계정 문), +/// TK_PREVIEW 에는 어떤 가시성 조건도 걸리지 않는다 — 서식생성기를 열 수 있으면 쓸 수 있다. +/// +/// 두 일의 무게가 다르기도 하다. 수정은 지금 쓰이는 서식을 제자리에서 바꿔 병원 전체에 +/// 즉시 영향을 준다. 미리보기는 이미 그 사람이 볼 수 있는 기록을 읽기만 한다. +/// 여기에 부서 문을 걸면 서식을 만드는 사람이 자기 서식을 검증할 수 없게 되고, +/// 검증을 못 하면 값이 틀린 서식이 그대로 운영에 올라간다 — 막아서 더 위험해지는 쪽이다. /// public static class PatientPreviewPolicy { #region Methods /// - /// 이 사용자가 환자 데이터로 미리보기를 볼 수 있는가. + /// 이 사용자가 환자 데이터로 미리보기를 볼 수 있는가 — 인증만 요구한다. /// - /// 인증된 HIS 사용자여야 한다 — 미인증이면 감사 로그에 남길 주체가 없고, - /// 주체 없는 환자 조회는 그 자체로 남기면 안 되는 일이다. + /// 미인증이면 감사 로그에 남길 주체가 없고, 주체 없는 환자 조회는 남기면 안 되는 일이다. + /// 그것이 유일한 조건이다. 병원·부서 인자는 일부러 받아 두고 쓰지 않는다 — + /// 병원별 규칙이 생기면 호출부를 고치지 않고 여기서 받을 수 있어야 하고, + /// 인자가 없으면 그때 호출부 전부를 다시 손대야 한다. /// public static bool CanPreviewPatient(string hospitalCode, string departmentCode, string uidCod, string hospitalStartDate) - => uidCod.Length > 0 - && ModifyPolicy.CanModify(hospitalCode, departmentCode, uidCod, hospitalStartDate); + => uidCod.Length > 0; /// 왜 막혔는지 — "권한이 없습니다"만으로는 누구에게 물어야 할지 모른다 public static string DenyReason(string hospitalCode, string uidCod, string hospitalStartDate) => uidCod.Length == 0 ? "HIS 사용자가 확인되지 않았습니다. 기록지정보 화면에서 실행하거나 사용자 코드를 전달해 주세요." - : ModifyPolicy.DenyReason(hospitalCode, uidCod, hospitalStartDate); + : string.Empty; /// /// 감사 로그 한 줄 — 누가·언제·어느 내원을 열었는가. diff --git a/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs b/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs index f52ddc4..55e2944 100644 --- a/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs +++ b/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs @@ -132,11 +132,12 @@ internal sealed class FormDesignDataBusiness UserSession.Current.HspCod, UserSession.Current.UidCod, HospitalStartDate); /// - /// 이 사용자가 실제 환자로 미리보기를 할 수 있는가. + /// 이 사용자가 실제 환자로 미리보기를 할 수 있는가 — 인증만 확인한다. /// - /// 수정과 같은 문을 쓴다 — 서식생성기에서 환자 정보를 꺼내 보는 것은 진료 행위가 아니라 - /// 서식이 맞게 뽑히는지 확인하는 일이고, 그 권한은 레거시가 전산실에만 열어 둔 것과 같은 범위다. - /// 여기를 넓히면 서식생성기가 환자 조회 도구가 된다. + /// 수정과 다른 문이다. 레거시가 부서로 가리는 툴은 TK_MODIFY 하나뿐이고 + /// TK_PREVIEW 에는 조건이 없다(frmSheetDesigner.vb:1030-1060). + /// 여기에 부서 문을 걸면 서식을 만든 사람이 자기 서식을 검증할 수 없다. + /// 안전장치는 막는 것이 아니라 감사 로그다. /// public static bool CanPreviewPatient() => PatientPreviewPolicy.CanPreviewPatient( UserSession.Current.HspCod, UserSession.Current.DepCod, UserSession.Current.UidCod, diff --git a/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs b/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs index d58d224..4b3d75b 100644 --- a/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs +++ b/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs @@ -5,9 +5,9 @@ namespace SheetMe.Core.Tests; /// /// 환자 미리보기 접근 규칙 고정. /// -/// 이 표가 느슨해지면 서식을 만드는 사람 누구나 운영 환자 기록을 열 수 있다. -/// 레거시가 그 상태였다 — 인가코드가 소스에 평문이고, 검색 범위 무제한이고, 감사 0건이다. -/// 검색 범위는 레거시와 같게 두기로 했으므로 감사와 권한이 유일한 장치다. +/// 레거시는 인가코드가 소스에 평문이고, 검색 범위 무제한이고, 감사 0건이었다. +/// 검색 범위와 접근 범위는 레거시와 같게 두기로 했으므로 감사 로그가 유일한 장치다 — +/// 그래서 감사 한 줄의 모양(주체가 있는가, 이름이 새지 않는가)이 여기서 가장 중요한 판정이다. /// [TestClass] public sealed class PatientPreviewPolicyTests @@ -23,13 +23,30 @@ public sealed class PatientPreviewPolicyTests } [TestMethod] - public void 수정_권한과_같은_축을_쓴다() + public void 부서로_막지_않는다() { - // 환자 기록을 보는 일은 지금 쓰이는 서식을 제자리에서 고치는 일과 무게가 다르지 않다. - Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("ABC", "EDPS", "011825", string.Empty)); - Assert.IsFalse(PatientPreviewPolicy.CanPreviewPatient("ABC", "NURS", "011825", string.Empty)); - Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("HANKOOK", "SALO", "011825", string.Empty)); - Assert.IsFalse(PatientPreviewPolicy.CanPreviewPatient("XYZ", "EDPS", "011825", "20250501")); + // 처음에는 수정 권한(ModifyPolicy)을 그대로 갖다 썼다. 그건 레거시에 없는 제약이었다 — + // 레거시가 부서로 가리는 툴은 TK_MODIFY 하나뿐이고 TK_PREVIEW 에는 문이 없다 + // (frmSheetDesigner.vb:1030-1060). 서식을 만드는 사람이 자기 서식을 검증할 수 없으면 + // 값이 틀린 서식이 그대로 운영에 올라간다. + foreach (var dep in new[] { "EDPS", "NURS", "SALO", "MEDI", "" }) + { + Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("ABC", dep, "011825", string.Empty), + $"부서 '{dep}' 로 막혔다"); + } + // 수정에만 걸리던 갈래도 미리보기에는 걸리지 않는다 + Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("XYZ", "NURS", "011825", "20250501")); + Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("HANKOOK", "NURS", "011825", string.Empty)); + } + + [TestMethod] + public void 수정_권한은_그대로_좁게_남는다() + { + // 미리보기를 연 것이 수정까지 연 것이 되면 안 된다 — 수정은 지금 쓰이는 서식을 + // 제자리에서 바꿔 병원 전체에 즉시 영향을 준다. 이 대조가 없으면 위 완화가 + // 조용히 ModifyPolicy 까지 번져도 알 수 없다. + Assert.IsFalse(ModifyPolicy.CanModify("ABC", "NURS", "011825", string.Empty)); + Assert.IsTrue(ModifyPolicy.CanModify("ABC", "EDPS", "011825", string.Empty)); } [TestMethod]