337 lines
10 KiB
Go
337 lines
10 KiB
Go
package authentication
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/golang-jwt/jwt"
|
|
"github.com/google/uuid"
|
|
dg "github.com/karincake/apem/db-gorm-pg"
|
|
ms "github.com/karincake/apem/ms-redis"
|
|
d "github.com/karincake/dodol"
|
|
l "github.com/karincake/lepet"
|
|
|
|
pl "simrs-vx/pkg/logger"
|
|
|
|
edp "simrs-vx/internal/domain/main-entities/division-position"
|
|
ed "simrs-vx/internal/domain/main-entities/doctor"
|
|
ee "simrs-vx/internal/domain/main-entities/employee"
|
|
eip "simrs-vx/internal/domain/main-entities/installation-position"
|
|
"simrs-vx/internal/domain/main-entities/intern"
|
|
em "simrs-vx/internal/domain/main-entities/midwife"
|
|
en "simrs-vx/internal/domain/main-entities/nurse"
|
|
ep "simrs-vx/internal/domain/main-entities/pharmacist"
|
|
esp "simrs-vx/internal/domain/main-entities/specialist-position"
|
|
essp "simrs-vx/internal/domain/main-entities/subspecialist-position"
|
|
eup "simrs-vx/internal/domain/main-entities/unit-position"
|
|
eu "simrs-vx/internal/domain/main-entities/user"
|
|
erg "simrs-vx/internal/domain/references/organization"
|
|
|
|
udp "simrs-vx/internal/use-case/main-use-case/division-position"
|
|
uip "simrs-vx/internal/use-case/main-use-case/installation-position"
|
|
usp "simrs-vx/internal/use-case/main-use-case/specialist-position"
|
|
ussp "simrs-vx/internal/use-case/main-use-case/subspecialist-position"
|
|
uup "simrs-vx/internal/use-case/main-use-case/unit-position"
|
|
)
|
|
|
|
// just return the error code
|
|
func getAndCheck(input, condition any, includes any) (eCode string) {
|
|
qry := dg.I.Where(condition)
|
|
|
|
// WARNING THIS PRELOAD FAILS
|
|
if includes != nil {
|
|
if val := includes.(string); val != "" {
|
|
qry = qry.Preload(val)
|
|
} else if vals := includes.([]string); len(vals) > 0 {
|
|
for _, val := range vals {
|
|
qry = qry.Preload(val)
|
|
}
|
|
}
|
|
}
|
|
|
|
result := qry.First(&input)
|
|
if result.Error != nil {
|
|
return "fetch-fail"
|
|
} else if result.RowsAffected == 0 {
|
|
return "auth-login-incorrect"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func getDivisionPosition(employee_id uint, event *pl.Event) ([]string, error) {
|
|
var result []string
|
|
|
|
// get data division_position based on employee_id
|
|
data, _, err := udp.ReadListData(edp.ReadListDto{FilterDto: edp.FilterDto{Employee_Id: &employee_id}}, event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(data) > 0 {
|
|
for _, dp := range data {
|
|
result = append(result, "div|"+*dp.Division_Code+"|"+dp.Code)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func getInstallationPosition(employeeId uint, event *pl.Event) ([]string, error) {
|
|
var result []string
|
|
|
|
// get data unit_position based on employee_id
|
|
data, _, err := uip.ReadListData(eip.ReadListDto{
|
|
FilterDto: eip.FilterDto{Employee_Id: &employeeId},
|
|
Includes: "installation"}, event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(data) > 0 {
|
|
for _, dp := range data {
|
|
result = append(result, "inst|"+*dp.Installation_Code+"|"+dp.Code)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func getUnitPosition(employeeId uint, event *pl.Event) ([]string, error) {
|
|
var result []string
|
|
|
|
// get data unit_position based on employee_id
|
|
data, _, err := uup.ReadListData(eup.ReadListDto{FilterDto: eup.FilterDto{Employee_Id: &employeeId}}, event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(data) > 0 {
|
|
for _, dp := range data {
|
|
result = append(result, "unit|"+*dp.Unit_Code+"|"+dp.Code)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func getSpecialistPosition(employeeId uint, event *pl.Event) ([]string, error) {
|
|
var result []string
|
|
|
|
// get data unit_position based on employee_id
|
|
data, _, err := usp.ReadListData(esp.ReadListDto{FilterDto: esp.FilterDto{Employee_Id: &employeeId}}, event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(data) > 0 {
|
|
for _, dp := range data {
|
|
result = append(result, "spec|"+*dp.Specialist_Code+"|"+dp.Code)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func getSubspecialistPosition(employeeId uint, event *pl.Event) ([]string, error) {
|
|
var result []string
|
|
|
|
// get data unit_position based on employee_id
|
|
data, _, err := ussp.ReadListData(essp.ReadListDto{
|
|
FilterDto: essp.FilterDto{Employee_Id: &employeeId},
|
|
Includes: "subspecialist"}, event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(data) > 0 {
|
|
for _, dp := range data {
|
|
result = append(result, "subspec|"+dp.Subspecialist.Code+"|"+dp.Code)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func checkStrClaims(claim map[string]interface{}, key string) string {
|
|
if v, exist := claim[key]; exist && v != nil {
|
|
return v.(string)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func checkStrPtrClaims(claim map[string]interface{}, key string) *string {
|
|
if v, exist := claim[key]; exist && v != nil {
|
|
val := v.(string)
|
|
return &val
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func checkUntPtrClaims(claim map[string]interface{}, key string) *uint {
|
|
if v, exist := claim[key]; exist && v != nil {
|
|
val := uint(v.(float64))
|
|
return &val
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error {
|
|
id, err := uuid.NewRandom()
|
|
if err != nil {
|
|
panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err))
|
|
}
|
|
if input.Duration == 0 {
|
|
input.Duration = 24 * 60
|
|
}
|
|
duration := time.Minute * time.Duration(input.Duration)
|
|
aUuid := id.String()
|
|
atExpires := time.Now().Add(duration).Unix()
|
|
|
|
atClaims["uuid"] = aUuid
|
|
atClaims["exp"] = atExpires
|
|
atClaims["user_id"] = user.Id
|
|
atClaims["user_name"] = user.Name
|
|
atClaims["user_contractPosition_code"] = user.ContractPosition_Code
|
|
|
|
outputData["user_id"] = user.Id
|
|
outputData["user_name"] = user.Name
|
|
outputData["user_contractPosition_code"] = user.ContractPosition_Code
|
|
|
|
roles := []string{}
|
|
switch user.ContractPosition_Code {
|
|
case erg.CSCEmp:
|
|
// employee
|
|
employee := ee.Employee{}
|
|
dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee)
|
|
if employee.Id == 0 {
|
|
return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}}
|
|
}
|
|
atClaims["employee_id"] = employee.Id
|
|
outputData["employee_id"] = employee.Id
|
|
roles = append(roles, "emp|"+string(*employee.Position_Code))
|
|
|
|
// employee position
|
|
if employee.Id > 0 && employee.Position_Code != nil {
|
|
atClaims["employee_position_code"] = *employee.Position_Code
|
|
switch *employee.Position_Code {
|
|
case erg.EPCDoc:
|
|
doctor := ed.Doctor{}
|
|
dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor)
|
|
if doctor.Id == 0 {
|
|
return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}}
|
|
}
|
|
atClaims["doctor_code"] = doctor.Code
|
|
outputData["doctor_code"] = doctor.Code
|
|
|
|
// specialist
|
|
if doctor.Unit_Code != nil {
|
|
atClaims["unit_code"] = doctor.Unit_Code
|
|
outputData["unit_code"] = doctor.Unit_Code
|
|
}
|
|
if doctor.Specialist_Code != nil {
|
|
atClaims["specialist_code"] = doctor.Specialist_Code
|
|
outputData["specialist_code"] = doctor.Specialist_Code
|
|
}
|
|
if doctor.Subspecialist_Code != nil {
|
|
atClaims["subspecialist_code"] = doctor.Subspecialist_Code
|
|
outputData["subspecialist_code"] = doctor.Subspecialist_Code
|
|
}
|
|
case erg.EPCNur:
|
|
empData := en.Nurse{}
|
|
dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData)
|
|
if empData.Id == 0 {
|
|
return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}}
|
|
}
|
|
atClaims["nurse_code"] = empData.Code
|
|
outputData["nurse_code"] = empData.Code
|
|
case erg.EPCMwi:
|
|
empData := em.Midwife{}
|
|
dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData)
|
|
if empData.Id == 0 {
|
|
return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}}
|
|
}
|
|
atClaims["midwife_code"] = empData.Code
|
|
outputData["midwife_code"] = empData.Code
|
|
case erg.EPCPha:
|
|
empData := ep.Pharmacist{}
|
|
dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData)
|
|
if empData.Id == 0 {
|
|
return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}}
|
|
}
|
|
atClaims["pharmacist_code"] = empData.Code
|
|
outputData["pharmacist_code"] = empData.Code
|
|
}
|
|
|
|
errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}}
|
|
|
|
// division position
|
|
divisionPositions, err := getDivisionPosition(employee.Id, &event)
|
|
if err != nil {
|
|
return errorGetPosition
|
|
}
|
|
|
|
// installation position
|
|
installationPositions, err := getInstallationPosition(employee.Id, &event)
|
|
if err != nil {
|
|
return errorGetPosition
|
|
}
|
|
|
|
// unit position
|
|
unitPositions, err := getUnitPosition(employee.Id, &event)
|
|
if err != nil {
|
|
return errorGetPosition
|
|
}
|
|
|
|
// specialist position
|
|
specialistPositions, err := getSpecialistPosition(employee.Id, &event)
|
|
if err != nil {
|
|
return errorGetPosition
|
|
}
|
|
|
|
// subspecialist position
|
|
subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event)
|
|
if err != nil {
|
|
return errorGetPosition
|
|
}
|
|
|
|
roles = append(roles, divisionPositions...)
|
|
roles = append(roles, installationPositions...)
|
|
roles = append(roles, unitPositions...)
|
|
roles = append(roles, specialistPositions...)
|
|
roles = append(roles, subspecialistPositions...)
|
|
// atClaims["division_positions"] = divsionPositions
|
|
// outputData["division_positions"] = divsionPositions
|
|
}
|
|
case erg.CSCInt:
|
|
intern := intern.Intern{}
|
|
dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern)
|
|
roles = append(roles, "int-"+string(*intern.Position_Code))
|
|
case erg.CSCSys:
|
|
roles = append(roles, "system")
|
|
}
|
|
atClaims["roles"] = roles
|
|
outputData["roles"] = roles
|
|
|
|
// Generate jwt
|
|
atSecretKey := authCfg.AtSecretKey
|
|
at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims)
|
|
ats, err := at.SignedString([]byte(atSecretKey))
|
|
if err != nil {
|
|
return d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}}
|
|
}
|
|
outputData["accessToken"] = ats
|
|
|
|
// Save to redis
|
|
exp, _ := atClaims["exp"].(int64)
|
|
now := time.Now()
|
|
atx := time.Unix(exp, 0) //converting Unix to UTC(to Time object)
|
|
err = ms.I.Set(atClaims["uuid"].(string), strconv.Itoa(int(user.Id)), atx.Sub(now)).Err()
|
|
if err != nil {
|
|
panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error()))
|
|
}
|
|
|
|
return nil
|
|
}
|