Documentation
¶
Index ¶
- Constants
- Variables
- func AdminAuditLogFacets(gdb *gorm.DB) (actions, resources []string, err error)
- func AdminForgejoRequestFacets(gdb *gorm.DB) (sources, methods []string, err error)
- func AdminGetAuditLog(gdb *gorm.DB, id string) (db.AuditLog, error)
- func AdminGetCourse(gdb *gorm.DB, id string) (db.Course, error)
- func AdminGetForgejoRequest(gdb *gorm.DB, id string) (db.ForgejoRequest, error)
- func AdminListStudents(gdb *gorm.DB, courseID string) ([]db.Student, error)
- func AdminListTutors(gdb *gorm.DB, courseID string) ([]db.Tutor, error)
- func AssignStudentsTutor(gdb *gorm.DB, courseID uint, userIDs []string, tutorID *uint) (int, error)
- func AutoDistributeStudents(gdb *gorm.DB, courseID uint) (assigned int, tutors int, err error)
- func CanManageCourse(gdb *gorm.DB, c *echo.Context, courseID any) bool
- func CourseAccessScope(c *echo.Context) func(*gorm.DB) *gorm.DB
- func CourseGrantCounts(gdb *gorm.DB, courseIDs []uint) map[uint]int64
- func CourseManageScope(c *echo.Context) func(*gorm.DB) *gorm.DB
- func CreateAPIKey(gdb *gorm.DB, userID, name string) (db.ApiKey, string, error)
- func DeleteAPIKey(gdb *gorm.DB, userID string, keyID uint) error
- func EchoContext(ctx context.Context) *echo.Context
- func FetchCLIVersions() []string
- func HasCourseAccess(gdb *gorm.DB, courseID uint, userID string) bool
- func IsTutorAssigned(gdb *gorm.DB, courseID, userID string) (bool, error)
- func ListAPIKeys(gdb *gorm.DB, userID string) ([]db.ApiKey, error)
- func ListExercisesForCourse(gdb *gorm.DB, courseID uint) ([]db.Exercise, error)
- func LoadCLIMinVersion(gdb *gorm.DB) string
- func Register[I, O any](h *Huma, op huma.Operation, handler func(context.Context, *I) (*O, error), ...)
- func ResolveUserID(gdb *gorm.DB, identifier string) (string, error)
- func RunTask(c *echo.Context, gdb *gorm.DB, name string) error
- func SetStudentTutor(gdb *gorm.DB, courseID uint, userID string, tutorID *uint) (*db.Student, error)
- func SettingAccessScope(c *echo.Context) func(*gorm.DB) *gorm.DB
- func UserReadScope(c *echo.Context) func(*gorm.DB) *gorm.DB
- type AssignTutorBody
- type AuditLogFacets
- type AuditLogFacetsInput
- type AuditLogFacetsOutput
- type AuditLogGetInput
- type AuditLogGetOutput
- type AuditLogListInput
- type AuditLogListOutput
- type AuditLogListParams
- type AuditLogListQuery
- type AuditLogListResult
- type AutoDistributeResult
- type BulkAssignTutorBody
- type BulkAssignTutorResult
- type CLIVersionInput
- type CLIVersionOutput
- type ChartsCSVOutput
- type ChartsInput
- type ChartsOutput
- type ChartsResponse
- type CourseAccessForCourseGrantInput
- type CourseAccessForCourseGrantOutput
- type CourseAccessForCourseListInput
- type CourseAccessForCourseListOutput
- type CourseAccessForCourseRevokeInput
- type CourseAccessForCourseRevokeOutput
- type CourseAccessOut
- type CourseBody
- type CourseBrief
- type CourseListQuery
- type CourseStudentGradesInput
- type CourseStudentGradesOutput
- type CourseStudentListParams
- type CourseStudentListQuery
- type CourseStudentListResult
- type CourseTutorListQuery
- type CoursesCreateInput
- type CoursesCreateOutput
- type CoursesDeleteInput
- type CoursesDeleteOutput
- type CoursesGetInput
- type CoursesGetOutput
- type CoursesHardDeleteInput
- type CoursesHardDeleteOutput
- type CoursesJoinInput
- type CoursesJoinOutput
- type CoursesListInput
- type CoursesListOutput
- type CoursesListParams
- type CoursesListResult
- type CoursesRestoreInput
- type CoursesRestoreOutput
- type CoursesStudentsAssignTutorBulkInput
- type CoursesStudentsAssignTutorBulkOutput
- type CoursesStudentsAutoDistributeInput
- type CoursesStudentsAutoDistributeOutput
- type CoursesStudentsListInput
- type CoursesStudentsListOutput
- type CoursesStudentsMineInput
- type CoursesStudentsMineOutput
- type CoursesStudentsSetTutorInput
- type CoursesStudentsSetTutorOutput
- type CoursesStudentsUnassignInput
- type CoursesStudentsUnassignOutput
- type CoursesTutorForUserInput
- type CoursesTutorForUserOutput
- type CoursesTutorMineInput
- type CoursesTutorMineOutput
- type CoursesTutorsAssignInput
- type CoursesTutorsAssignOutput
- type CoursesTutorsListInput
- type CoursesTutorsListOutput
- type CoursesTutorsUnassignInput
- type CoursesTutorsUnassignOutput
- type CoursesUpdateInput
- type CoursesUpdateOutput
- type CreateUserBody
- type CronJobResponse
- type CronListInput
- type CronListOutput
- type CronRunInput
- type CronRunOutput
- type ExerciseAllRow
- type ExerciseOut
- type ExercisesAllListParams
- type ExercisesAllListResult
- type ExercisesListInput
- type ExercisesListOutput
- type ForgejoRequestFacets
- type ForgejoRequestListParams
- type ForgejoRequestListQuery
- type ForgejoRequestListResult
- type ForgejoRequestsFacetsInput
- type ForgejoRequestsFacetsOutput
- type ForgejoRequestsListInput
- type ForgejoRequestsListOutput
- type ForgejoTimePoint
- type GradeBucket
- type GradeItem
- type GradedUngraded
- type Handler
- func (h *Handler) AttendanceHandler(c *echo.Context) error
- func (h *Handler) AuditLogFacets(ctx context.Context, input *AuditLogFacetsInput) (*AuditLogFacetsOutput, error)
- func (h *Handler) AuditLogGet(ctx context.Context, input *AuditLogGetInput) (*AuditLogGetOutput, error)
- func (h *Handler) AuditLogList(ctx context.Context, input *AuditLogListInput) (*AuditLogListOutput, error)
- func (h *Handler) CLIVersion(ctx context.Context, input *CLIVersionInput) (*CLIVersionOutput, error)
- func (h *Handler) Charts(ctx context.Context, input *ChartsInput) (*ChartsOutput, error)
- func (h *Handler) ChartsCSV(ctx context.Context, input *ChartsInput) (*ChartsCSVOutput, error)
- func (h *Handler) CourseAccessForCourseGrant(ctx context.Context, input *CourseAccessForCourseGrantInput) (*CourseAccessForCourseGrantOutput, error)
- func (h *Handler) CourseAccessForCourseList(ctx context.Context, input *CourseAccessForCourseListInput) (*CourseAccessForCourseListOutput, error)
- func (h *Handler) CourseAccessForCourseRevoke(ctx context.Context, input *CourseAccessForCourseRevokeInput) (*CourseAccessForCourseRevokeOutput, error)
- func (h *Handler) CourseStudentGrades(ctx context.Context, input *CourseStudentGradesInput) (*CourseStudentGradesOutput, error)
- func (h *Handler) CoursesCreate(ctx context.Context, input *CoursesCreateInput) (*CoursesCreateOutput, error)
- func (h *Handler) CoursesDelete(ctx context.Context, input *CoursesDeleteInput) (*CoursesDeleteOutput, error)
- func (h *Handler) CoursesGet(ctx context.Context, input *CoursesGetInput) (*CoursesGetOutput, error)
- func (h *Handler) CoursesHardDelete(ctx context.Context, input *CoursesHardDeleteInput) (*CoursesHardDeleteOutput, error)
- func (h *Handler) CoursesJoin(ctx context.Context, input *CoursesJoinInput) (*CoursesJoinOutput, error)
- func (h *Handler) CoursesList(ctx context.Context, input *CoursesListInput) (*CoursesListOutput, error)
- func (h *Handler) CoursesRestore(ctx context.Context, input *CoursesRestoreInput) (*CoursesRestoreOutput, error)
- func (h *Handler) CoursesStudentsAssignTutorBulk(ctx context.Context, input *CoursesStudentsAssignTutorBulkInput) (*CoursesStudentsAssignTutorBulkOutput, error)
- func (h *Handler) CoursesStudentsAutoDistribute(ctx context.Context, input *CoursesStudentsAutoDistributeInput) (*CoursesStudentsAutoDistributeOutput, error)
- func (h *Handler) CoursesStudentsList(ctx context.Context, input *CoursesStudentsListInput) (*CoursesStudentsListOutput, error)
- func (h *Handler) CoursesStudentsMine(ctx context.Context, input *CoursesStudentsMineInput) (*CoursesStudentsMineOutput, error)
- func (h *Handler) CoursesStudentsSetTutor(ctx context.Context, input *CoursesStudentsSetTutorInput) (*CoursesStudentsSetTutorOutput, error)
- func (h *Handler) CoursesStudentsUnassign(ctx context.Context, input *CoursesStudentsUnassignInput) (*CoursesStudentsUnassignOutput, error)
- func (h *Handler) CoursesTutorForUser(ctx context.Context, input *CoursesTutorForUserInput) (*CoursesTutorForUserOutput, error)
- func (h *Handler) CoursesTutorMine(ctx context.Context, input *CoursesTutorMineInput) (*CoursesTutorMineOutput, error)
- func (h *Handler) CoursesTutorsAssign(ctx context.Context, input *CoursesTutorsAssignInput) (*CoursesTutorsAssignOutput, error)
- func (h *Handler) CoursesTutorsList(ctx context.Context, input *CoursesTutorsListInput) (*CoursesTutorsListOutput, error)
- func (h *Handler) CoursesTutorsUnassign(ctx context.Context, input *CoursesTutorsUnassignInput) (*CoursesTutorsUnassignOutput, error)
- func (h *Handler) CoursesUpdate(ctx context.Context, input *CoursesUpdateInput) (*CoursesUpdateOutput, error)
- func (h *Handler) CronList(ctx context.Context, input *CronListInput) (*CronListOutput, error)
- func (h *Handler) CronRun(ctx context.Context, input *CronRunInput) (*CronRunOutput, error)
- func (h *Handler) ExercisesList(ctx context.Context, input *ExercisesListInput) (*ExercisesListOutput, error)
- func (h *Handler) ForgejoRequestsFacets(ctx context.Context, input *ForgejoRequestsFacetsInput) (*ForgejoRequestsFacetsOutput, error)
- func (h *Handler) ForgejoRequestsList(ctx context.Context, input *ForgejoRequestsListInput) (*ForgejoRequestsListOutput, error)
- func (h *Handler) GitPostRecieveHandler(c *echo.Context) error
- func (h *Handler) GitPreRecieveHandler(c *echo.Context) error
- func (h *Handler) HealthCheckRun(ctx context.Context, input *HealthCheckRunInput) (*HealthCheckRunOutput, error)
- func (h *Handler) HealthStatus(ctx context.Context, input *HealthStatusInput) (*HealthStatusOutput, error)
- func (h *Handler) SettingsCreate(ctx context.Context, input *SettingsCreateInput) (*SettingsCreateOutput, error)
- func (h *Handler) SettingsDelete(ctx context.Context, input *SettingsDeleteInput) (*SettingsDeleteOutput, error)
- func (h *Handler) SettingsGet(ctx context.Context, input *SettingsGetInput) (*SettingsGetOutput, error)
- func (h *Handler) SettingsList(ctx context.Context, input *SettingsListInput) (*SettingsListOutput, error)
- func (h *Handler) SettingsUpdate(ctx context.Context, input *SettingsUpdateInput) (*SettingsUpdateOutput, error)
- func (h *Handler) Stats(ctx context.Context, input *StatsInput) (*StatsOutput, error)
- func (h *Handler) TaskGet(ctx context.Context, input *TaskGetInput) (*TaskGetOutput, error)
- func (h *Handler) TaskList(ctx context.Context, input *TaskListInput) (*TaskListOutput, error)
- func (h *Handler) TaskRun(ctx context.Context, input *TaskRunInput) (*TaskRunOutput, error)
- func (h *Handler) UsersAdminList(ctx context.Context, input *UsersAdminListInput) (*UsersAdminListOutput, error)
- func (h *Handler) UsersCreate(ctx context.Context, input *UsersCreateInput) (*UsersCreateOutput, error)
- func (h *Handler) UsersDelete(ctx context.Context, input *UsersDeleteInput) (*UsersDeleteOutput, error)
- func (h *Handler) UsersDeleteSessions(ctx context.Context, input *UsersDeleteSessionsInput) (*UsersDeleteSessionsOutput, error)
- func (h *Handler) UsersGet(ctx context.Context, input *UsersGetInput) (*UsersGetOutput, error)
- func (h *Handler) UsersList(ctx context.Context, input *UsersListInput) (*UsersListOutput, error)
- func (h *Handler) UsersMe(ctx context.Context, input *UsersMeInput) (*UsersMeOutput, error)
- func (h *Handler) UsersMeCourses(ctx context.Context, input *UsersMeCoursesInput) (*UsersMeCoursesOutput, error)
- func (h *Handler) UsersMeGrades(ctx context.Context, input *UsersMeGradesInput) (*UsersMeGradesOutput, error)
- func (h *Handler) UsersMeRecentGrades(ctx context.Context, input *UsersMeRecentGradesInput) (*UsersMeRecentGradesOutput, error)
- func (h *Handler) UsersUpdate(ctx context.Context, input *UsersUpdateInput) (*UsersUpdateOutput, error)
- type HealthBeszelContainer
- type HealthBeszelInfo
- type HealthCheckItem
- type HealthCheckRunInput
- type HealthCheckRunOutput
- type HealthStatusInput
- type HealthStatusOutput
- type HealthSummary
- type HealthSystemInfo
- type Huma
- type LabelCount
- type MyCourseItem
- type RecentGradeItem
- type SemesterCount
- type SessionBrief
- type SetStudentTutorBody
- type SettingBody
- type SettingListQuery
- type SettingsCreateInput
- type SettingsCreateOutput
- type SettingsDeleteInput
- type SettingsDeleteOutput
- type SettingsGetInput
- type SettingsGetOutput
- type SettingsListInput
- type SettingsListOutput
- type SettingsUpdateInput
- type SettingsUpdateOutput
- type StaffStatsResponse
- type StatsInput
- type StatsOutput
- type StatsResponse
- type StudentOut
- type TaskGetInput
- type TaskGetOutput
- type TaskListInput
- type TaskListOutput
- type TaskRunInput
- type TaskRunOutput
- type TimeSeries
- type TimeSeriesPoint
- type TutorAssignmentBrief
- type TutorAssignmentOut
- type TutorBrief
- type TutorOut
- type TutorUserSearchResult
- type UpdateUserBody
- type UserAdminItem
- type UserBrief
- type UserListQuery
- type UsersAdminListInput
- type UsersAdminListOutput
- type UsersAdminListParams
- type UsersAdminListQuery
- type UsersAdminListResult
- type UsersCreateInput
- type UsersCreateOutput
- type UsersDeleteInput
- type UsersDeleteOutput
- type UsersDeleteSessionsInput
- type UsersDeleteSessionsOutput
- type UsersGetInput
- type UsersGetOutput
- type UsersListInput
- type UsersListOutput
- type UsersMeCoursesInput
- type UsersMeCoursesOutput
- type UsersMeGradesInput
- type UsersMeGradesOutput
- type UsersMeInput
- type UsersMeOutput
- type UsersMeRecentGradesInput
- type UsersMeRecentGradesOutput
- type UsersUpdateInput
- type UsersUpdateOutput
Constants ¶
const CLIMinVersionSettingKey = "cli_min_version"
CLIMinVersionSettingKey is the settings key for the minimum CLI version.
const OrchestrationBotUsername = "orchestration-bot"
OrchestrationBotUsername is the forgejo login of the "orchestration-bot" account. The bot creates every course org and repo on the owner's behalf.
Variables ¶
var ( ErrTutorNotFound = errors.New("tutor not found in this course") ErrTutorWrongCourse = errors.New("tutor does not belong to this course") )
ErrTutorNotFound and ErrTutorWrongCourse are returned by the tutor assignment helpers when the tutor id does not exist or belongs to a different course. API handlers map both to 400, the UI to 422.
var ErrNoCourseTutors = errors.New("course has no tutors")
ErrNoCourseTutors is returned by AutoDistributeStudents when the course has no tutors to distribute students to.
Functions ¶
func AdminAuditLogFacets ¶
AdminAuditLogFacets returns distinct action and resource values present in the audit log, used to populate filter dropdowns.
func AdminForgejoRequestFacets ¶
AdminForgejoRequestFacets returns distinct source and method values present in the Forgejo request log.
func AdminGetAuditLog ¶
AdminGetAuditLog fetches a single audit log entry by ID.
func AdminGetCourse ¶
AdminGetCourse fetches a single course by ID (including archived courses via Unscoped, since the admin UI needs to show archived courses too).
func AdminGetForgejoRequest ¶
AdminGetForgejoRequest fetches a single Forgejo request by ID.
func AdminListStudents ¶
AdminListStudents fetches students for a course with users preloaded.
func AdminListTutors ¶
AdminListTutors fetches tutors for a course with users preloaded.
func AssignStudentsTutor ¶
AssignStudentsTutor assigns or clears the tutor for multiple students of a course in one transaction. User ids without a matching student row in the course are skipped. The tutor must belong to the course (ErrTutorNotFound/ErrTutorWrongCourse). Returns the number of updated student rows.
func AutoDistributeStudents ¶
AutoDistributeStudents distributes the unassigned students of a course evenly across the course's tutors. Existing assignments are kept; counts start from the currently assigned students. Each unassigned student (in id order) goes to the tutor with the lowest current count, ties broken by the lower tutor id. Everything runs in one transaction. Returns the number of updated student rows and the number of tutors considered.
func CanManageCourse ¶
CanManageCourse reports whether the caller may manage the course identified by courseID. Admins always may; staff may for courses they own and for courses an admin granted them via course_accesses. Used by handlers (e.g. HTML fragments) that operate on a course by id and need a boolean guard rather than a query scope.
func CourseAccessScope ¶
CourseAccessScope returns a GORM scope that filters courses based on the caller's role for *read* access. Admins see everything. Staff see joinable courses plus the courses they own. Everyone else (students and unauthenticated callers) sees only courses with allow_join = true.
func CourseGrantCounts ¶
CourseGrantCounts returns the number of course_accesses grants per course id for the given course ids. Missing ids map to no entry (zero count).
func CourseManageScope ¶
CourseManageScope returns a GORM scope that restricts course queries to the courses the caller may *manage* (edit, delete, assign tutors/students, grade). Admins may manage every course; staff may manage the courses they own plus the ones an admin granted them via course_accesses; everyone else matches nothing. Applied to mutating course endpoints so a staff member acting on someone else's course gets a 404 rather than silently touching it.
func CreateAPIKey ¶
CreateAPIKey generates a new API key for the given user, stores the hash, and returns the model + the plaintext key (only visible at creation time). Keys expire after 1 year.
func DeleteAPIKey ¶
DeleteAPIKey deletes an API key, scoped to the given user.
func EchoContext ¶
EchoContext returns the echo context for the current huma request. Register injects it before the handler runs so handlers can build echo-context dependent GORM scopes and record audit entries. Returns nil when the handler is invoked outside of a registered operation (tests).
func FetchCLIVersions ¶
func FetchCLIVersions() []string
FetchCLIVersions fetches the available hopper-cli release versions from PyPI and returns them sorted descending (newest first) with a "v" prefix. Returns nil if PyPI is unreachable or the response cannot be parsed.
func HasCourseAccess ¶
HasCourseAccess reports whether userID holds an admin-granted course access (a course_accesses row) for courseID. It says nothing about ownership, admin rights, or tutor slots; combine it with the other checks where those matter. Used by the per-record guards that bypass CanManageCourse (e.g. grade and tutor-assignment lookups).
func IsTutorAssigned ¶
IsTutorAssigned returns true if userID is a tutor of courseID.
func ListAPIKeys ¶
ListAPIKeys returns all API keys for the given user, newest first.
func ListExercisesForCourse ¶
ListExercisesForCourse returns every exercise defined in a course, ordered by start date. Exported so tests and in-process callers can reuse the query without going through HTTP.
func LoadCLIMinVersion ¶
LoadCLIMinVersion reads the cli_min_version setting from the database, returning the stored value (with a "v" prefix if missing) or an empty string when the setting does not exist.
func Register ¶
func Register[I, O any](h *Huma, op huma.Operation, handler func(context.Context, *I) (*O, error), mw ...echo.MiddlewareFunc)
Register registers a huma operation with echo middleware applied as operation-level huma middleware, keeping route registration a one-liner:
api.Register(h, op, handler, a.Auth.RequireStaff())
The echo context of the current request is injected into the handler context and can be retrieved with EchoContext.
func ResolveUserID ¶
ResolveUserID resolves an arbitrary identifier to the canonical user PK (OIDC sub). Tries id, then preferred_username (case-insensitive), then student_id. Returns gorm.ErrRecordNotFound if nothing matches.
func RunTask ¶
RunTask triggers the named task. Returns an error if the task isn't found or fails. Records an audit entry on success. Exported for use by the HTML fragment handlers.
func SetStudentTutor ¶
func SetStudentTutor(gdb *gorm.DB, courseID uint, userID string, tutorID *uint) (*db.Student, error)
SetStudentTutor sets or clears the tutor of a single student in a course. userID is the enrolled student's user id; a nil tutorID clears the assignment. The student row must exist in the course (gorm.ErrRecordNotFound) and the tutor must belong to the course (ErrTutorNotFound/ErrTutorWrongCourse). Returns the updated student row with the user preloaded.
func SettingAccessScope ¶
SettingAccessScope returns a GORM scope that filters settings by the caller's access level. Unauthenticated callers see only "public" entries. Regular authenticated users see "public" + "authed". Admins see everything.
func UserReadScope ¶
UserReadScope returns a GORM scope that restricts a users query to the rows the caller is allowed to *read*. Admins see everyone. Any other authenticated caller sees:
- themselves;
- (as course owner or granted staff) every student and tutor enrolled in a course they own or hold a course_accesses grant for;
- (as a course tutor) every student assigned to a tutor slot they hold.
The ownership branches are harmless for callers who own no courses and hold no tutor slots - their subqueries simply match nothing - so no role branch is needed beyond the admin short-circuit. Applied to the read endpoints so a staff member or tutor gets a scoped view instead of the whole user table, and a 404 (not a 403) for anyone outside their reach.
The whole predicate is a single grouped OR so it AND-combines cleanly with any search/filter scopes the list handler layers on top.
Types ¶
type AssignTutorBody ¶
type AssignTutorBody struct {
UserID string `json:"user_id"`
Description string `json:"description" required:"false"`
}
AssignTutorBody is the body for POST /courses/{id}/tutors.
type AuditLogFacets ¶
type AuditLogFacets struct {
Actions []string `json:"actions"`
Resources []string `json:"resources"`
}
AuditLogFacets is the response body of GET /audit-log/facets. Each field carries the distinct values currently present in the audit_logs table for the matching column, sorted ascending. Clients use it to populate filter dropdowns so we don't have to hardcode the list of actions in the UI every time a new audit call-site is added on the backend.
type AuditLogFacetsInput ¶
type AuditLogFacetsInput struct{}
AuditLogFacetsInput has no request parameters.
type AuditLogFacetsOutput ¶
type AuditLogFacetsOutput struct {
Body AuditLogFacets
}
AuditLogFacetsOutput holds the response body for AuditLogFacets.
type AuditLogGetInput ¶
type AuditLogGetInput struct {
ID string `path:"id"`
}
AuditLogGetInput holds the request parameters for AuditLogGet.
type AuditLogGetOutput ¶
AuditLogGetOutput holds the response body for AuditLogGet.
type AuditLogListInput ¶
type AuditLogListInput struct {
AuditLogListQuery
}
AuditLogListInput holds the request parameters for AuditLogList.
type AuditLogListOutput ¶
type AuditLogListOutput struct {
Body query.PaginatedResponse[db.AuditLog]
}
AuditLogListOutput holds the response body for AuditLogList.
type AuditLogListParams ¶
type AuditLogListParams struct {
Search string
Action string
Resource string
ActorID string
ResourceID string
Since string
Until string
SortBy string
SortDir string
Page int
PageSize int
}
AuditLogListParams holds the filter/sort/pagination inputs for the audit log list. Shared by the JSON API handler, the HTML fragment handler, and the page handler so all three paths agree on how params are read.
func ParseAuditLogListParams ¶
func ParseAuditLogListParams(c *echo.Context) AuditLogListParams
ParseAuditLogListParams extracts AuditLogListParams from query string.
type AuditLogListQuery ¶
type AuditLogListQuery struct {
Search string `query:"search" required:"false"`
Action string `query:"action" required:"false"`
Resource string `query:"resource" required:"false"`
ActorID string `query:"actor_id" required:"false"`
ResourceID string `query:"resource_id" required:"false"`
Since string `query:"since" required:"false"`
Until string `query:"until" required:"false"`
SortBy string `query:"sort_by" required:"false"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
AuditLogListQuery holds the filter/sort/pagination inputs for GET /audit-log. The query/default tags drive huma's request binding; the values are mapped into AuditLogListParams for the shared AdminListAuditLog query path.
type AuditLogListResult ¶
type AuditLogListResult struct {
Items []db.AuditLog
Total int64
Page int
PageSize int
TotalPages int
HasNext bool
HasPrev bool
}
AuditLogListResult holds the paginated result of an audit log list query.
func AdminListAuditLog ¶
func AdminListAuditLog(gdb *gorm.DB, p AuditLogListParams, loc *time.Location) (AuditLogListResult, error)
AdminListAuditLog runs the audit log list query with filters, sort, and pagination. Used by both the JSON API handler and the HTML fragment handler, one query path, two response formats. loc is the app timezone, used to interpret zone-less since/until filter values.
type AutoDistributeResult ¶
AutoDistributeResult is the response body of the auto distribution.
type BulkAssignTutorBody ¶
type BulkAssignTutorBody struct {
UserIDs []string `json:"user_ids" required:"true"`
TutorID *uint `json:"tutor_id" required:"false"`
}
BulkAssignTutorBody is the body for POST /courses/{id}/students/tutor. An absent or null tutor_id clears the assignment for all listed users.
type BulkAssignTutorResult ¶
type BulkAssignTutorResult struct {
Assigned int `json:"assigned"`
}
BulkAssignTutorResult is the response body of the bulk tutor assignment.
type CLIVersionInput ¶
type CLIVersionInput struct{}
CLIVersionInput holds the request parameters for CLIVersion (none).
type CLIVersionOutput ¶
type CLIVersionOutput struct {
Body cliVersionResponse
}
CLIVersionOutput holds the response body for CLIVersion.
type ChartsCSVOutput ¶
type ChartsCSVOutput struct {
ContentType string `header:"Content-Type"`
ContentDisposition string `header:"Content-Disposition"`
Body []byte
}
ChartsCSVOutput holds the response for ChartsCSV. The headers are bound via huma's output header fields so the raw CSV body keeps its content type.
type ChartsInput ¶
type ChartsInput struct {
CourseID uint64 `query:"course_id" required:"false"`
}
ChartsInput holds the request parameters for Charts and ChartsCSV.
type ChartsOutput ¶
type ChartsOutput struct {
Body ChartsResponse
}
ChartsOutput holds the response body for Charts.
type ChartsResponse ¶
type ChartsResponse struct {
UsersByFaculty []LabelCount `json:"users_by_faculty"`
RegistrationsOverTime []TimeSeriesPoint `json:"registrations_over_time"`
LoginsByDay []TimeSeriesPoint `json:"logins_by_day"`
LoginsByHour []LabelCount `json:"logins_by_hour"`
LoginsByWeekday []LabelCount `json:"logins_by_weekday"`
AuditActivityOverTime []TimeSeries `json:"audit_activity_over_time"`
ForgejoOverTime []ForgejoTimePoint `json:"forgejo_over_time"`
CoursesPerSemester []LabelCount `json:"courses_per_semester"`
StudentsPerTutor []LabelCount `json:"students_per_tutor"`
GradeDistPerExercise []GradeBucket `json:"grade_distribution_per_exercise"`
AvgScorePerExercise []LabelCount `json:"average_score_per_exercise"`
GradedVsUngraded []GradedUngraded `json:"graded_vs_ungraded_per_exercise"`
GradesByWeek []TimeSeriesPoint `json:"grades_by_week"`
AttendancePerWeek []TimeSeriesPoint `json:"attendance_per_week"`
PresentedVsAttended []LabelCount `json:"presented_vs_attended"`
EnrollmentsByFaculty []LabelCount `json:"enrollments_by_faculty"`
}
ChartsResponse contains all chart datasets for the stats page.
type CourseAccessForCourseGrantInput ¶
CourseAccessForCourseGrantInput holds the request parameters for CourseAccessForCourseGrant.
type CourseAccessForCourseGrantOutput ¶
type CourseAccessForCourseGrantOutput struct {
Body CourseAccessOut
}
CourseAccessForCourseGrantOutput holds the response body for CourseAccessForCourseGrant.
type CourseAccessForCourseListInput ¶
type CourseAccessForCourseListInput struct {
ID string `path:"id"`
}
CourseAccessForCourseListInput holds the request parameters for CourseAccessForCourseList.
type CourseAccessForCourseListOutput ¶
type CourseAccessForCourseListOutput struct {
Body []CourseAccessOut
}
CourseAccessForCourseListOutput holds the response body for CourseAccessForCourseList.
type CourseAccessForCourseRevokeInput ¶
type CourseAccessForCourseRevokeInput struct {
ID string `path:"id"`
UserID string `path:"userID"`
}
CourseAccessForCourseRevokeInput holds the request parameters for CourseAccessForCourseRevoke.
type CourseAccessForCourseRevokeOutput ¶
type CourseAccessForCourseRevokeOutput struct {
Status int
}
CourseAccessForCourseRevokeOutput holds the response status for CourseAccessForCourseRevoke.
type CourseAccessOut ¶
type CourseAccessOut struct {
ID uint `json:"id"`
CourseID uint `json:"course_id"`
UserID string `json:"user_id"`
GrantedBy string `json:"granted_by"`
}
CourseAccessOut is the public shape of a course_accesses grant.
type CourseBody ¶
type CourseBody struct {
Name string `json:"name"`
Semester string `json:"semester"`
DisplayName string `json:"display_name" required:"false"`
Website string `json:"website" required:"false"`
BuilderImage string `json:"builder_image" required:"false"`
GraderImage string `json:"grader_image" required:"false"`
AllowPush bool `json:"allow_push" required:"false"`
AllowJoin bool `json:"allow_join" required:"false"`
RepoAccess string `json:"repo_access" required:"false"`
OwnerID string `json:"owner_id" required:"false"`
}
CourseBody is the request body for creating and updating courses. The id and timestamp fields are server-managed and not part of the payload. owner_id is accepted on create (admins may set it) and ignored on update.
type CourseBrief ¶
type CourseBrief struct {
ID uint `json:"id"`
Name string `json:"name"`
Semester string `json:"semester"`
DisplayName string `json:"display_name"`
}
CourseBrief is a minimal representation of a course for the admin UI.
func VisibleCourses ¶
func VisibleCourses(gdb *gorm.DB, ownerID string, isAdmin bool) []CourseBrief
VisibleCourses returns the courses the caller can see, for filter dropdowns: all courses for admins, owned and granted courses for staff.
type CourseListQuery ¶
type CourseListQuery struct {
Search string `query:"search" required:"false"`
AllowJoin string `query:"allow_join" required:"false"`
AllowPush string `query:"allow_push" required:"false"`
Archived string `query:"archived" required:"false"`
Name string `query:"name" required:"false"`
Display string `query:"display_name" required:"false"`
Semester string `query:"semester" required:"false"`
SortBy string `query:"sort_by" required:"false"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
CourseListQuery holds the filter/sort/pagination inputs for GET /courses. The query/default tags drive huma's request binding; the values are mapped into CoursesListParams for the shared AdminListCourses query path. The boolean filters are strings because huma does not support pointer query parameters; boolParam converts them below.
type CourseStudentGradesInput ¶
type CourseStudentGradesInput struct {
CourseSlug string `path:"courseSlug"`
Username string `path:"username"`
}
CourseStudentGradesInput holds the request parameters for CourseStudentGrades. The course is addressed by its UID (Semester + "-" + Name, the Forgejo org name) and the student by their Forgejo username (users.preferred_username, the repo name), matching the <org>/<repo> layout of the course repositories.
type CourseStudentGradesOutput ¶
type CourseStudentGradesOutput struct {
Body []GradeItem
}
CourseStudentGradesOutput holds the response body for CourseStudentGrades.
type CourseStudentListParams ¶
type CourseStudentListParams struct {
Search string
TutorID string
SortBy string
SortDir string
Page int
PageSize int
}
CourseStudentListParams holds the filter/sort/pagination inputs for the course students list. Shared by the huma handler and any other caller of ListCourseStudents.
func CourseStudentListParamsFromPost ¶
func CourseStudentListParamsFromPost(c *echo.Context) CourseStudentListParams
courseStudentListParamsFromPost builds the params from an htmx POST body that included the filter form (#students-filters): the tab field marks the body as carrying filter state. The bulk_tutor_id and row_tutor_id fields are the assignment targets and are never read as filters; a GET query fallback covers clients that posted without the filter form.
func ParseCourseStudentListParams ¶
func ParseCourseStudentListParams(c *echo.Context) CourseStudentListParams
ParseCourseStudentListParams extracts CourseStudentListParams from the query string, following the same pattern as ParseUsersAdminListParams.
type CourseStudentListQuery ¶
type CourseStudentListQuery struct {
Search string `query:"search" required:"false"`
TutorID string `query:"tutor_id" required:"false"`
SortBy string `query:"sort_by" required:"false"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
CourseStudentListQuery holds the pagination and filter inputs for the course students list endpoint. The query/default tags drive huma's request binding; the values are mapped into CourseStudentListParams for the shared ListCourseStudents query path.
type CourseStudentListResult ¶
type CourseStudentListResult struct {
Items []StudentOut
Page int
PageSize int
TotalItems int64
TotalPages int
HasNext bool
HasPrev bool
}
CourseStudentListResult holds the paginated result of a course students list query.
func ListCourseStudents ¶
func ListCourseStudents(gdb *gorm.DB, courseID uint, params CourseStudentListParams) (CourseStudentListResult, error)
ListCourseStudents runs the course students list query for one course and returns enriched items with pagination metadata. Raw joins are used so the search and sort fields can come from the users and tutors tables; students whose user row is soft-deleted still appear (their User brief is nil). Email is filled from the preloaded user map; empty for soft-deleted users.
type CourseTutorListQuery ¶
type CourseTutorListQuery struct {
SortBy string `query:"sort_by" required:"false" sort:"id,created_at" default_sort:"id asc"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
CourseTutorListQuery holds the pagination inputs for the course tutors list endpoint. The query/default tags drive huma's request binding; the sort/default_sort tags are ignored by huma and consumed by query.Scopes.
type CoursesCreateInput ¶
type CoursesCreateInput struct {
Body CourseBody
}
type CoursesCreateOutput ¶
CoursesCreateOutput holds the response body for CoursesCreate.
type CoursesDeleteInput ¶
type CoursesDeleteInput struct {
ID string `path:"id"`
}
type CoursesDeleteOutput ¶
type CoursesDeleteOutput struct {
Status int
}
CoursesDeleteOutput holds the response status for CoursesDelete.
type CoursesGetInput ¶
type CoursesGetInput struct {
ID string `path:"id"`
}
CoursesGetInput holds the request parameters for CoursesGet.
type CoursesGetOutput ¶
CoursesGetOutput holds the response body for CoursesGet.
type CoursesHardDeleteInput ¶
type CoursesHardDeleteInput struct {
ID string `path:"id"`
}
type CoursesHardDeleteOutput ¶
type CoursesHardDeleteOutput struct {
Status int
}
CoursesHardDeleteOutput holds the response status for CoursesHardDelete.
type CoursesJoinInput ¶
type CoursesJoinInput struct {
ID string `path:"id"`
}
CoursesJoinInput holds the request parameters for CoursesJoin.
type CoursesJoinOutput ¶
CoursesJoinOutput holds the response body for CoursesJoin.
type CoursesListInput ¶
type CoursesListInput struct {
CourseListQuery
}
CoursesListInput holds the request parameters for CoursesList.
type CoursesListOutput ¶
type CoursesListOutput struct {
Body query.PaginatedResponse[db.Course]
}
CoursesListOutput holds the response body for CoursesList.
type CoursesListParams ¶
type CoursesListParams struct {
Search string
AllowJoin *bool
AllowPush *bool
Archived *bool
Name string
Display string
Semester string
SortBy string
SortDir string
Page int
PageSize int
}
CoursesListParams holds the filter/sort/pagination inputs for the admin courses list. Shared by the JSON API handler, the HTML fragment handler, and the page handler so all three paths agree on how params are read.
func ParseCoursesListParams ¶
func ParseCoursesListParams(c *echo.Context) CoursesListParams
ParseCoursesListParams extracts CoursesListParams from query string. Shared by the JSON API handler, the HTML fragment handler, and the page handler so all three paths agree on how params are read.
type CoursesListResult ¶
type CoursesListResult struct {
Items []db.Course
Total int64
Page int
PageSize int
TotalPages int
HasNext bool
HasPrev bool
}
CoursesListResult holds the paginated result of an admin courses list query.
func AdminListCourses ¶
func AdminListCourses(gdb *gorm.DB, p CoursesListParams) (CoursesListResult, error)
AdminListCourses runs the courses list query with filters, sort, and pagination. Used by both the JSON API handler and the HTML fragment handler, one query path, two response formats. Always returns both active and archived courses (use Archived to filter).
type CoursesRestoreInput ¶
type CoursesRestoreInput struct {
ID string `path:"id"`
}
type CoursesRestoreOutput ¶
CoursesRestoreOutput holds the response body for CoursesRestore.
type CoursesStudentsAssignTutorBulkInput ¶
type CoursesStudentsAssignTutorBulkInput struct {
ID string `path:"id"`
Body BulkAssignTutorBody
}
CoursesStudentsAssignTutorBulkInput holds the request parameters for CoursesStudentsAssignTutorBulk.
type CoursesStudentsAssignTutorBulkOutput ¶
type CoursesStudentsAssignTutorBulkOutput struct {
Body BulkAssignTutorResult
}
CoursesStudentsAssignTutorBulkOutput holds the response body for CoursesStudentsAssignTutorBulk.
type CoursesStudentsAutoDistributeInput ¶
type CoursesStudentsAutoDistributeInput struct {
ID string `path:"id"`
}
CoursesStudentsAutoDistributeInput holds the request parameters for CoursesStudentsAutoDistribute.
type CoursesStudentsAutoDistributeOutput ¶
type CoursesStudentsAutoDistributeOutput struct {
Body AutoDistributeResult
}
CoursesStudentsAutoDistributeOutput holds the response body for CoursesStudentsAutoDistribute.
type CoursesStudentsListInput ¶
type CoursesStudentsListInput struct {
ID string `path:"id"`
CourseStudentListQuery
}
CoursesStudentsListInput holds the request parameters for CoursesStudentsList.
type CoursesStudentsListOutput ¶
type CoursesStudentsListOutput struct {
Body query.PaginatedResponse[StudentOut]
}
CoursesStudentsListOutput holds the response body for CoursesStudentsList.
type CoursesStudentsMineInput ¶
type CoursesStudentsMineInput struct {
ID string `path:"id"`
}
CoursesStudentsMineInput holds the request parameters for CoursesStudentsMine.
type CoursesStudentsMineOutput ¶
type CoursesStudentsMineOutput struct {
Body []StudentOut
}
CoursesStudentsMineOutput holds the response body for CoursesStudentsMine.
type CoursesStudentsSetTutorInput ¶
type CoursesStudentsSetTutorInput struct {
ID string `path:"id"`
UserID string `path:"userID"`
Body SetStudentTutorBody
}
CoursesStudentsSetTutorInput holds the request parameters for CoursesStudentsSetTutor.
type CoursesStudentsSetTutorOutput ¶
type CoursesStudentsSetTutorOutput struct {
Body StudentOut
}
CoursesStudentsSetTutorOutput holds the response body for CoursesStudentsSetTutor.
type CoursesStudentsUnassignInput ¶
CoursesStudentsUnassignInput holds the request parameters for CoursesStudentsUnassign.
type CoursesStudentsUnassignOutput ¶
type CoursesStudentsUnassignOutput struct {
Status int
}
CoursesStudentsUnassignOutput holds the response status for CoursesStudentsUnassign.
type CoursesTutorForUserInput ¶
type CoursesTutorForUserInput struct {
CourseID string `path:"course_id"`
UserID string `path:"user_id"`
}
CoursesTutorForUserInput holds the request parameters for CoursesTutorForUser.
type CoursesTutorForUserOutput ¶
type CoursesTutorForUserOutput struct {
Body TutorAssignmentOut
}
CoursesTutorForUserOutput holds the response body for CoursesTutorForUser.
type CoursesTutorMineInput ¶
type CoursesTutorMineInput struct {
CourseID string `path:"course_id"`
}
CoursesTutorMineInput holds the request parameters for CoursesTutorMine.
type CoursesTutorMineOutput ¶
type CoursesTutorMineOutput struct {
Body TutorAssignmentOut
}
CoursesTutorMineOutput holds the response body for CoursesTutorMine.
type CoursesTutorsAssignInput ¶
type CoursesTutorsAssignInput struct {
ID string `path:"id"`
Body AssignTutorBody
}
CoursesTutorsAssignInput holds the request parameters for CoursesTutorsAssign.
type CoursesTutorsAssignOutput ¶
type CoursesTutorsAssignOutput struct {
Body TutorOut
}
CoursesTutorsAssignOutput holds the response body for CoursesTutorsAssign.
type CoursesTutorsListInput ¶
type CoursesTutorsListInput struct {
ID string `path:"id"`
CourseTutorListQuery
}
CoursesTutorsListInput holds the request parameters for CoursesTutorsList.
type CoursesTutorsListOutput ¶
type CoursesTutorsListOutput struct {
Body query.PaginatedResponse[TutorOut]
}
CoursesTutorsListOutput holds the response body for CoursesTutorsList.
type CoursesTutorsUnassignInput ¶
CoursesTutorsUnassignInput holds the request parameters for CoursesTutorsUnassign.
type CoursesTutorsUnassignOutput ¶
type CoursesTutorsUnassignOutput struct {
Status int
}
CoursesTutorsUnassignOutput holds the response status for CoursesTutorsUnassign.
type CoursesUpdateInput ¶
type CoursesUpdateInput struct {
ID string `path:"id"`
Body CourseBody
}
type CoursesUpdateOutput ¶
CoursesUpdateOutput holds the response body for CoursesUpdate.
type CreateUserBody ¶
type CreateUserBody struct {
Email string `json:"email" required:"false"`
Name string `json:"name"`
Subject string `json:"subject" required:"false"`
PreferredUsername string `json:"preferred_username" required:"false"`
StudentID string `json:"student_id" required:"false"`
AccountType string `json:"account_type" required:"false"`
Faculty string `json:"faculty" required:"false"`
EnrolledSubject string `json:"enrolled_subject" required:"false"`
ExtraClaims string `json:"extra_claims" required:"false"`
Role db.Role `json:"role" required:"false"`
}
CreateUserBody is the request body for creating a user. The id and the timestamp fields are server-managed and not part of the payload.
type CronJobResponse ¶
type CronJobResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Tags []string `json:"tags"`
IsRunning bool `json:"is_running"`
LastRunStartedAt *time.Time `json:"last_run_started_at,omitempty"`
LastRunCompletedAt *time.Time `json:"last_run_completed_at,omitempty"`
NextRun *time.Time `json:"next_run,omitempty"`
NextRuns []time.Time `json:"next_runs,omitempty"`
Schedule any `json:"schedule,omitempty"` // optional, see below
}
func ListCronJobs ¶
func ListCronJobs(scheduler gocron.Scheduler) []CronJobResponse
ListCronJobs lists all jobs in the given scheduler, for use by the HTML fragment handlers (which have access to *app.App but not *api.Handler).
type CronListInput ¶
type CronListInput struct{}
CronListInput holds the request parameters for CronList (none).
type CronListOutput ¶
type CronListOutput struct {
Body []CronJobResponse
}
CronListOutput holds the response body for CronList.
type CronRunInput ¶
type CronRunInput struct {
ID string `path:"id"`
}
CronRunInput holds the request parameters for CronRun.
type CronRunOutput ¶
type CronRunOutput struct {
Body CronJobResponse
}
CronRunOutput holds the response body for CronRun.
type ExerciseAllRow ¶
type ExerciseAllRow struct {
ID uint `json:"id"`
Name string `json:"name"`
CourseID uint `json:"course_id"`
CourseName string `json:"course_name"`
Semester string `json:"semester"`
Start time.Time `json:"start"`
End time.Time `json:"end"`
Points *float64 `json:"points"`
UngradedCount int64 `json:"ungraded_count"`
}
ExerciseAllRow is one exercise with its course and the number of submissions that still need grading (points IS NULL).
type ExerciseOut ¶
type ExerciseOut struct {
ID uint `json:"id"`
Name string `json:"name"`
Start time.Time `json:"start"`
End time.Time `json:"end"`
Points *float64 `json:"points"`
CourseID uint `json:"course_id"`
}
ExerciseOut is the public shape of an exercise returned by the build/ grading lookup endpoint. It mirrors the subset of db.Exercise that an external consumer (the build/grading service) needs to decide whether a build is eligible and to pick a pre-deadline commit. It is a separate type from db.Exercise so we never accidentally leak internal fields.
type ExercisesAllListParams ¶
type ExercisesAllListParams struct {
Search string
CourseID string
SortBy string
SortDir string
Page int
PageSize int
}
ExercisesAllListParams holds the filter/sort/pagination inputs for the cross-course exercises list. Shared by the page handler and the HTML fragment handler.
func ParseExercisesAllListParams ¶
func ParseExercisesAllListParams(c *echo.Context) ExercisesAllListParams
ParseExercisesAllListParams extracts ExercisesAllListParams from the query string.
type ExercisesAllListResult ¶
type ExercisesAllListResult struct {
Items []ExerciseAllRow
Total int64
Page int
PageSize int
TotalPages int
HasNext bool
HasPrev bool
}
ExercisesAllListResult holds the paginated result of the cross-course exercises list.
func AdminListExercisesAll ¶
func AdminListExercisesAll(gdb *gorm.DB, p ExercisesAllListParams) (ExercisesAllListResult, error)
AdminListExercisesAll lists exercises across all courses.
func ScopedListExercisesAll ¶
func ScopedListExercisesAll(gdb *gorm.DB, p ExercisesAllListParams, ownerID string) (ExercisesAllListResult, error)
ScopedListExercisesAll lists exercises restricted to courses owned by the given staff member or granted to them via course_accesses.
type ExercisesListInput ¶
type ExercisesListInput struct {
ID string `path:"id"`
}
ExercisesListInput holds the request parameters for ExercisesList.
type ExercisesListOutput ¶
type ExercisesListOutput struct {
Body []ExerciseOut
}
ExercisesListOutput holds the response body for ExercisesList.
type ForgejoRequestFacets ¶
type ForgejoRequestFacets struct {
Sources []string `json:"sources"`
Methods []string `json:"methods"`
}
ForgejoRequestFacets is the response body of GET /forgejo-requests/facets. Each field carries the distinct values currently present in the forgejo_requests table, sorted ascending; the UI uses them to populate filter dropdowns.
type ForgejoRequestListParams ¶
type ForgejoRequestListParams struct {
Search string
Source string
Method string
MinStatus string
MaxStatus string
Since string
Until string
SortBy string
SortDir string
Page int
PageSize int
}
ForgejoRequestListParams holds the filter/sort/pagination inputs for the Forgejo request log list. Shared by the JSON API handler, the HTML fragment handler, and the page handler.
func ParseForgejoRequestListParams ¶
func ParseForgejoRequestListParams(c *echo.Context) ForgejoRequestListParams
ParseForgejoRequestListParams extracts ForgejoRequestListParams from query string.
type ForgejoRequestListQuery ¶
type ForgejoRequestListQuery struct {
Search string `query:"search" required:"false"`
Source string `query:"source" required:"false"`
Method string `query:"method" required:"false"`
MinStatus string `query:"min_status" required:"false"`
MaxStatus string `query:"max_status" required:"false"`
Since string `query:"since" required:"false"`
Until string `query:"until" required:"false"`
SortBy string `query:"sort_by" required:"false"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
ForgejoRequestListQuery holds the filter/sort/pagination inputs for GET /forgejo-requests. The query/default tags drive huma's request binding; the values are mapped into ForgejoRequestListParams for the shared AdminListForgejoRequests query path.
type ForgejoRequestListResult ¶
type ForgejoRequestListResult struct {
Items []db.ForgejoRequest
Total int64
Page int
PageSize int
TotalPages int
HasNext bool
HasPrev bool
}
ForgejoRequestListResult holds the paginated result of a Forgejo request list query.
func AdminListForgejoRequests ¶
func AdminListForgejoRequests(gdb *gorm.DB, p ForgejoRequestListParams, loc *time.Location) (ForgejoRequestListResult, error)
AdminListForgejoRequests runs the Forgejo request list query with filters, sort, and pagination. Used by both the JSON API handler and the HTML fragment handler.
type ForgejoRequestsFacetsInput ¶
type ForgejoRequestsFacetsInput struct{}
ForgejoRequestsFacetsInput has no request parameters.
type ForgejoRequestsFacetsOutput ¶
type ForgejoRequestsFacetsOutput struct {
Body ForgejoRequestFacets
}
ForgejoRequestsFacetsOutput holds the response body for ForgejoRequestsFacets.
type ForgejoRequestsListInput ¶
type ForgejoRequestsListInput struct {
ForgejoRequestListQuery
}
ForgejoRequestsListInput holds the request parameters for ForgejoRequestsList.
type ForgejoRequestsListOutput ¶
type ForgejoRequestsListOutput struct {
Body query.PaginatedResponse[db.ForgejoRequest]
}
ForgejoRequestsListOutput holds the response body for ForgejoRequestsList.
type ForgejoTimePoint ¶
type ForgejoTimePoint struct {
Date string `json:"date"`
Success int64 `json:"success"`
Error int64 `json:"error"`
AvgLatency int64 `json:"avg_latency_ms"`
}
ForgejoTimePoint combines request counts and latency for a single day.
type GradeBucket ¶
type GradeBucket struct {
Exercise string `json:"exercise"`
Bucket string `json:"bucket"`
Count int64 `json:"count"`
}
GradeBucket is one bucket of the grade-distribution histogram for an exercise.
type GradeItem ¶
type GradeItem struct {
ExerciseName string `json:"exercise_name"`
CourseName string `json:"course_name"`
CourseSlug string `json:"course_slug"`
CourseID uint `json:"course_id"`
Points *float64 `json:"points"`
MaxPoints *float64 `json:"max_points"`
GradedAt *time.Time `json:"graded_at"`
Start time.Time `json:"start"`
End time.Time `json:"end"`
}
GradeItem is one exercise entry for the /users/me/grades overview. Unlike RecentGradeItem it also covers exercises that have not been graded yet (no student_exercises row, or one with NULL points): for those points and graded_at are null. Start/End are the exercise's time window so the frontend can render countdowns to the deadline.
type GradedUngraded ¶
type GradedUngraded struct {
Exercise string `json:"exercise"`
Graded int64 `json:"graded"`
Ungraded int64 `json:"ungraded"`
}
GradedUngraded pairs graded and ungraded counts for a single exercise.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
func (*Handler) AttendanceHandler ¶
AttendanceHandler handles POST /api/attendance. A tutor scans a student's QR code (which encodes the student's user ID); this logs a TutorialParticipation record for today. The caller must be a tutor of the given course.
Students assigned to this tutor can check in once per day. Students enrolled in the course but assigned to a different tutor (or no tutor) are "guests" and can attend once per course per week. Students not enrolled in the course at all are rejected.
func (*Handler) AuditLogFacets ¶
func (h *Handler) AuditLogFacets(ctx context.Context, input *AuditLogFacetsInput) (*AuditLogFacetsOutput, error)
AuditLogFacets returns the distinct action and resource values currently present in the audit log, used to populate filter dropdowns (admin only).
func (*Handler) AuditLogGet ¶
func (h *Handler) AuditLogGet(ctx context.Context, input *AuditLogGetInput) (*AuditLogGetOutput, error)
AuditLogGet returns a single audit log entry by ID (admin only).
func (*Handler) AuditLogList ¶
func (h *Handler) AuditLogList(ctx context.Context, input *AuditLogListInput) (*AuditLogListOutput, error)
AuditLogList returns a paginated list of audit log entries, newest first, filterable by action, resource, actor and time range (admin only).
func (*Handler) CLIVersion ¶
func (h *Handler) CLIVersion(ctx context.Context, input *CLIVersionInput) (*CLIVersionOutput, error)
CLIVersion returns the minimum required hopper-cli version from the "cli_min_version" setting. Public endpoint; no authentication required.
func (*Handler) Charts ¶
func (h *Handler) Charts(ctx context.Context, input *ChartsInput) (*ChartsOutput, error)
Charts returns all chart datasets (overview, per-course, cross-dimensional) as JSON. When course_id is present and non-zero, per-course charts filter to that course; overview and cross-dimensional charts are always unfiltered.
func (*Handler) ChartsCSV ¶
func (h *Handler) ChartsCSV(ctx context.Context, input *ChartsInput) (*ChartsCSVOutput, error)
ChartsCSV returns a CSV file containing all chart datasets, one section per chart separated by a blank line. When course_id is present and non-zero, per-course charts filter to that course.
func (*Handler) CourseAccessForCourseGrant ¶
func (h *Handler) CourseAccessForCourseGrant(ctx context.Context, input *CourseAccessForCourseGrantInput) (*CourseAccessForCourseGrantOutput, error)
CourseAccessForCourseGrant grants a staff user full manage rights on the course (admin only). Re-granting an existing pair returns the existing grant unchanged (idempotent).
func (*Handler) CourseAccessForCourseList ¶
func (h *Handler) CourseAccessForCourseList(ctx context.Context, input *CourseAccessForCourseListInput) (*CourseAccessForCourseListOutput, error)
CourseAccessForCourseList returns the course access grants on a course (admin only).
func (*Handler) CourseAccessForCourseRevoke ¶
func (h *Handler) CourseAccessForCourseRevoke(ctx context.Context, input *CourseAccessForCourseRevokeInput) (*CourseAccessForCourseRevokeOutput, error)
CourseAccessForCourseRevoke revokes a course access grant (admin only).
func (*Handler) CourseStudentGrades ¶
func (h *Handler) CourseStudentGrades(ctx context.Context, input *CourseStudentGradesInput) (*CourseStudentGradesOutput, error)
CourseStudentGrades returns all exercises of one course for one student, including ungraded ones (points and graded_at are null for those), with the same item shape as UsersMeGrades. The course is resolved by its UID and the student by their Forgejo username. Access is limited to the student themselves and course staff (course owner, admins, tutors of that course); anyone else signed in gets 403, unknown courses or students 404.
func (*Handler) CoursesCreate ¶
func (h *Handler) CoursesCreate(ctx context.Context, input *CoursesCreateInput) (*CoursesCreateOutput, error)
CoursesCreate creates a new course (staff only).
func (*Handler) CoursesDelete ¶
func (h *Handler) CoursesDelete(ctx context.Context, input *CoursesDeleteInput) (*CoursesDeleteOutput, error)
CoursesDelete deletes a course by ID (soft delete, staff only).
func (*Handler) CoursesGet ¶
func (h *Handler) CoursesGet(ctx context.Context, input *CoursesGetInput) (*CoursesGetOutput, error)
CoursesGet returns a single course by ID. Non-admin users see only joinable courses.
func (*Handler) CoursesHardDelete ¶
func (h *Handler) CoursesHardDelete(ctx context.Context, input *CoursesHardDeleteInput) (*CoursesHardDeleteOutput, error)
CoursesHardDelete permanently removes an archived course and all of its data from the database. Only courses that are already soft-deleted (archived) can be hard-deleted (admin only).
func (*Handler) CoursesJoin ¶
func (h *Handler) CoursesJoin(ctx context.Context, input *CoursesJoinInput) (*CoursesJoinOutput, error)
CoursesJoin enrolls the authenticated user as a student in the given course. The course must have allow_join enabled. When Forgejo is configured, the user is required to have an account on the Forgejo instance (the local part of their email is used as the username); otherwise the request is rejected with 409.
func (*Handler) CoursesList ¶
func (h *Handler) CoursesList(ctx context.Context, input *CoursesListInput) (*CoursesListOutput, error)
CoursesList returns a paginated list of courses. Non-admin users see only joinable courses.
func (*Handler) CoursesRestore ¶
func (h *Handler) CoursesRestore(ctx context.Context, input *CoursesRestoreInput) (*CoursesRestoreOutput, error)
CoursesRestore restores a soft-deleted (archived) course by clearing its deleted_at (staff only).
func (*Handler) CoursesStudentsAssignTutorBulk ¶
func (h *Handler) CoursesStudentsAssignTutorBulk(ctx context.Context, input *CoursesStudentsAssignTutorBulkInput) (*CoursesStudentsAssignTutorBulkOutput, error)
CoursesStudentsAssignTutorBulk assigns or clears the tutor for multiple students of a course in one transaction (staff only). User ids without a matching student row in the course are skipped. Returns the number of student rows updated.
func (*Handler) CoursesStudentsAutoDistribute ¶
func (h *Handler) CoursesStudentsAutoDistribute(ctx context.Context, input *CoursesStudentsAutoDistributeInput) (*CoursesStudentsAutoDistributeOutput, error)
CoursesStudentsAutoDistribute evenly distributes the unassigned students of a course across its tutors (staff only). Existing assignments are kept.
func (*Handler) CoursesStudentsList ¶
func (h *Handler) CoursesStudentsList(ctx context.Context, input *CoursesStudentsListInput) (*CoursesStudentsListOutput, error)
CoursesStudentsList returns a paginated list of students enrolled in a specific course. Only callers who may manage the course get access.
func (*Handler) CoursesStudentsMine ¶
func (h *Handler) CoursesStudentsMine(ctx context.Context, input *CoursesStudentsMineInput) (*CoursesStudentsMineOutput, error)
CoursesStudentsMine returns the students assigned to the authenticated tutor in the given course. Tutors (including admins/owners who are assigned as tutors) see only their assigned students; admins and the course owner without a tutor assignment see all students. Each student includes a trimmed user profile (id, name, preferred_username; the Forgejo repo name).
func (*Handler) CoursesStudentsSetTutor ¶
func (h *Handler) CoursesStudentsSetTutor(ctx context.Context, input *CoursesStudentsSetTutorInput) (*CoursesStudentsSetTutorOutput, error)
CoursesStudentsSetTutor sets or clears the tutor of a single student in a course (staff only). An absent or null tutor_id clears the assignment.
func (*Handler) CoursesStudentsUnassign ¶
func (h *Handler) CoursesStudentsUnassign(ctx context.Context, input *CoursesStudentsUnassignInput) (*CoursesStudentsUnassignOutput, error)
CoursesStudentsUnassign removes a user's enrollment from the given course (staff only).
func (*Handler) CoursesTutorForUser ¶
func (h *Handler) CoursesTutorForUser(ctx context.Context, input *CoursesTutorForUserInput) (*CoursesTutorForUserOutput, error)
CoursesTutorForUser returns the tutor assigned to the given user in the course. Only the user themselves and course staff (course owner, admins, tutors of the course) may look it up; anyone else signed in gets 403. The course is addressed by its numeric ID or its UID.
func (*Handler) CoursesTutorMine ¶
func (h *Handler) CoursesTutorMine(ctx context.Context, input *CoursesTutorMineInput) (*CoursesTutorMineOutput, error)
CoursesTutorMine returns the tutor assigned to the authenticated user in the given course. The course is addressed by its numeric ID or its UID.
func (*Handler) CoursesTutorsAssign ¶
func (h *Handler) CoursesTutorsAssign(ctx context.Context, input *CoursesTutorsAssignInput) (*CoursesTutorsAssignOutput, error)
CoursesTutorsAssign assigns an existing user as a tutor of the given course (staff only).
func (*Handler) CoursesTutorsList ¶
func (h *Handler) CoursesTutorsList(ctx context.Context, input *CoursesTutorsListInput) (*CoursesTutorsListOutput, error)
CoursesTutorsList returns a paginated list of tutors assigned to a specific course. Only callers who may manage the course get access.
func (*Handler) CoursesTutorsUnassign ¶
func (h *Handler) CoursesTutorsUnassign(ctx context.Context, input *CoursesTutorsUnassignInput) (*CoursesTutorsUnassignOutput, error)
CoursesTutorsUnassign removes a user as a tutor of the given course (staff only). In the same transaction the tutor's assigned students are unassigned (tutor_id set to NULL) before the tutor row is deleted, so no student row depends on the removed tutor afterwards.
func (*Handler) CoursesUpdate ¶
func (h *Handler) CoursesUpdate(ctx context.Context, input *CoursesUpdateInput) (*CoursesUpdateOutput, error)
CoursesUpdate updates an existing course by ID. Staff may only update the courses they own.
func (*Handler) CronList ¶
func (h *Handler) CronList(ctx context.Context, input *CronListInput) (*CronListOutput, error)
CronList returns a list of all jobs regularly run by the orchestration app.
func (*Handler) CronRun ¶
func (h *Handler) CronRun(ctx context.Context, input *CronRunInput) (*CronRunOutput, error)
CronRun triggers the given job to run immediately without waiting for its next scheduled execution.
func (*Handler) ExercisesList ¶
func (h *Handler) ExercisesList(ctx context.Context, input *ExercisesListInput) (*ExercisesListOutput, error)
ExercisesList returns the exercises defined in a course, ordered by start date. Used by the build/grading service to resolve exercise deadlines without duplicating the exercise table.
func (*Handler) ForgejoRequestsFacets ¶
func (h *Handler) ForgejoRequestsFacets(ctx context.Context, input *ForgejoRequestsFacetsInput) (*ForgejoRequestsFacetsOutput, error)
ForgejoRequestsFacets returns the distinct source and method values currently present in the Forgejo request log, used to populate filter dropdowns (admin only).
func (*Handler) ForgejoRequestsList ¶
func (h *Handler) ForgejoRequestsList(ctx context.Context, input *ForgejoRequestsListInput) (*ForgejoRequestsListOutput, error)
ForgejoRequestsList returns a paginated list of every outgoing Forgejo HTTP request the orchestrator has made (most recent first), with full request and response envelopes (admin only).
func (*Handler) GitPostRecieveHandler ¶
func (*Handler) GitPreRecieveHandler ¶
func (*Handler) HealthCheckRun ¶
func (h *Handler) HealthCheckRun(ctx context.Context, input *HealthCheckRunInput) (*HealthCheckRunOutput, error)
HealthCheckRun triggers a single health check by name and returns the fresh result. Records an audit entry on success.
func (*Handler) HealthStatus ¶
func (h *Handler) HealthStatus(ctx context.Context, input *HealthStatusInput) (*HealthStatusOutput, error)
HealthStatus returns the latest results of all health checks, the summary counts, the current Beszel metrics snapshot, and process system info.
func (*Handler) SettingsCreate ¶
func (h *Handler) SettingsCreate(ctx context.Context, input *SettingsCreateInput) (*SettingsCreateOutput, error)
SettingsCreate creates a new setting (admin only).
func (*Handler) SettingsDelete ¶
func (h *Handler) SettingsDelete(ctx context.Context, input *SettingsDeleteInput) (*SettingsDeleteOutput, error)
SettingsDelete deletes a setting by key (admin only).
func (*Handler) SettingsGet ¶
func (h *Handler) SettingsGet(ctx context.Context, input *SettingsGetInput) (*SettingsGetOutput, error)
SettingsGet returns a single setting by key if visible to the caller.
func (*Handler) SettingsList ¶
func (h *Handler) SettingsList(ctx context.Context, input *SettingsListInput) (*SettingsListOutput, error)
SettingsList returns a paginated list of settings visible to the caller.
func (*Handler) SettingsUpdate ¶
func (h *Handler) SettingsUpdate(ctx context.Context, input *SettingsUpdateInput) (*SettingsUpdateOutput, error)
SettingsUpdate updates an existing setting by key (admin only).
func (*Handler) Stats ¶
func (h *Handler) Stats(ctx context.Context, input *StatsInput) (*StatsOutput, error)
Stats returns the aggregate dashboard statistics (admin only).
func (*Handler) TaskGet ¶
func (h *Handler) TaskGet(ctx context.Context, input *TaskGetInput) (*TaskGetOutput, error)
TaskGet returns details for a single registered task.
func (*Handler) TaskList ¶
func (h *Handler) TaskList(ctx context.Context, input *TaskListInput) (*TaskListOutput, error)
TaskList returns a list of all registered tasks that can be run manually.
func (*Handler) TaskRun ¶
func (h *Handler) TaskRun(ctx context.Context, input *TaskRunInput) (*TaskRunOutput, error)
TaskRun triggers a registered task to run immediately.
func (*Handler) UsersAdminList ¶
func (h *Handler) UsersAdminList(ctx context.Context, input *UsersAdminListInput) (*UsersAdminListOutput, error)
UsersAdminList returns a paginated list of users with their session count, last login, recent sessions, and course relationships (admin only).
func (*Handler) UsersCreate ¶
func (h *Handler) UsersCreate(ctx context.Context, input *UsersCreateInput) (*UsersCreateOutput, error)
UsersCreate creates a new user (admin only).
func (*Handler) UsersDelete ¶
func (h *Handler) UsersDelete(ctx context.Context, input *UsersDeleteInput) (*UsersDeleteOutput, error)
UsersDelete deletes a user by ID (admin only).
func (*Handler) UsersDeleteSessions ¶
func (h *Handler) UsersDeleteSessions(ctx context.Context, input *UsersDeleteSessionsInput) (*UsersDeleteSessionsOutput, error)
UsersDeleteSessions deletes all active OIDC sessions for the specified user, forcing them to re-authenticate on their next request (admin only).
func (*Handler) UsersGet ¶
func (h *Handler) UsersGet(ctx context.Context, input *UsersGetInput) (*UsersGetOutput, error)
UsersGet returns a single user by ID. Non-admin callers may only read users they are related to (staff: members of their courses; tutors: their assigned students; anyone: themselves); others get 404.
func (*Handler) UsersList ¶
func (h *Handler) UsersList(ctx context.Context, input *UsersListInput) (*UsersListOutput, error)
UsersList returns a paginated list of users matching the requested filters. Non-admin callers only see users they are related to: staff see the students and tutors of the courses they own, tutors see their assigned students, and everyone always sees themselves.
func (*Handler) UsersMe ¶
func (h *Handler) UsersMe(ctx context.Context, input *UsersMeInput) (*UsersMeOutput, error)
UsersMe returns the authenticated user for the currently signed-in user.
func (*Handler) UsersMeCourses ¶
func (h *Handler) UsersMeCourses(ctx context.Context, input *UsersMeCoursesInput) (*UsersMeCoursesOutput, error)
UsersMeCourses returns the courses in which the authenticated user is a student or a tutor. Each entry carries a `role` field ("student" or "tutor") so the caller can pick the right action. Archived (soft-deleted) courses are excluded.
func (*Handler) UsersMeGrades ¶
func (h *Handler) UsersMeGrades(ctx context.Context, input *UsersMeGradesInput) (*UsersMeGradesOutput, error)
UsersMeGrades returns all exercises of the courses the authenticated user is enrolled in as a student, including ungraded ones (points and graded_at are null for those). Items are ordered by course name, then by exercise start, end, and name.
func (*Handler) UsersMeRecentGrades ¶
func (h *Handler) UsersMeRecentGrades(ctx context.Context, input *UsersMeRecentGradesInput) (*UsersMeRecentGradesOutput, error)
UsersMeRecentGrades returns the 5 most recently graded exercises for the authenticated user.
func (*Handler) UsersUpdate ¶
func (h *Handler) UsersUpdate(ctx context.Context, input *UsersUpdateInput) (*UsersUpdateOutput, error)
UsersUpdate updates an existing user by ID (admin only).
type HealthBeszelContainer ¶
type HealthBeszelContainer struct {
Name string `json:"name"`
CPUPercent float64 `json:"cpu_percent"`
MemMB float64 `json:"mem_mb"`
NetUpMBs float64 `json:"net_up_mbs"`
NetDownMBs float64 `json:"net_down_mbs"`
}
HealthBeszelContainer is one container's resource usage from Beszel.
type HealthBeszelInfo ¶
type HealthBeszelInfo struct {
HostStatus string `json:"host_status"`
HostUptimeSec float64 `json:"host_uptime_sec"`
AgentVersion string `json:"agent_version"`
LastHeartbeat time.Time `json:"last_heartbeat"`
CPUPercent float64 `json:"cpu_percent"`
MemUsedGB float64 `json:"mem_used_gb"`
MemTotalGB float64 `json:"mem_total_gb"`
MemPercent float64 `json:"mem_percent"`
DiskUsedGB float64 `json:"disk_used_gb"`
DiskTotalGB float64 `json:"disk_total_gb"`
DiskPercent float64 `json:"disk_percent"`
LoadAvg [3]float64 `json:"load_avg"`
NetUpMBs float64 `json:"net_up_mbs"`
NetDownMBs float64 `json:"net_down_mbs"`
Containers []HealthBeszelContainer `json:"containers"`
}
HealthBeszelInfo mirrors health.BeszelSnapshot in JSON-friendly form.
type HealthCheckItem ¶
type HealthCheckItem struct {
Name string `json:"name"`
Group string `json:"group"`
Status string `json:"status"`
Message string `json:"message"`
LatencyMS int64 `json:"latency_ms"`
ConsecutiveFailures int `json:"consecutive_failures"`
CheckedAt time.Time `json:"checked_at"`
Detail map[string]any `json:"detail,omitempty"`
}
HealthCheckItem is the API view of one health check's latest result.
type HealthCheckRunInput ¶
type HealthCheckRunInput struct {
Name string `path:"name"`
}
HealthCheckRunInput holds the request parameters for HealthCheckRun.
type HealthCheckRunOutput ¶
type HealthCheckRunOutput struct {
Body HealthCheckItem
}
HealthCheckRunOutput holds the response body for HealthCheckRun.
type HealthStatusInput ¶
type HealthStatusInput struct{}
HealthStatusInput holds the request parameters for HealthStatus (none).
type HealthStatusOutput ¶
type HealthStatusOutput struct {
Body struct {
Checks []HealthCheckItem `json:"checks"`
Summary HealthSummary `json:"summary"`
Beszel *HealthBeszelInfo `json:"beszel"`
System HealthSystemInfo `json:"system"`
Warnings []config.ConfigWarning `json:"warnings"`
GeneratedAt time.Time `json:"generated_at"`
}
}
HealthStatusOutput holds the response body for HealthStatus.
type HealthSummary ¶
type HealthSummary struct {
Total int `json:"total"`
OK int `json:"ok"`
Warn int `json:"warn"`
Fail int `json:"fail"`
Unknown int `json:"unknown"`
}
HealthSummary counts the latest results by status.
type HealthSystemInfo ¶
type HealthSystemInfo struct {
GoVersion string `json:"go_version"`
UptimeSec int64 `json:"uptime_sec"`
StartedAt time.Time `json:"started_at"`
}
HealthSystemInfo describes the orchestration process itself.
type Huma ¶
Huma holds the huma API mounted on the shared echo instance.
func NewHuma ¶
NewHuma builds the huma API on top of the given echo instance. The API metadata comes from the resolved config (API_HOST, API_TERMS, API_SUPPORT_* env vars, read once at startup). Huma serves the generated spec itself at /api/openapi.json and /api/openapi.yaml and the docs UI at /api/docs. The schema endpoint is disabled because the spec embeds all schemas.
func (*Huma) UseAuth ¶
func (h *Huma) UseAuth(mw ...echo.MiddlewareFunc) huma.Middlewares
UseAuth converts echo middleware (a.Auth.Require, RequireStaff, ...) into huma middleware for one operation. The middleware runs against the unwrapped echo context; if it short-circuits with an error, the error is rendered by echo's existing error handler unchanged and the huma handler is never invoked.
type LabelCount ¶
LabelCount is a generic label/count pair for categorical chart data.
type MyCourseItem ¶
MyCourseItem pairs a full course with the role the current user has in it (student or tutor). Used by /users/me/courses so the dashboard template can render the right action per role.
type RecentGradeItem ¶
type RecentGradeItem struct {
ExerciseName string `json:"exercise_name"`
CourseName string `json:"course_name"`
CourseSlug string `json:"course_slug"`
CourseID uint `json:"course_id"`
Points *float64 `json:"points"`
MaxPoints *float64 `json:"max_points"`
GradedAt time.Time `json:"graded_at"`
}
RecentGradeItem is a grade record for the dashboard "Recently Graded" list.
type SemesterCount ¶
SemesterCount pairs a semester identifier with the number of courses in it.
type SessionBrief ¶
type SessionBrief struct {
ID string `json:"id"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
}
SessionBrief is a minimal representation of an OIDC session for the admin UI.
type SetStudentTutorBody ¶
type SetStudentTutorBody struct {
TutorID *uint `json:"tutor_id" required:"false"`
}
SetStudentTutorBody is the body for PUT /courses/{id}/students/{userID}/tutor. An absent or null tutor_id clears the assignment.
type SettingBody ¶
type SettingBody struct {
Key string `json:"key"`
Value string `json:"value"`
Type string `json:"type" required:"false"`
Access string `json:"access" required:"false"`
}
SettingBody is the request body for creating and updating settings. Timestamps are server-managed and not part of the payload.
type SettingListQuery ¶
type SettingListQuery struct {
Key string `query:"key" required:"false" filter:"key"`
Type string `query:"type" required:"false" filter:"type"`
Access string `query:"access" required:"false" filter:"access"`
Search string `query:"search" required:"false" search:"key,value"`
SortBy string `query:"sort_by" required:"false" sort:"key,access,created_at,updated_at"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
SettingListQuery holds the filter/sort/pagination inputs for GET /settings. The query/default tags drive huma's request binding; the filter/search/sort tags are ignored by huma and consumed by query.Scopes.
type SettingsCreateInput ¶
type SettingsCreateInput struct {
Body SettingBody
}
SettingsCreateInput holds the request parameters for SettingsCreate.
type SettingsCreateOutput ¶
SettingsCreateOutput holds the response body for SettingsCreate.
type SettingsDeleteInput ¶
type SettingsDeleteInput struct {
Key string `path:"key"`
}
SettingsDeleteInput holds the request parameters for SettingsDelete.
type SettingsDeleteOutput ¶
type SettingsDeleteOutput struct {
Status int
}
SettingsDeleteOutput holds the response status for SettingsDelete.
type SettingsGetInput ¶
type SettingsGetInput struct {
Key string `path:"key"`
}
SettingsGetInput holds the request parameters for SettingsGet.
type SettingsGetOutput ¶
SettingsGetOutput holds the response body for SettingsGet.
type SettingsListInput ¶
type SettingsListInput struct {
SettingListQuery
}
SettingsListInput holds the request parameters for SettingsList.
type SettingsListOutput ¶
type SettingsListOutput struct {
Body query.PaginatedResponse[db.Setting]
}
SettingsListOutput holds the response body for SettingsList.
type SettingsUpdateInput ¶
type SettingsUpdateInput struct {
Key string `path:"key"`
Body SettingBody
}
SettingsUpdateInput holds the request parameters for SettingsUpdate.
type SettingsUpdateOutput ¶
SettingsUpdateOutput holds the response body for SettingsUpdate.
type StaffStatsResponse ¶
type StaffStatsResponse struct {
MyCourses int64 `json:"my_courses"`
JoinableCourses int64 `json:"joinable_courses"`
ArchivedCourses int64 `json:"archived_courses"`
SemesterBreakdown []SemesterCount `json:"semester_breakdown"`
MyStudents int64 `json:"my_students"`
MyTutors int64 `json:"my_tutors"`
MyExercises int64 `json:"my_exercises"`
}
StaffStatsResponse holds dashboard stats scoped to a single staff member.
func ComputeStaffStats ¶
func ComputeStaffStats(gdb *gorm.DB, userID string) StaffStatsResponse
ComputeStaffStats aggregates dashboard statistics scoped to the courses owned by the given user ID or granted to them via course_accesses.
type StatsInput ¶
type StatsInput struct{}
StatsInput holds the request parameters for Stats (none).
type StatsOutput ¶
type StatsOutput struct {
Body StatsResponse
}
StatsOutput holds the response body for Stats.
type StatsResponse ¶
type StatsResponse struct {
TotalUsers int64 `json:"total_users"`
StaffUsers int64 `json:"total_staff"`
AdminUsers int64 `json:"admin_users"`
TotalCourses int64 `json:"total_courses"`
JoinableCourses int64 `json:"joinable_courses"`
ArchivedCourses int64 `json:"archived_courses"`
TotalStudents int64 `json:"total_students"`
TotalTutors int64 `json:"total_tutors"`
TotalAuditLogs int64 `json:"total_audit_logs"`
TotalExercises int64 `json:"total_exercises"`
ActiveSessions int64 `json:"active_sessions"`
TotalTasks int64 `json:"total_tasks"`
TotalCronJobs int64 `json:"total_cron_jobs"`
OrphanOrgs int64 `json:"orphan_orgs"`
SemesterBreakdown []SemesterCount `json:"semester_breakdown"`
}
StatsResponse is the response body of GET /stats. It aggregates counts across the major tables and includes a Forgejo orphan-org count when the Forgejo client is configured.
func ComputeStats ¶
func ComputeStats(gdb *gorm.DB, scheduler jobsLister) StatsResponse
ComputeStats aggregates dashboard statistics. Exported so the HTML fragment handler (which has *app.App but not *api.Handler) can call it. The orphan-org count needs the Forgejo client, which is a package-level singleton, so this function has no receiver.
type StudentOut ¶
type StudentOut struct {
ID uint `json:"id"`
Matrikelnummer *int `json:"matrikelnummer"`
CourseID uint `json:"course_id"`
UserID string `json:"user_id"`
TutorID *uint `json:"tutor_id"`
User *UserBrief `json:"user,omitempty"`
// Email is only populated by ListCourseStudents, which is reachable
// exclusively by callers who may manage the course. Other constructors
// (studentsToOut, the set-tutor handler) leave it empty, keeping the
// tutor-facing endpoints trimmed to the UserBrief identity fields.
Email string `json:"email,omitempty"`
Tutor *TutorBrief `json:"tutor,omitempty"`
}
StudentOut is the public shape of a course-student row. It mirrors the flat db.Student fields and embeds the preloaded user as a trimmed UserBrief. db.Student.User is tagged json:"-" in the model (repo-wide convention to avoid serialization loops), so the DTO carries the user explicitly and controls exactly which user fields leave the API.
type TaskGetInput ¶
type TaskGetInput struct {
Name string `path:"name"`
}
TaskGetInput holds the request parameters for TaskGet.
type TaskGetOutput ¶
TaskGetOutput holds the response body for TaskGet.
type TaskListInput ¶
type TaskListInput struct{}
TaskListInput holds the request parameters for TaskList (none).
type TaskListOutput ¶
TaskListOutput holds the response body for TaskList.
type TaskRunInput ¶
type TaskRunInput struct {
Name string `path:"name"`
}
TaskRunInput holds the request parameters for TaskRun.
type TaskRunOutput ¶
TaskRunOutput holds the response body for TaskRun.
type TimeSeries ¶
type TimeSeries struct {
Label string `json:"label"`
Points []TimeSeriesPoint `json:"points"`
}
TimeSeries is a named series of time-series points.
type TimeSeriesPoint ¶
TimeSeriesPoint is a single point in a time series.
type TutorAssignmentBrief ¶
type TutorAssignmentBrief struct {
Name string `json:"name"`
PreferredUsername string `json:"preferred_username"`
Email string `json:"email"`
}
TutorAssignmentBrief is the trimmed tutor identity returned by the tutor-assignment lookup endpoints. Name may be empty (the client falls back to preferred_username then). Email is included so clients can show a mailto link to the tutor.
type TutorAssignmentOut ¶
type TutorAssignmentOut struct {
Tutor *TutorAssignmentBrief `json:"tutor"`
}
TutorAssignmentOut is the response body of the tutor-assignment lookup endpoints. Tutor is null when the user has no students row in the course, no assigned tutor, or the tutor's user record is missing; the client hides the label then.
type TutorBrief ¶
type TutorBrief struct {
ID uint `json:"id"`
UserID string `json:"user_id"`
Name string `json:"name"`
}
TutorBrief is a trimmed tutor representation for course-student list endpoints. Name is the tutor's user name (empty when the user is not loaded or soft-deleted).
type TutorOut ¶
type TutorOut struct {
ID uint `json:"id"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CourseID uint `json:"course_id"`
UserID string `json:"user_id"`
StudentCount int64 `json:"student_count"`
User *UserBrief `json:"user,omitempty"`
}
TutorOut is the public shape of a course-tutor row. It mirrors the flat db.Tutor fields and embeds the preloaded user as a trimmed UserBrief. db.Tutor.User is tagged json:"-" in the model (repo-wide convention to avoid serialization loops), so the DTO carries the user explicitly and controls exactly which user fields leave the API.
type TutorUserSearchResult ¶
type TutorUserSearchResult struct {
Items []db.User
Page int
PageSize int
TotalItems int64
TotalPages int
HasNext bool
HasPrev bool
}
TutorUserSearchResult holds the paginated result of the tutor-assignment user search.
func SearchUsersForTutorAssignment ¶
func SearchUsersForTutorAssignment(gdb *gorm.DB, search, matrikelnummer string, page, pageSize int, courseID uint) (TutorUserSearchResult, error)
SearchUsersForTutorAssignment returns a paginated list of users matching the search string (ILIKE on name, email, student_id, and preferred_username, mirroring AdminListUsers) and the matrikelnummer filter (ILIKE on student_id), excluding users who are already tutors of courseID. Used by the tutor-assignment page's user list so already-assigned tutors do not show up as add candidates.
type UpdateUserBody ¶
type UpdateUserBody struct {
Subject string `json:"subject" required:"false"`
PreferredUsername string `json:"preferred_username" required:"false"`
StudentID string `json:"student_id" required:"false"`
AccountType string `json:"account_type" required:"false"`
Faculty string `json:"faculty" required:"false"`
EnrolledSubject string `json:"enrolled_subject" required:"false"`
Role db.Role `json:"role" required:"false"`
}
UpdateUserBody is the request body for updating a user. name, email, and extra_claims are excluded because the update path never writes them. subject is still accepted so the identity-uniqueness check sees the same values the handler checks, but it is omitted from the update payload.
type UserAdminItem ¶
type UserAdminItem struct {
db.User `json:"user"`
SessionCount int `json:"session_count"`
LastLogin *time.Time `json:"last_login"`
Sessions []SessionBrief `json:"sessions"`
OwnedCourses []CourseBrief `json:"owned_courses"`
TutoredCourses []CourseBrief `json:"tutored_courses"`
EnrolledCourses []CourseBrief `json:"enrolled_courses"`
GrantedCourses []CourseBrief `json:"granted_courses"`
APIKeys []db.ApiKey `json:"api_keys"`
Grades []RecentGradeItem `json:"grades"`
IsProtectedAdmin bool `json:"is_protected_admin"`
}
UserAdminItem is the full user representation for the admin users page, including session and course relationship data.
func AdminGetUser ¶
func AdminGetUser(gdb *gorm.DB, id string) (UserAdminItem, error)
AdminGetUser fetches a single user with sessions and course relationships for the admin detail modal. Returns the enriched UserAdminItem.
func ScopedGetUser ¶
func ScopedGetUser(gdb *gorm.DB, ownerID, targetUserID string) (UserAdminItem, error)
ScopedGetUser fetches a single user if they are within the caller's scope (self, a student/tutor in a course the caller owns or was granted via course_accesses, or a student assigned to a tutor slot the caller holds). Returns gorm.ErrRecordNotFound if the target is out of scope.
type UserBrief ¶
type UserBrief struct {
ID string `json:"id"`
Name string `json:"name"`
PreferredUsername string `json:"preferred_username"`
}
UserBrief is a trimmed user representation that is safe to embed in list endpoints reachable by non-admin staff (e.g. tutors viewing their students). It exposes only identity fields; email, OIDC subject, student ID (matrikelnummer), account type, faculty, enrolled subject, raw extra claims, and the global role are intentionally omitted.
type UserListQuery ¶
type UserListQuery struct {
ID string `query:"id" required:"false" filter:"id"`
Email string `query:"email" required:"false" filter:"email"`
Subject string `query:"subject" required:"false" filter:"subject"`
StudentID string `query:"student_id" required:"false" filter:"student_id"`
Role string `query:"role" required:"false" filter:"role"`
Search string `query:"search" required:"false" search:"name,email"`
SortBy string `query:"sort_by" required:"false" sort:"id,name,email,created_at,updated_at,student_id,role" default_sort:"created_at desc"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
UserListQuery holds the filter and pagination inputs for GET /users. The query/default tags drive huma's request binding; the filter/search/sort tags are ignored by huma and consumed by query.Scopes.
type UsersAdminListInput ¶
type UsersAdminListInput struct {
UsersAdminListQuery
}
UsersAdminListInput holds the request parameters for UsersAdminList.
type UsersAdminListOutput ¶
type UsersAdminListOutput struct {
Body query.PaginatedResponse[UserAdminItem]
}
UsersAdminListOutput holds the response body for UsersAdminList.
type UsersAdminListParams ¶
type UsersAdminListParams struct {
Search string
Role string
Matrikelnummer string
Tutor bool
SortBy string
SortDir string
Page int
PageSize int
}
UsersAdminListParams holds the filter/sort/pagination inputs for the admin users list. Shared by the JSON API handler and the HTML fragment handler.
func ParseUsersAdminListParams ¶
func ParseUsersAdminListParams(c *echo.Context) UsersAdminListParams
ParseUsersAdminListParams extracts UsersAdminListParams from query string. Shared by the JSON API handler, the HTML fragment handler, and the page handler so all three paths agree on how params are read.
type UsersAdminListQuery ¶
type UsersAdminListQuery struct {
Search string `query:"search" required:"false"`
Role string `query:"role" required:"false"`
Matrikelnummer string `query:"matrikelnummer" required:"false"`
Tutor bool `query:"tutor" required:"false"`
SortBy string `query:"sort_by" required:"false"`
SortDir string `query:"sort_dir" required:"false"`
Page int `query:"page" default:"1"`
PageSize int `query:"page_size" default:"25"`
}
UsersAdminListQuery holds the filter/sort/pagination inputs for the admin users list. The query/default tags drive huma's request binding; the values are mapped into UsersAdminListParams for the shared AdminListUsers query path.
type UsersAdminListResult ¶
type UsersAdminListResult struct {
Items []UserAdminItem
Total int64
Page int
PageSize int
TotalPages int
HasNext bool
HasPrev bool
}
UsersAdminListResult holds the paginated result of an admin users list query.
func AdminListUsers ¶
func AdminListUsers(gdb *gorm.DB, p UsersAdminListParams) (UsersAdminListResult, error)
AdminListUsers runs the admin users list query and returns enriched items with pagination metadata. Used by both the JSON API handler and the HTML fragment handler: one query path, two response formats.
func ScopedListUsers ¶
func ScopedListUsers(gdb *gorm.DB, p UsersAdminListParams, ownerID string) (UsersAdminListResult, error)
ScopedListUsers runs the admin users list query but restricts results to users visible to the given staff member: themselves, plus students and tutors of courses they own or were granted via course_accesses. Used by staff-scoped fragment handlers.
type UsersCreateInput ¶
type UsersCreateInput struct {
Body CreateUserBody
}
UsersCreateInput holds the request parameters for UsersCreate.
type UsersCreateOutput ¶
UsersCreateOutput holds the response body for UsersCreate.
type UsersDeleteInput ¶
type UsersDeleteInput struct {
ID string `path:"id"`
}
UsersDeleteInput holds the request parameters for UsersDelete.
type UsersDeleteOutput ¶
type UsersDeleteOutput struct {
Status int
}
UsersDeleteOutput holds the response status for UsersDelete.
type UsersDeleteSessionsInput ¶
type UsersDeleteSessionsInput struct {
ID string `path:"id"`
}
UsersDeleteSessionsInput holds the request parameters for UsersDeleteSessions.
type UsersDeleteSessionsOutput ¶
type UsersDeleteSessionsOutput struct {
Body struct {
DeletedCount int64 `json:"deleted_count"`
}
}
UsersDeleteSessionsOutput holds the response body for UsersDeleteSessions.
type UsersGetInput ¶
type UsersGetInput struct {
ID string `path:"id"`
}
UsersGetInput holds the request parameters for UsersGet.
type UsersGetOutput ¶
UsersGetOutput holds the response body for UsersGet.
type UsersListInput ¶
type UsersListInput struct {
UserListQuery
}
UsersListInput holds the request parameters for UsersList.
type UsersListOutput ¶
type UsersListOutput struct {
Body query.PaginatedResponse[db.User]
}
UsersListOutput holds the response body for UsersList.
type UsersMeCoursesInput ¶
type UsersMeCoursesInput struct{}
UsersMeCoursesInput holds the request parameters for UsersMeCourses (none).
type UsersMeCoursesOutput ¶
type UsersMeCoursesOutput struct {
Body []MyCourseItem
}
UsersMeCoursesOutput holds the response body for UsersMeCourses.
type UsersMeGradesInput ¶
type UsersMeGradesInput struct{}
UsersMeGradesInput holds the request parameters for UsersMeGrades (none).
type UsersMeGradesOutput ¶
type UsersMeGradesOutput struct {
Body []GradeItem
}
UsersMeGradesOutput holds the response body for UsersMeGrades.
type UsersMeInput ¶
type UsersMeInput struct{}
UsersMeInput holds the request parameters for UsersMe (none).
type UsersMeOutput ¶
UsersMeOutput holds the response body for UsersMe.
type UsersMeRecentGradesInput ¶
type UsersMeRecentGradesInput struct{}
UsersMeRecentGradesInput holds the request parameters for UsersMeRecentGrades (none).
type UsersMeRecentGradesOutput ¶
type UsersMeRecentGradesOutput struct {
Body []RecentGradeItem
}
UsersMeRecentGradesOutput holds the response body for UsersMeRecentGrades.
type UsersUpdateInput ¶
type UsersUpdateInput struct {
ID string `path:"id"`
Body UpdateUserBody
}
UsersUpdateInput holds the request parameters for UsersUpdate.
type UsersUpdateOutput ¶
UsersUpdateOutput holds the response body for UsersUpdate.