Merge pull request #145 from dikstub-rssa/fix/anything-moko

fix (encounter): add guard for create, delete and cancel
This commit is contained in:
Dwi Atmoko Purbo Sakti
2025-11-13 14:52:29 +07:00
committed by GitHub
6 changed files with 73 additions and 10 deletions
@@ -104,10 +104,14 @@ type UpdateDto struct {
type UpdateStatusDto struct {
Id uint16 `json:"id"`
StatusCode erc.DataStatusCode `json:"status_code"`
pa.AuthInfo
}
type DeleteDto struct {
Id uint16 `json:"id"`
pa.AuthInfo
}
type MetaDto struct {
@@ -89,9 +89,14 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) {
if id <= 0 {
return
}
authInfo, err := pa.GetAuthInfo(r)
if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
}
dto := e.DeleteDto{}
dto.Id = uint16(id)
dto.AuthInfo = *authInfo
res, err := u.Delete(dto)
rw.DataResponse(w, res, err)
}
@@ -159,11 +164,17 @@ func (obj myBase) Cancel(w http.ResponseWriter, r *http.Request) {
return
}
authInfo, err := pa.GetAuthInfo(r)
if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
}
dto := e.UpdateStatusDto{
Id: uint16(id),
StatusCode: erc.DSCCancel,
}
dto.AuthInfo = *authInfo
res, err := u.UpdateStatusCode(dto)
rw.DataResponse(w, res, err)
}
+1 -1
View File
@@ -11,7 +11,7 @@ type AuthInfo struct {
Uuid string
User_Id uint
User_Name string
User_ContractPosition_code string
User_ContractPosition_Code string
Employee_Position_Code *string
Employee_Id *uint
Doctor_Code *string
@@ -205,7 +205,7 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err
User_Name: fmt.Sprintf("%v", claims["user_name"]),
}
data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code")
data.User_ContractPosition_Code = checkStrClaims(claims, "contractPosition_code")
data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code")
data.Doctor_Code = checkStrPtrClaims(claims, "doctor_code")
data.Nurse_Code = checkStrPtrClaims(claims, "nurse_code")
@@ -16,10 +16,10 @@ import (
erc "simrs-vx/internal/domain/references/common"
ere "simrs-vx/internal/domain/references/encounter"
erg "simrs-vx/internal/domain/references/organization"
eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist"
edc "simrs-vx/internal/domain/main-entities/death-cause"
eem "simrs-vx/internal/domain/main-entities/employee"
e "simrs-vx/internal/domain/main-entities/encounter"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist"
@@ -27,7 +27,6 @@ import (
uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist"
udc "simrs-vx/internal/use-case/main-use-case/death-cause"
uem "simrs-vx/internal/use-case/main-use-case/employee"
uir "simrs-vx/internal/use-case/main-use-case/internal-reference"
urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist"
)
@@ -79,6 +78,19 @@ func Create(input e.CreateDto) (*d.Data, error) {
}
}
// check only user with registration position is allowed to create encounter
if input.AuthInfo.User_ContractPosition_Code != string(erg.EPCReg) {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "auth-forbidden",
Detail: "user position is not allowed, only user with registration position is allowed to create encounter",
Raw: errors.New("authentication failed"),
}
return nil, pl.SetLogError(&event, input)
} else {
input.Adm_Employee_Id = input.AuthInfo.Employee_Id
}
// check if patient is new in the hospital
input.NewStatus, err = identifyPatientStatus(input)
@@ -90,12 +102,6 @@ func Create(input e.CreateDto) (*d.Data, error) {
return err
}
if emp, err := uem.ReadDetailData(eem.ReadDetailDto{User_Id: &input.AuthInfo.User_Id}, &event, tx); err != nil {
return err
} else {
input.Adm_Employee_Id = &emp.Id
}
// create encounter
if resData, err := CreateData(input, &event, tx); err != nil {
return err
@@ -322,6 +328,17 @@ func Delete(input e.DeleteDto) (*d.Data, error) {
// Start log
pl.SetLogInfo(&event, input, "started", "delete")
// check only user with registration position is allowed to create encounter
if input.AuthInfo.User_ContractPosition_Code != string(erg.EPCReg) {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "auth-forbidden",
Detail: "user position is not allowed, only user with registration position is allowed to create encounter",
Raw: errors.New("authentication failed"),
}
return nil, pl.SetLogError(&event, input)
}
err = dg.I.Transaction(func(tx *gorm.DB) error {
pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail")
if data, err = ReadDetailData(rdDto, &event, tx); err != nil {
@@ -494,6 +511,21 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) {
// TODO: Prevent cancellation if the billing has been verified
// TODO: Only "supervisi pendaftaran" could cancel encounter
roleAllowedToCancel := []string{
string(erg.EPCReg),
string(erg.EPCNur),
string(erg.EPCDoc),
}
if !pu.Contains(roleAllowedToCancel, input.AuthInfo.User_ContractPosition_Code) {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "auth-forbidden",
Detail: "user position is not allowed, only user with registration, nurse, or doctor position is allowed to cancel encounter",
Raw: errors.New("authentication failed"),
}
return pl.SetLogError(&event, input)
}
// Prevent cancellation if soapi exist
encounterId := uint(input.Id)
+16
View File
@@ -150,3 +150,19 @@ func IsDateBeforeNow(t *time.Time) bool {
}
return t.Before(time.Now())
}
// Contains reports whether v is present in s.
func Contains[S ~[]E, E comparable](s S, v E) bool {
return index(s, v) >= 0
}
// Index returns the index of the first occurrence of v in s,
// or -1 if not present.
func index[S ~[]E, E comparable](s S, v E) int {
for i := range s {
if v == s[i] {
return i
}
}
return -1
}