fix: route workbench requests to tenant database
This commit is contained in:
+73
-68
@@ -72,7 +72,7 @@ func (a *API) Healthz(w http.ResponseWriter, r *http.Request) {
|
||||
writeSuccess(w, r, map[string]any{"status": "ok", "service": "im_workbench"})
|
||||
}
|
||||
|
||||
type handlerFunc func(http.ResponseWriter, *http.Request, *auth.Principal)
|
||||
type handlerFunc func(http.ResponseWriter, *http.Request, *auth.Principal, *store.Store)
|
||||
|
||||
func (a *API) withAuth(next handlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -86,22 +86,27 @@ func (a *API) withAuth(next handlerFunc) http.HandlerFunc {
|
||||
}
|
||||
return
|
||||
}
|
||||
next(w, r, principal)
|
||||
st, err := a.store.ForTenant(r.Context(), principal.TenantID, principal.TenantCode)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
}
|
||||
next(w, r, principal, st)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) workbench(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) workbench(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
}
|
||||
modules, version, err := a.store.WorkbenchModules(r.Context(), p.UserID)
|
||||
modules, version, err := st.WorkbenchModules(r.Context(), p.UserID)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
}
|
||||
items := workbenchModulePayloads(modules)
|
||||
if err := a.populateUnread(r, p, items); err != nil {
|
||||
if err := a.populateUnread(st, r, p, items); err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
}
|
||||
@@ -122,7 +127,7 @@ func (a *API) workbench(w http.ResponseWriter, r *http.Request, p *auth.Principa
|
||||
})
|
||||
}
|
||||
|
||||
func (a *API) organizationDepartments(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) organizationDepartments(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -131,7 +136,7 @@ func (a *API) organizationDepartments(w http.ResponseWriter, r *http.Request, p
|
||||
if parentID == "" {
|
||||
parentID = "root"
|
||||
}
|
||||
items, next, err := a.store.Departments(r.Context(), p.UserID, parentID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.Departments(r.Context(), p.UserID, parentID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -139,7 +144,7 @@ func (a *API) organizationDepartments(w http.ResponseWriter, r *http.Request, p
|
||||
writeSuccess(w, r, pagePayload(organizationDepartmentPayloads(items), next))
|
||||
}
|
||||
|
||||
func (a *API) organizationDepartmentResource(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) organizationDepartmentResource(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
departmentID, tail, ok := resourceTail(r.URL.Path, "/v1/workbench/organization/departments/")
|
||||
if !ok || tail != "members" {
|
||||
writeError(w, r, http.StatusNotFound, 30004, reasonMalformedRequest, "organization route not found", nil)
|
||||
@@ -149,7 +154,7 @@ func (a *API) organizationDepartmentResource(w http.ResponseWriter, r *http.Requ
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
}
|
||||
items, next, err := a.store.DepartmentMembers(r.Context(), p.UserID, departmentID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.DepartmentMembers(r.Context(), p.UserID, departmentID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -159,13 +164,13 @@ func (a *API) organizationDepartmentResource(w http.ResponseWriter, r *http.Requ
|
||||
writeSuccess(w, r, payload)
|
||||
}
|
||||
|
||||
func (a *API) organizationMembers(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) organizationMembers(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
}
|
||||
query := firstNonEmpty(r.URL.Query().Get("q"), r.URL.Query().Get("keyword"))
|
||||
items, next, err := a.store.Members(r.Context(), p.UserID, r.URL.Query().Get("department_id"), strings.TrimSpace(query), r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.Members(r.Context(), p.UserID, r.URL.Query().Get("department_id"), strings.TrimSpace(query), r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -175,7 +180,7 @@ func (a *API) organizationMembers(w http.ResponseWriter, r *http.Request, p *aut
|
||||
writeSuccess(w, r, payload)
|
||||
}
|
||||
|
||||
func (a *API) organizationSearch(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) organizationSearch(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -185,12 +190,12 @@ func (a *API) organizationSearch(w http.ResponseWriter, r *http.Request, p *auth
|
||||
writeError(w, r, http.StatusBadRequest, 30000, reasonMalformedRequest, "malformed request", map[string]any{"field": "q"})
|
||||
return
|
||||
}
|
||||
departments, _, err := a.store.Departments(r.Context(), p.UserID, "root", "", limit(r, 10, 50))
|
||||
departments, _, err := st.Departments(r.Context(), p.UserID, "root", "", limit(r, 10, 50))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
}
|
||||
members, _, err := a.store.Members(r.Context(), p.UserID, "", query, "", limit(r, 20, 100))
|
||||
members, _, err := st.Members(r.Context(), p.UserID, "", query, "", limit(r, 20, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -207,7 +212,7 @@ func (a *API) organizationSearch(w http.ResponseWriter, r *http.Request, p *auth
|
||||
writeSuccess(w, r, map[string]any{"items": items, "next_cursor": "", "has_more": false})
|
||||
}
|
||||
|
||||
func (a *API) attendanceConfig(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) attendanceConfig(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -217,7 +222,7 @@ func (a *API) attendanceConfig(w http.ResponseWriter, r *http.Request, p *auth.P
|
||||
writeError(w, r, http.StatusBadRequest, 30000, reasonMalformedRequest, "malformed request", map[string]any{"field": "date"})
|
||||
return
|
||||
}
|
||||
cfg, err := a.store.AttendanceConfig(r.Context(), p.UserID, date)
|
||||
cfg, err := st.AttendanceConfig(r.Context(), p.UserID, date)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -225,12 +230,12 @@ func (a *API) attendanceConfig(w http.ResponseWriter, r *http.Request, p *auth.P
|
||||
writeSuccess(w, r, attendanceConfigPayload(cfg))
|
||||
}
|
||||
|
||||
func (a *API) attendanceRecords(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) attendanceRecords(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
}
|
||||
records, next, stats, err := a.store.AttendanceRecords(r.Context(), p.UserID, store.AttendanceListOptions{
|
||||
records, next, stats, err := st.AttendanceRecords(r.Context(), p.UserID, store.AttendanceListOptions{
|
||||
Scope: r.URL.Query().Get("scope"),
|
||||
From: r.URL.Query().Get("from"),
|
||||
To: r.URL.Query().Get("to"),
|
||||
@@ -250,7 +255,7 @@ func (a *API) attendanceRecords(w http.ResponseWriter, r *http.Request, p *auth.
|
||||
writeSuccess(w, r, payload)
|
||||
}
|
||||
|
||||
func (a *API) attendanceCheckins(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) attendanceCheckins(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodPost {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -316,7 +321,7 @@ func (a *API) attendanceCheckins(w http.ResponseWriter, r *http.Request, p *auth
|
||||
writeError(w, r, http.StatusBadRequest, 30000, reasonMalformedRequest, "malformed request", map[string]any{"field": "device"})
|
||||
return
|
||||
}
|
||||
record, checkin, err := a.store.CreateAttendanceCheckin(r.Context(), p.UserID, "attc_"+randomToken(12), store.AttendanceCheckinRequest{
|
||||
record, checkin, err := st.CreateAttendanceCheckin(r.Context(), p.UserID, "attc_"+randomToken(12), store.AttendanceCheckinRequest{
|
||||
Date: date, Action: action, RuleID: ruleID, ShiftID: shiftID,
|
||||
ClientTime: clientTime, Location: location, Wifi: wifi, Device: device, IdempotencyKey: idempotencyKey,
|
||||
})
|
||||
@@ -332,10 +337,10 @@ func (a *API) attendanceCheckins(w http.ResponseWriter, r *http.Request, p *auth
|
||||
writeSuccess(w, r, map[string]any{"record": attendanceRecordPayload(record), "checkin": attendanceCheckinPayload(*checkin)})
|
||||
}
|
||||
|
||||
func (a *API) attendanceAppeals(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) attendanceAppeals(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
items, next, err := a.store.AttendanceAppeals(r.Context(), p.UserID, r.URL.Query().Get("status"), r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.AttendanceAppeals(r.Context(), p.UserID, r.URL.Query().Get("status"), r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -367,7 +372,7 @@ func (a *API) attendanceAppeals(w http.ResponseWriter, r *http.Request, p *auth.
|
||||
targetTime = &parsed
|
||||
}
|
||||
attachments, _ := json.Marshal(body.AttachmentFileIDs)
|
||||
appeal, err := a.store.CreateAttendanceAppeal(r.Context(), p.UserID, store.AttendanceAppeal{
|
||||
appeal, err := st.CreateAttendanceAppeal(r.Context(), p.UserID, store.AttendanceAppeal{
|
||||
AppealID: "atta_" + randomToken(12), RecordID: strings.TrimSpace(body.RecordID), UserID: p.UserID, AppealType: strings.TrimSpace(body.AppealType),
|
||||
Reason: strings.TrimSpace(body.Reason), TargetAction: strings.TrimSpace(body.TargetAction), TargetTime: targetTime, AttachmentFileIDs: string(attachments),
|
||||
}, idempotencyKey)
|
||||
@@ -386,10 +391,10 @@ func (a *API) attendanceAppeals(w http.ResponseWriter, r *http.Request, p *auth.
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) meetings(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) meetings(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
items, next, err := a.store.Meetings(r.Context(), p.UserID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.Meetings(r.Context(), p.UserID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -423,7 +428,7 @@ func (a *API) meetings(w http.ResponseWriter, r *http.Request, p *auth.Principal
|
||||
return
|
||||
}
|
||||
reminders, _ := json.Marshal(body.ReminderMinutes)
|
||||
meeting, err := a.store.CreateMeeting(r.Context(), p.UserID, store.Meeting{
|
||||
meeting, err := st.CreateMeeting(r.Context(), p.UserID, store.Meeting{
|
||||
MeetingID: "mtg_" + randomToken(12), RecorderID: int64(body.RecorderUserID), Title: strings.TrimSpace(body.Title), StartAt: startAt, EndAt: endAt,
|
||||
Location: strings.TrimSpace(body.Location), ReminderMinutes: string(reminders), IdempotencyKey: idempotencyKey,
|
||||
}, parseUserIDList(body.AttendeeUserIDs))
|
||||
@@ -443,7 +448,7 @@ func (a *API) meetings(w http.ResponseWriter, r *http.Request, p *auth.Principal
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) meetingResource(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) meetingResource(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
meetingID, tail, ok := resourceTail(r.URL.Path, "/v1/workbench/meetings/")
|
||||
if !ok {
|
||||
writeError(w, r, http.StatusNotFound, 30004, reasonMalformedRequest, "meeting route not found", nil)
|
||||
@@ -451,7 +456,7 @@ func (a *API) meetingResource(w http.ResponseWriter, r *http.Request, p *auth.Pr
|
||||
}
|
||||
switch {
|
||||
case tail == "" && r.Method == http.MethodGet:
|
||||
meeting, err := a.store.Meeting(r.Context(), p.UserID, meetingID)
|
||||
meeting, err := st.Meeting(r.Context(), p.UserID, meetingID)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -466,7 +471,7 @@ func (a *API) meetingResource(w http.ResponseWriter, r *http.Request, p *auth.Pr
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
meeting, err := a.store.UpdateMeeting(r.Context(), p.UserID, meetingID, store.MeetingPatch{Title: body.Title, RecorderID: body.RecorderUserID.ptr(), Version: body.Version})
|
||||
meeting, err := st.UpdateMeeting(r.Context(), p.UserID, meetingID, store.MeetingPatch{Title: body.Title, RecorderID: body.RecorderUserID.ptr(), Version: body.Version})
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -478,7 +483,7 @@ func (a *API) meetingResource(w http.ResponseWriter, r *http.Request, p *auth.Pr
|
||||
}
|
||||
writeSuccess(w, r, meetingPayload(*meeting, p.UserID))
|
||||
case tail == "cancel" && r.Method == http.MethodPost:
|
||||
meeting, err := a.store.CancelMeeting(r.Context(), p.UserID, meetingID)
|
||||
meeting, err := st.CancelMeeting(r.Context(), p.UserID, meetingID)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -497,7 +502,7 @@ func (a *API) meetingResource(w http.ResponseWriter, r *http.Request, p *auth.Pr
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
meeting, err := a.store.RespondMeeting(r.Context(), p.UserID, meetingID, strings.TrimSpace(body.Response), body.Version)
|
||||
meeting, err := st.RespondMeeting(r.Context(), p.UserID, meetingID, strings.TrimSpace(body.Response), body.Version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -509,22 +514,22 @@ func (a *API) meetingResource(w http.ResponseWriter, r *http.Request, p *auth.Pr
|
||||
}
|
||||
writeSuccess(w, r, meetingPayload(*meeting, p.UserID))
|
||||
case tail == "notes" && r.Method == http.MethodGet:
|
||||
a.meetingNotesDetail(w, r, p, meetingID)
|
||||
a.meetingNotesDetail(w, r, p, st, meetingID)
|
||||
case tail == "notes/files" && r.Method == http.MethodPost:
|
||||
a.meetingNoteFiles(w, r, p, meetingID)
|
||||
a.meetingNoteFiles(w, r, p, st, meetingID)
|
||||
case strings.HasPrefix(tail, "notes/files/"):
|
||||
a.meetingNoteFileResource(w, r, p, meetingID, strings.TrimPrefix(tail, "notes/files/"))
|
||||
a.meetingNoteFileResource(w, r, p, st, meetingID, strings.TrimPrefix(tail, "notes/files/"))
|
||||
default:
|
||||
methodNotAllowed(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) meetingNotes(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) meetingNotes(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
}
|
||||
items, next, err := a.store.MeetingNotes(r.Context(), p.UserID, r.URL.Query().Get("query"), r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.MeetingNotes(r.Context(), p.UserID, r.URL.Query().Get("query"), r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -532,13 +537,13 @@ func (a *API) meetingNotes(w http.ResponseWriter, r *http.Request, p *auth.Princ
|
||||
writeSuccess(w, r, pagePayload(meetingNoteListPayloads(items, p.UserID), next))
|
||||
}
|
||||
|
||||
func (a *API) meetingNotesDetail(w http.ResponseWriter, r *http.Request, p *auth.Principal, meetingID string) {
|
||||
meeting, err := a.store.Meeting(r.Context(), p.UserID, meetingID)
|
||||
func (a *API) meetingNotesDetail(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store, meetingID string) {
|
||||
meeting, err := st.Meeting(r.Context(), p.UserID, meetingID)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
}
|
||||
files, err := a.store.MeetingNoteFiles(r.Context(), p.UserID, meetingID)
|
||||
files, err := st.MeetingNoteFiles(r.Context(), p.UserID, meetingID)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -546,7 +551,7 @@ func (a *API) meetingNotesDetail(w http.ResponseWriter, r *http.Request, p *auth
|
||||
writeSuccess(w, r, meetingNotesDetailPayload(*meeting, files, p.UserID))
|
||||
}
|
||||
|
||||
func (a *API) meetingNoteFiles(w http.ResponseWriter, r *http.Request, p *auth.Principal, meetingID string) {
|
||||
func (a *API) meetingNoteFiles(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store, meetingID string) {
|
||||
idempotencyKey, ok := requireIdempotencyKey(w, r)
|
||||
if !ok {
|
||||
return
|
||||
@@ -557,7 +562,7 @@ func (a *API) meetingNoteFiles(w http.ResponseWriter, r *http.Request, p *auth.P
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
file, err := a.store.CreateMeetingNoteFile(r.Context(), p.UserID, meetingID, "mnote_"+randomToken(12), strings.TrimSpace(body.FileID), idempotencyKey)
|
||||
file, err := st.CreateMeetingNoteFile(r.Context(), p.UserID, meetingID, "mnote_"+randomToken(12), strings.TrimSpace(body.FileID), idempotencyKey)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -570,7 +575,7 @@ func (a *API) meetingNoteFiles(w http.ResponseWriter, r *http.Request, p *auth.P
|
||||
writeSuccess(w, r, meetingNoteFilePayload(*file, p.UserID))
|
||||
}
|
||||
|
||||
func (a *API) meetingNoteFileResource(w http.ResponseWriter, r *http.Request, p *auth.Principal, meetingID, noteFileID string) {
|
||||
func (a *API) meetingNoteFileResource(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store, meetingID, noteFileID string) {
|
||||
idempotencyKey, ok := requireIdempotencyKey(w, r)
|
||||
if !ok {
|
||||
return
|
||||
@@ -584,7 +589,7 @@ func (a *API) meetingNoteFileResource(w http.ResponseWriter, r *http.Request, p
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
file, err := a.store.ReplaceMeetingNoteFile(r.Context(), p.UserID, meetingID, noteFileID, strings.TrimSpace(body.FileID), idempotencyKey, body.Version)
|
||||
file, err := st.ReplaceMeetingNoteFile(r.Context(), p.UserID, meetingID, noteFileID, strings.TrimSpace(body.FileID), idempotencyKey, body.Version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -601,7 +606,7 @@ func (a *API) meetingNoteFileResource(w http.ResponseWriter, r *http.Request, p
|
||||
writeError(w, r, http.StatusBadRequest, 30000, reasonMalformedRequest, "malformed request", map[string]any{"field": "version"})
|
||||
return
|
||||
}
|
||||
file, err := a.store.DeleteMeetingNoteFile(r.Context(), p.UserID, meetingID, noteFileID, idempotencyKey, version)
|
||||
file, err := st.DeleteMeetingNoteFile(r.Context(), p.UserID, meetingID, noteFileID, idempotencyKey, version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -617,10 +622,10 @@ func (a *API) meetingNoteFileResource(w http.ResponseWriter, r *http.Request, p
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) dailyReports(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) dailyReports(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
items, next, err := a.store.DailyReports(r.Context(), p.UserID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.DailyReports(r.Context(), p.UserID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -638,7 +643,7 @@ func (a *API) dailyReports(w http.ResponseWriter, r *http.Request, p *auth.Princ
|
||||
writeError(w, r, http.StatusBadRequest, 30000, reasonMalformedRequest, "malformed request", map[string]any{"field": "report_date"})
|
||||
return
|
||||
}
|
||||
report, err := a.store.CreateDailyDraft(r.Context(), p.UserID, "dr_"+randomToken(12), date)
|
||||
report, err := st.CreateDailyDraft(r.Context(), p.UserID, "dr_"+randomToken(12), date)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -654,7 +659,7 @@ func (a *API) dailyReports(w http.ResponseWriter, r *http.Request, p *auth.Princ
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) dailyReportResource(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) dailyReportResource(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
reportID, tail, ok := resourceTail(r.URL.Path, "/v1/workbench/reports/daily/")
|
||||
if !ok {
|
||||
writeError(w, r, http.StatusNotFound, 30004, reasonMalformedRequest, "daily report route not found", nil)
|
||||
@@ -662,7 +667,7 @@ func (a *API) dailyReportResource(w http.ResponseWriter, r *http.Request, p *aut
|
||||
}
|
||||
switch {
|
||||
case tail == "" && r.Method == http.MethodGet:
|
||||
report, err := a.store.DailyReport(r.Context(), p.UserID, reportID)
|
||||
report, err := st.DailyReport(r.Context(), p.UserID, reportID)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -682,7 +687,7 @@ func (a *API) dailyReportResource(w http.ResponseWriter, r *http.Request, p *aut
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
report, err := a.store.SaveDailyDraft(r.Context(), p.UserID, reportID, body.Content, body.Attachments, body.Version)
|
||||
report, err := st.SaveDailyDraft(r.Context(), p.UserID, reportID, body.Content, body.Attachments, body.Version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -700,7 +705,7 @@ func (a *API) dailyReportResource(w http.ResponseWriter, r *http.Request, p *aut
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
report, err := a.store.SubmitDaily(r.Context(), p.UserID, reportID, body.Version)
|
||||
report, err := st.SubmitDaily(r.Context(), p.UserID, reportID, body.Version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -711,7 +716,7 @@ func (a *API) dailyReportResource(w http.ResponseWriter, r *http.Request, p *aut
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) dailyReportStatistics(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) dailyReportStatistics(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -719,7 +724,7 @@ func (a *API) dailyReportStatistics(w http.ResponseWriter, r *http.Request, p *a
|
||||
writeSuccess(w, r, map[string]any{"expected_count": 0, "submitted_count": 0, "missing_count": 0, "scope": map[string]any{"department_id": r.URL.Query().Get("department_id")}})
|
||||
}
|
||||
|
||||
func (a *API) dailyReportReminders(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) dailyReportReminders(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodPost {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -743,10 +748,10 @@ func (a *API) dailyReportReminders(w http.ResponseWriter, r *http.Request, p *au
|
||||
writeSuccess(w, r, map[string]any{"status": "queued"})
|
||||
}
|
||||
|
||||
func (a *API) monthlyReports(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) monthlyReports(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
items, next, err := a.store.MonthlyReports(r.Context(), p.UserID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
items, next, err := st.MonthlyReports(r.Context(), p.UserID, r.URL.Query().Get("cursor"), limit(r, 50, 100))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -759,7 +764,7 @@ func (a *API) monthlyReports(w http.ResponseWriter, r *http.Request, p *auth.Pri
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
report, err := a.store.CreateMonthlyDraft(r.Context(), p.UserID, "mr_"+randomToken(12), strings.TrimSpace(body.Month))
|
||||
report, err := st.CreateMonthlyDraft(r.Context(), p.UserID, "mr_"+randomToken(12), strings.TrimSpace(body.Month))
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -775,7 +780,7 @@ func (a *API) monthlyReports(w http.ResponseWriter, r *http.Request, p *auth.Pri
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) monthlyReportResource(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) monthlyReportResource(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
reportID, tail, ok := resourceTail(r.URL.Path, "/v1/workbench/reports/monthly/")
|
||||
if !ok {
|
||||
writeError(w, r, http.StatusNotFound, 30004, reasonMalformedRequest, "monthly report route not found", nil)
|
||||
@@ -783,7 +788,7 @@ func (a *API) monthlyReportResource(w http.ResponseWriter, r *http.Request, p *a
|
||||
}
|
||||
switch {
|
||||
case tail == "" && r.Method == http.MethodGet:
|
||||
report, err := a.store.MonthlyReport(r.Context(), p.UserID, reportID)
|
||||
report, err := st.MonthlyReport(r.Context(), p.UserID, reportID)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -804,7 +809,7 @@ func (a *API) monthlyReportResource(w http.ResponseWriter, r *http.Request, p *a
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
report, err := a.store.SaveMonthlyDraft(r.Context(), p.UserID, reportID, body.WorkSummary, body.NextPlan, body.Attachments, body.Version)
|
||||
report, err := st.SaveMonthlyDraft(r.Context(), p.UserID, reportID, body.WorkSummary, body.NextPlan, body.Attachments, body.Version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -822,7 +827,7 @@ func (a *API) monthlyReportResource(w http.ResponseWriter, r *http.Request, p *a
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
report, err := a.store.SubmitMonthly(r.Context(), p.UserID, reportID, body.Version)
|
||||
report, err := st.SubmitMonthly(r.Context(), p.UserID, reportID, body.Version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -840,7 +845,7 @@ func (a *API) monthlyReportResource(w http.ResponseWriter, r *http.Request, p *a
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
report, err := a.store.ReopenMonthly(r.Context(), p.UserID, reportID, body.Version)
|
||||
report, err := st.ReopenMonthly(r.Context(), p.UserID, reportID, body.Version)
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -851,7 +856,7 @@ func (a *API) monthlyReportResource(w http.ResponseWriter, r *http.Request, p *a
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) monthlyReportStatistics(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) monthlyReportStatistics(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -859,12 +864,12 @@ func (a *API) monthlyReportStatistics(w http.ResponseWriter, r *http.Request, p
|
||||
writeSuccess(w, r, map[string]any{"expected_count": 0, "submitted_count": 0, "missing_count": 0, "scope": map[string]any{"department_id": r.URL.Query().Get("department_id")}})
|
||||
}
|
||||
|
||||
func (a *API) mailboxConfig(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) mailboxConfig(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
}
|
||||
cfg, err := a.store.MailboxConfig(r.Context())
|
||||
cfg, err := st.MailboxConfig(r.Context())
|
||||
if err != nil {
|
||||
writeStoreError(w, r, err)
|
||||
return
|
||||
@@ -872,7 +877,7 @@ func (a *API) mailboxConfig(w http.ResponseWriter, r *http.Request, p *auth.Prin
|
||||
writeSuccess(w, r, mailboxConfigPayload(*cfg))
|
||||
}
|
||||
|
||||
func (a *API) mailboxSubmissions(w http.ResponseWriter, r *http.Request, p *auth.Principal) {
|
||||
func (a *API) mailboxSubmissions(w http.ResponseWriter, r *http.Request, p *auth.Principal, st *store.Store) {
|
||||
if r.Method != http.MethodPost {
|
||||
methodNotAllowed(w, r)
|
||||
return
|
||||
@@ -897,7 +902,7 @@ func (a *API) mailboxSubmissions(w http.ResponseWriter, r *http.Request, p *auth
|
||||
return
|
||||
}
|
||||
attachments, _ := json.Marshal(body.AttachmentFileIDs)
|
||||
submission, err := a.store.CreateMailboxSubmission(r.Context(), p.UserID, store.MailboxSubmission{
|
||||
submission, err := st.CreateMailboxSubmission(r.Context(), p.UserID, store.MailboxSubmission{
|
||||
SubmissionID: "mb_" + randomToken(12), Subject: subject, Content: content,
|
||||
Anonymous: body.Anonymous, AttachmentFileIDs: string(attachments), NoticeVersion: strings.TrimSpace(body.NoticeVersion),
|
||||
}, idempotencyKey)
|
||||
@@ -954,10 +959,10 @@ func meetingTargetUsers(meeting store.Meeting) []int64 {
|
||||
return targets
|
||||
}
|
||||
|
||||
func (a *API) populateUnread(r *http.Request, p *auth.Principal, modules []map[string]any) error {
|
||||
func (a *API) populateUnread(st *store.Store, r *http.Request, p *auth.Principal, modules []map[string]any) error {
|
||||
for _, module := range modules {
|
||||
if module["code"] == "meetings" {
|
||||
count, err := a.store.MeetingUnreadCount(r.Context(), p.UserID)
|
||||
count, err := st.MeetingUnreadCount(r.Context(), p.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user