commitd2ec8c0f07Author: mario <dev.mario@sismedika@gmail.com> Date: Thu May 15 15:42:33 2025 +0700 add: db tx commit and rollback implementation commit264435f67eAuthor: mario <dev.mario@sismedika@gmail.com> Date: Thu May 15 14:34:20 2025 +0700 fix: shortlink generation logic update/create commit047ab1937aAuthor: mario <dev.mario@sismedika@gmail.com> Date: Thu May 15 11:06:04 2025 +0700 fix: if multiple studies patient, show first study by default commitc13f834b92Author: mario <dev.mario@sismedika@gmail.com> Date: Thu May 15 09:46:32 2025 +0700 add: register and login with DB query AND some struct type correction commitdd4451c2a8Author: mario <dev.mario@sismedika@gmail.com> Date: Wed May 14 10:23:33 2025 +0700 new file structure & koneksi ke DB commit8289881df3Author: mario <dev.mario@sismedika@gmail.com> Date: Tue May 13 16:49:07 2025 +0700 edit: rm debug route commitdd784da232Author: mario <dev.mario@sismedika@gmail.com> Date: Tue May 13 15:44:11 2025 +0700 add: implement shortlink commit2687a761ccAuthor: mario <dev.mario@sismedika@gmail.com> Date: Tue May 13 11:47:19 2025 +0700 add new dummy doctor user commiteb67eaca46Author: mario <dev.mario@sismedika@gmail.com> Date: Tue May 13 11:46:28 2025 +0700 add: ref_doctor studylist filter commit0d4825d152Author: mario <dev.mario@sismedika@gmail.com> Date: Tue May 13 10:07:16 2025 +0700 edit study_iuids & accNum in patient jwt to array commit2d1f135fdaAuthor: mario <dev.mario@sismedika@gmail.com> Date: Tue May 13 09:52:45 2025 +0700 patient see their multiple studies commit13bb380f51Author: mario <dev.mario@sismedika@gmail.com> Date: Fri May 9 10:13:16 2025 +0700 add: cors handler route and readme commit6c9ab574ceAuthor: mario <dev.mario@sismedika@gmail.com> Date: Mon May 5 11:50:36 2025 +0700 add: login & token validation tapi belum connect ke DB commit297c9a6a01Author: mario <dev.mario@sismedika@gmail.com> Date: Mon Apr 28 15:37:02 2025 +0700 add readme.md commit9b8e0260f3Author: mario <dev.mario@sismedika@gmail.com> Date: Mon Apr 7 15:46:07 2025 +0700 connected-to-google commitf340bc5916Author: mario <dev.mario@sismedika.com> Date: Mon Apr 7 11:14:18 2025 +0700 init
168 lines
4.7 KiB
Go
168 lines
4.7 KiB
Go
package repository
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/internal/api/models"
|
|
"devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/internal/database"
|
|
"github.com/jmoiron/sqlx"
|
|
)
|
|
|
|
// DBShortLink represents a shortlink from the database
|
|
type DBShortLink struct {
|
|
ShortlinkID int `db:"ShortlinkID"`
|
|
ShortlinkCode string `db:"ShortlinkCode"`
|
|
Shortlink_PatientID string `db:"Shortlink_PatientID"`
|
|
Shortlink_Study_IUID string `db:"Shortlink_Study_IUID"`
|
|
ShortlinkHashDoB string `db:"ShortlinkHashDoB"`
|
|
ShortlinkExpiredAt time.Time `db:"ShortlinkExpiredAt"`
|
|
ShortlinkIsRevoked bool `db:"ShortlinkIsRevoked"`
|
|
ShortlinkRemainingTries int `db:"ShortlinkRemainingTries"`
|
|
ShortlinkCreatedAt time.Time `db:"ShortlinkCreatedAt"`
|
|
ShortlinkCreate_UserID int `db:"ShortlinkCreate_UserID"`
|
|
}
|
|
|
|
// ShortLinkRepository handles database operations related to shortlinks
|
|
type ShortLinkRepository struct {
|
|
*Repository
|
|
}
|
|
|
|
// NewShortLinkRepository creates a new shortlink repository
|
|
func NewShortLinkRepository() *ShortLinkRepository {
|
|
return &ShortLinkRepository{
|
|
Repository: NewRepository(),
|
|
}
|
|
}
|
|
|
|
// ToShortLink converts a DBShortLink to a ShortLink model
|
|
func (s *DBShortLink) ToShortLink() *models.ShortLink {
|
|
return &models.ShortLink{
|
|
ID: fmt.Sprintf("%d", s.ShortlinkID),
|
|
Token: s.ShortlinkCode,
|
|
PatientID: s.Shortlink_PatientID,
|
|
StudyUID: s.Shortlink_Study_IUID,
|
|
HashedDOB: s.ShortlinkHashDoB,
|
|
ExpiresAt: s.ShortlinkExpiredAt.Format(time.RFC3339),
|
|
IsRevoked: s.ShortlinkIsRevoked,
|
|
RemainingTries: s.ShortlinkRemainingTries,
|
|
CreatedAt: s.ShortlinkCreatedAt.Format(time.RFC3339),
|
|
CreatedByID: fmt.Sprintf("%d", s.ShortlinkCreate_UserID),
|
|
}
|
|
}
|
|
|
|
// GetShortLinkByToken retrieves a shortlink by token
|
|
func (r *ShortLinkRepository) GetShortLinkByToken(token string) (*models.ShortLink, error) {
|
|
var dbShortLink DBShortLink
|
|
|
|
query := `SELECT * FROM shortlink WHERE ShortlinkCode = ?`
|
|
err := database.DB.Get(&dbShortLink, query, token)
|
|
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
return nil, fmt.Errorf("database error getting shortlink: %w", err)
|
|
}
|
|
|
|
return dbShortLink.ToShortLink(), nil
|
|
}
|
|
|
|
// CreateShortLinkTx stores a new shortlink in the database within a transaction
|
|
func (r *ShortLinkRepository) CreateShortLinkTx(tx *sqlx.Tx, shortLink *models.ShortLink) error {
|
|
query := `INSERT INTO shortlink (
|
|
ShortlinkCode,
|
|
Shortlink_PatientID,
|
|
Shortlink_Study_IUID,
|
|
ShortlinkHashDoB,
|
|
ShortlinkExpiredAt,
|
|
ShortlinkIsRevoked,
|
|
ShortlinkRemainingTries,
|
|
ShortlinkCreatedAt,
|
|
ShortlinkCreate_UserID)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), ?)`
|
|
|
|
createdByID, err := strconv.Atoi(shortLink.CreatedByID)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid created by ID: %w", err)
|
|
}
|
|
|
|
expiresAt, err := time.Parse(time.RFC3339, shortLink.ExpiresAt)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid expiration date: %w", err)
|
|
}
|
|
|
|
_, err = tx.Exec(
|
|
query,
|
|
shortLink.Token,
|
|
shortLink.PatientID,
|
|
shortLink.StudyUID,
|
|
shortLink.HashedDOB,
|
|
expiresAt,
|
|
shortLink.IsRevoked,
|
|
shortLink.RemainingTries,
|
|
createdByID,
|
|
)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("database error creating shortlink: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateShortLinkTx updates an existing shortlink in the database within a transaction
|
|
func (r *ShortLinkRepository) UpdateShortLinkTx(tx *sqlx.Tx, shortLink *models.ShortLink) error {
|
|
query := `UPDATE shortlink SET
|
|
ShortlinkIsRevoked = ?,
|
|
ShortlinkRemainingTries = ?,
|
|
ShortlinkExpiredAt = ?
|
|
WHERE ShortlinkCode = ?`
|
|
|
|
expiresAt, err := time.Parse(time.RFC3339, shortLink.ExpiresAt)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid expiration date: %w", err)
|
|
}
|
|
|
|
_, err = tx.Exec(
|
|
query,
|
|
shortLink.IsRevoked,
|
|
shortLink.RemainingTries,
|
|
expiresAt,
|
|
shortLink.Token,
|
|
)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("database error updating shortlink: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetActiveShortLinkByPatientAndStudy retrieves an active (unexpired, not revoked) shortlink
|
|
// for the given patient ID and study UID
|
|
func (r *ShortLinkRepository) GetActiveShortLinkByPatientAndStudy(patientID string, studyUID string) (*models.ShortLink, error) {
|
|
var dbShortLink DBShortLink
|
|
|
|
query := `SELECT * FROM shortlink
|
|
WHERE Shortlink_PatientID = ?
|
|
AND Shortlink_Study_IUID = ?
|
|
AND ShortlinkExpiredAt > NOW()
|
|
AND ShortlinkIsRevoked = FALSE
|
|
ORDER BY ShortlinkExpiredAt DESC
|
|
LIMIT 1`
|
|
|
|
err := database.DB.Get(&dbShortLink, query, patientID, studyUID)
|
|
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
return nil, fmt.Errorf("database error getting active shortlink: %w", err)
|
|
}
|
|
|
|
return dbShortLink.ToShortLink(), nil
|
|
}
|