app

package
v0.0.0-...-c6dbdfa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2024 License: GPL-3.0 Imports: 36 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrBadRequest returns status 400 Bad Request for malformed request body.
	ErrBadRequest = &ErrResponse{HTTPStatusCode: http.StatusBadRequest, StatusText: http.StatusText(http.StatusBadRequest)}

	// ErrUnauthorized returns 401 Unauthorized.
	// e.g. "User has not logged-in"
	ErrUnauthenticated = &ErrResponse{HTTPStatusCode: http.StatusUnauthorized, StatusText: http.StatusText(http.StatusUnauthorized)}

	// ErrForbidden returns status 403 Forbidden for unauthorized request.
	// e.g. "User doesn't have enough privilege"
	ErrUnauthorized = &ErrResponse{HTTPStatusCode: http.StatusForbidden, StatusText: http.StatusText(http.StatusForbidden)}

	// ErrNotFound returns status 404 Not Found for invalid resource request.
	ErrNotFound = &ErrResponse{HTTPStatusCode: http.StatusNotFound, StatusText: http.StatusText(http.StatusNotFound)}

	// ErrInternalServerError returns status 500 Internal Server Error.
	ErrInternalServerError = &ErrResponse{HTTPStatusCode: http.StatusInternalServerError, StatusText: http.StatusText(http.StatusInternalServerError)}
)

see https://stackoverflow.com/a/50143519/7443104

Functions

func BasicAuthMiddleware

func BasicAuthMiddleware(realm string, credentials map[string]string) func(next http.Handler) http.Handler

func EnsurePrivacyInEnrollments

func EnsurePrivacyInEnrollments(enrolledUsers []model.UserCourse, givenRole authorize.CourseRole) []model.UserCourse

EnsurePrivacyInEnrollments removes some data from the request to ensure that not everyone has access to personal data

func ErrRender

func ErrRender(err error) render.Renderer

ErrRender returns status 422 Unprocessable Entity rendering response error.

func FileServer

func FileServer(r chi.Router, path string, root http.FileSystem)

FileServer conveniently sets up a http.FileServer handler to serve static files from a http.FileSystem.

func InitPrometheus

func InitPrometheus()

func InitSubmissionProducer

func InitSubmissionProducer()

func LimitedDecoder

func LimitedDecoder(r *http.Request, v interface{}) error

LimitedDecoder limits the amount of data a client can send in a JSON data request. The golang fork-join multi-threading allows no easy way to cancel started requests. Therefore we limit the amount of data which is read by the server whenever we need to parse a JSON request.

func LoggingMiddleware

func LoggingMiddleware(next http.Handler) http.Handler

func New

func New(db *sqlx.DB, promhttp http.Handler, log bool) (*chi.Mux, error)

New configures application resources and routes.

func NoCache

func NoCache(next http.Handler) http.Handler

NoCache writes required cache headers to all requests.

func NowUTC

func NowUTC() time.Time

NowUTC returns the current server time

func OverTime

func OverTime(t time.Time) bool

OverTime tests if the deadline is missed (alias for publicyet)

func PublicYet

func PublicYet(t time.Time) bool

PublicYet tests if a given time is now or in the past

func RunInit

func RunInit()

func SecureMiddleware

func SecureMiddleware(next http.Handler) http.Handler

SecureMiddleware writes required access headers to all requests.

func VersionMiddleware

func VersionMiddleware(next http.Handler) http.Handler

VersionMiddleware writes the current API version to the headers.

Types

type API

type API struct {
	User       *UserResource
	Account    *AccountResource
	Auth       *AuthResource
	Course     *CourseResource
	Sheet      *SheetResource
	Task       *TaskResource
	Group      *GroupResource
	TaskRating *TaskRatingResource
	Submission *SubmissionResource
	Material   *MaterialResource
	Grade      *GradeResource
	Common     *CommonResource
	Exam       *ExamResource
}

API provides application resources and handlers.

func NewAPI

func NewAPI(db *sqlx.DB, tokenAuth *authenticate.TokenAuth, sessionAuth *scs.Manager) (*API, error)

NewAPI configures and returns application API.

type AccountRequest

type AccountRequest struct {
	Account *struct {
		Email             string `json:"email" required:"false" example:"other@example.com"`
		PlainPassword     string `json:"plain_password" required:"false" example:"new_password"`
		EncryptedPassword string `json:"-"`
	} `json:"account" required:"true"`
	OldPlainPassword string `json:"old_plain_password" example:"old_password"`
}

AccountRequest is the request when a password/email update is requested.

func (*AccountRequest) Bind

func (body *AccountRequest) Bind(r *http.Request) error

Bind preprocesses a AccountRequest.

type AccountResource

type AccountResource struct {
	Stores *Stores
}

AccountResource specifies user management handler.

func NewAccountResource

func NewAccountResource(stores *Stores) *AccountResource

NewAccountResource create and returns a AccountResource.

func (*AccountResource) ChangeAvatarHandler

func (rs *AccountResource) ChangeAvatarHandler(w http.ResponseWriter, r *http.Request)

ChangeAvatarHandler is public endpoint for URL: /account/avatar METHOD: post TAG: account REQUEST: Imagefile RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Change the specific account avatar of the request identity DESCRIPTION: We currently support only jpg, jpeg,png images.

func (*AccountResource) CreateHandler

func (rs *AccountResource) CreateHandler(w http.ResponseWriter, r *http.Request)

CreateHandler is public endpoint for URL: /account METHOD: post TAG: account REQUEST: CreateUserAccountRequest RESPONSE: 201,UserResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: Create a new user account to register on the site. DESCRIPTION: The account will be created and a confirmation email will be sent. There is no way to set an avatar here and root will be false by default.

func (*AccountResource) DeleteAvatarHandler

func (rs *AccountResource) DeleteAvatarHandler(w http.ResponseWriter, r *http.Request)

DeleteAvatarHandler is public endpoint for URL: /account/avatar METHOD: delete TAG: account RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Delete the specific account avatar of the request identity DESCRIPTION: This is necessary, when a user wants to switch back to a default avatar.

func (*AccountResource) EditHandler

func (rs *AccountResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /account METHOD: patch TAG: account REQUEST: AccountRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Updates email or password DESCRIPTION: This is the only endpoint having PATCH as the backend will automatically only update fields which are non-empty. If both are given, it will update both fields. If the email should be changed a new confirmation email will be sent and clicking on the confirmation link is required to login again.

func (*AccountResource) GetAvatarHandler

func (rs *AccountResource) GetAvatarHandler(w http.ResponseWriter, r *http.Request)

GetAvatarHandler is public endpoint for URL: /account/avatar METHOD: get TAG: account RESPONSE: 200,ImageFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Retrieve the specific account avatar from the request identity DESCRIPTION: If there is an avatar for this specific user, this will return the image otherwise it will use a default image. We currently support only jpg images.

func (*AccountResource) GetEnrollmentsHandler

func (rs *AccountResource) GetEnrollmentsHandler(w http.ResponseWriter, r *http.Request)

GetEnrollmentsHandler is public endpoint for URL: /account/enrollments METHOD: get TAG: account RESPONSE: 200,UserEnrollmentResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Retrieve the specific account avatar from the request identity This lists all course enrollments of the request identity including role.

func (*AccountResource) GetExamEnrollmentsHandler

func (rs *AccountResource) GetExamEnrollmentsHandler(w http.ResponseWriter, r *http.Request)

GetExamEnrollmentsHandler is public endpoint for URL: /account/exams/enrollments METHOD: get TAG: account RESPONSE: 200,ExamEnrollmentResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Retrieve the specific account avatar from the request identity This lists all course enrollments of the request identity including role.

func (*AccountResource) GetHandler

func (rs *AccountResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /account METHOD: get TAG: account RESPONSE: 200,UserResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Retrieve the specific user account from the requesting identity. DESCRIPTION: It will contain all information as this can only query the own account

type AchievementInfo

type AchievementInfo struct {
	User   UserInfo `json:"user_info" example:""`
	Points []int    `json:"points" example:"4"`
}

type AuthResource

type AuthResource struct {
	Stores      *Stores
	TokenAuth   *authenticate.TokenAuth
	SessionAuth *scs.Manager
}

AuthResource specifies user management handler.

func NewAuthResource

func NewAuthResource(stores *Stores, tokenAuth *authenticate.TokenAuth, sessionAuth *scs.Manager) *AuthResource

NewAuthResource create and returns a AuthResource.

func (*AuthResource) ConfirmEmailHandler

func (rs *AuthResource) ConfirmEmailHandler(w http.ResponseWriter, r *http.Request)

ConfirmEmailHandler is public endpoint for URL: /auth/confirm_email METHOD: post TAG: auth REQUEST: ConfirmEmailRequest RESPONSE: 200,OK RESPONSE: 400,BadRequest SUMMARY: handles the confirmation link and activate an account

func (*AuthResource) LoginHandler

func (rs *AuthResource) LoginHandler(w http.ResponseWriter, r *http.Request)

LoginHandler is public endpoint for URL: /auth/sessions METHOD: post TAG: auth REQUEST: LoginRequest RESPONSE: 200,LoginResponse RESPONSE: 400,BadRequest SUMMARY: Start a session DESCRIPTION: This endpoint will generate the access token without login credentials if the refresh token is given.

func (*AuthResource) LogoutHandler

func (rs *AuthResource) LogoutHandler(w http.ResponseWriter, r *http.Request)

LogoutHandler is public endpoint for URL: /auth/sessions METHOD: delete TAG: auth RESPONSE: 200,OK RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Destroy a session

func (*AuthResource) RefreshAccessTokenHandler

func (rs *AuthResource) RefreshAccessTokenHandler(w http.ResponseWriter, r *http.Request)

RefreshAccessTokenHandler is public endpoint for URL: /auth/token METHOD: post TAG: auth REQUEST: LoginRequest RESPONSE: 201,AuthResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: Refresh or Generate Access token DESCRIPTION: This endpoint will generate the access token without login credentials if the refresh token is given.

func (*AuthResource) RequestPasswordResetHandler

func (rs *AuthResource) RequestPasswordResetHandler(w http.ResponseWriter, r *http.Request)

RequestPasswordResetHandler is public endpoint for URL: /auth/request_password_reset METHOD: post TAG: auth REQUEST: ResetPasswordRequest RESPONSE: 200,OK RESPONSE: 400,BadRequest SUMMARY: will send an email with password reset link

func (*AuthResource) UpdatePasswordHandler

func (rs *AuthResource) UpdatePasswordHandler(w http.ResponseWriter, r *http.Request)

UpdatePasswordHandler is public endpoint for URL: /auth/update_password METHOD: post TAG: auth REQUEST: UpdatePasswordRequest RESPONSE: 200,OK RESPONSE: 400,BadRequest SUMMARY: sets a new password

type AuthResponse

type AuthResponse struct {
	Access struct {
		Token string `json:"token" example:"eyJhbGciOiJIUzI1...rZikwLEI7XhY"`
	} `json:"access"`
	Refresh struct {
		Token string `json:"token" example:"eyJhbGciOiJIUzI1...EYCBjslOydswU"`
	} `json:"refresh"`
}

func (*AuthResponse) Render

func (body *AuthResponse) Render(w http.ResponseWriter, r *http.Request) error

type ChangeRoleInCourseRequest

type ChangeRoleInCourseRequest struct {
	Role int `json:"role" example:"0"`
}

func (*ChangeRoleInCourseRequest) Bind

type CommonResource

type CommonResource struct {
	Stores *Stores
}

CommonResource specifies user management handler.

func NewCommonResource

func NewCommonResource(stores *Stores) *CommonResource

NewCommonResource create and returns a CommonResource.

func (*CommonResource) PingHandler

func (rs *CommonResource) PingHandler(w http.ResponseWriter, r *http.Request)

PingHandler is public endpoint for URL: /ping METHOD: get TAG: common RESPONSE: 200,PongResponse SUMMARY: heartbeat of backend

func (*CommonResource) PrivacyStatementHandler

func (rs *CommonResource) PrivacyStatementHandler(w http.ResponseWriter, r *http.Request)

PrivacyStatementHandler is public endpoint for URL: /privacy_statement METHOD: get TAG: common RESPONSE: 200,RawResponse SUMMARY: the privacy statement

func (*CommonResource) VersionHandler

func (rs *CommonResource) VersionHandler(w http.ResponseWriter, r *http.Request)

VersionHandler is public endpoint for URL: /version METHOD: get TAG: common RESPONSE: 200,VersionResponse SUMMARY: all version information

type ConfirmEmailRequest

type ConfirmEmailRequest struct {
	Email             string `json:"email" example:"test@uni-tuebingen.de"`
	ConfirmEmailToken string `json:"confirmation_token" example:"SDFOI34FZH4HUFH"`
}

ConfirmEmailRequest is the request for email verification.

func (*ConfirmEmailRequest) Bind

func (body *ConfirmEmailRequest) Bind(r *http.Request) error

Bind preprocesses a ConfirmEmailRequest.

type CourseRequest

type CourseRequest struct {
	Name               string    `json:"name" example:"Info 2"`
	Description        string    `json:"description" example:"An example course."`
	BeginsAt           time.Time `json:"begins_at" example:"auto"`
	EndsAt             time.Time `json:"ends_at" example:"auto"`
	RequiredPercentage int       `json:"required_percentage" example:"80"`
}

CourseRequest is the request payload for course management.

func (*CourseRequest) Bind

func (body *CourseRequest) Bind(r *http.Request) error

Bind preprocesses a CourseRequest.

func (*CourseRequest) Validate

func (body *CourseRequest) Validate() error

type CourseResource

type CourseResource struct {
	Stores *Stores
}

CourseResource specifies course management handler.

func NewCourseResource

func NewCourseResource(stores *Stores) *CourseResource

NewCourseResource create and returns a CourseResource.

func (*CourseResource) BidsHandler

func (rs *CourseResource) BidsHandler(w http.ResponseWriter, r *http.Request)

BidsHandler is public endpoint for URL: /courses/{course_id}/bids URLPARAM: course_id,integer METHOD: get TAG: courses RESPONSE: 200,GroupBidsResponseList RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get all bids for the request identity in a course

func (*CourseResource) ChangeRole

func (rs *CourseResource) ChangeRole(w http.ResponseWriter, r *http.Request)

ChangeRole is public endpoint for URL: /courses/{course_id}/enrollments/{user_id} URLPARAM: course_id,integer URLPARAM: user_id,integer METHOD: put TAG: enrollments REQUEST: ChangeRoleInCourseRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: change role of specific user

func (*CourseResource) Context

func (rs *CourseResource) Context(next http.Handler) http.Handler

Context middleware is used to load an Course object from the URL parameter `courseID` passed through as the request. In case the Course could not be found, we stop here and return a 404. We do NOT check whether the course is authorized to get this course.

func (*CourseResource) CreateHandler

func (rs *CourseResource) CreateHandler(w http.ResponseWriter, r *http.Request)

CreateHandler is public endpoint for URL: /courses METHOD: post TAG: courses REQUEST: CourseRequest RESPONSE: 204,CourseResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: create a new course

func (*CourseResource) DeleteHandler

func (rs *CourseResource) DeleteHandler(w http.ResponseWriter, r *http.Request)

DeleteHandler is public endpoint for URL: /courses/{course_id} URLPARAM: course_id,integer METHOD: delete TAG: courses RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: delete a specific course

func (*CourseResource) DeleteUserEnrollmentHandler

func (rs *CourseResource) DeleteUserEnrollmentHandler(w http.ResponseWriter, r *http.Request)

DeleteUserEnrollmentHandler is public endpoint for URL: /courses/{course_id}/enrollments/{user_id} URLPARAM: course_id,integer URLPARAM: user_id,integer METHOD: delete TAG: enrollments RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: give enrollment of a specific user in a specific course

func (*CourseResource) DisenrollHandler

func (rs *CourseResource) DisenrollHandler(w http.ResponseWriter, r *http.Request)

DisenrollHandler is public endpoint for URL: /courses/{course_id}/enrollments URLPARAM: course_id,integer METHOD: delete TAG: enrollments RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: disenroll a user from a course

func (*CourseResource) EditHandler

func (rs *CourseResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /courses/{course_id} URLPARAM: course_id,integer METHOD: put TAG: courses REQUEST: CourseRequest RESPONSE: 204,NotContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: update a specific course

func (*CourseResource) EnrollHandler

func (rs *CourseResource) EnrollHandler(w http.ResponseWriter, r *http.Request)

EnrollHandler is public endpoint for URL: /courses/{course_id}/enrollments URLPARAM: course_id,integer METHOD: post TAG: enrollments REQUEST: Empty RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: enroll a user into a course

func (*CourseResource) GetHandler

func (rs *CourseResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /courses/{course_id} URLPARAM: course_id,integer METHOD: get TAG: courses RESPONSE: 200,CourseResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get a specific course

func (*CourseResource) GetUserEnrollmentHandler

func (rs *CourseResource) GetUserEnrollmentHandler(w http.ResponseWriter, r *http.Request)

GetUserEnrollmentHandler is public endpoint for URL: /courses/{course_id}/enrollments/{user_id} URLPARAM: course_id,integer URLPARAM: user_id,integer METHOD: get TAG: enrollments RESPONSE: 200,EnrollmentResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: give enrollment of a specific user in a specific course

func (*CourseResource) IndexEnrollmentsHandler

func (rs *CourseResource) IndexEnrollmentsHandler(w http.ResponseWriter, r *http.Request)

IndexEnrollmentsHandler is public endpoint for URL: /courses/{course_id}/enrollments URLPARAM: course_id,integer QUERYPARAM: roles,string QUERYPARAM: first_name,string QUERYPARAM: last_name,string QUERYPARAM: email,string QUERYPARAM: subject,string QUERYPARAM: language,string QUERYPARAM: q,string METHOD: get TAG: enrollments RESPONSE: 200,EnrollmentResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: list all courses DESCRIPTION: If the query 'q' parameter is given this endpoints returns all users which matches the query by first_name, last_name or email. The 'q' does not need be wrapped by '%'. But all other query strings do need to be wrapped by '%' to indicated end and start of a string.

func (*CourseResource) IndexHandler

func (rs *CourseResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses METHOD: get TAG: courses RESPONSE: 200,CourseResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: list all courses

func (*CourseResource) PointsHandler

func (rs *CourseResource) PointsHandler(w http.ResponseWriter, r *http.Request)

PointsHandler is public endpoint for URL: /courses/{course_id}/points URLPARAM: course_id,integer METHOD: get TAG: courses RESPONSE: 200,SheetPointsResponseList RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get all points for the request identity

func (*CourseResource) RoleContext

func (rs *CourseResource) RoleContext(next http.Handler) http.Handler

RoleContext middleware extracts the role of an identity in a given course

func (*CourseResource) SendEmailHandler

func (rs *CourseResource) SendEmailHandler(w http.ResponseWriter, r *http.Request)

SendEmailHandler is public endpoint for URL: /courses/{course_id}/emails URLPARAM: course_id,integer QUERYPARAM: roles,string QUERYPARAM: first_name,string QUERYPARAM: last_name,string QUERYPARAM: email,string QUERYPARAM: subject,string QUERYPARAM: language,string METHOD: post TAG: courses TAG: email REQUEST: EmailRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: send email to entire course filtered

type CourseResponse

type CourseResponse struct {
	ID                 int64     `json:"id" example:"1"`
	Name               string    `json:"name" example:"Info2"`
	Description        string    `json:"description" example:"Some course description here"`
	BeginsAt           time.Time `json:"begins_at" example:"auto"`
	EndsAt             time.Time `json:"ends_at" example:"auto"`
	RequiredPercentage int       `json:"required_percentage" example:"80"`
}

CourseResponse is the response payload for course management.

func (*CourseResponse) Render

func (body *CourseResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a CourseResponse.

type CourseStore

type CourseStore interface {
	Get(courseID int64) (*model.Course, error)
	Update(p *model.Course) error
	GetAll() ([]model.Course, error)
	Create(p *model.Course) (*model.Course, error)
	Delete(courseID int64) error
	Enroll(courseID int64, userID int64, role int64) error
	Disenroll(courseID int64, userID int64) error
	EnrolledUsers(
		courseID int64,
		roleFilter []string,
		filterFirstName string,
		filterLastName string,
		filterEmail string,
		filterSubject string,
		filterLanguage string) ([]model.UserCourse, error)
	FindEnrolledUsers(
		courseID int64,
		roleFilter []string,
		filterQuery string,
	) ([]model.UserCourse, error)
	GetUserEnrollment(courseID int64, userID int64) (*model.UserCourse, error)
	PointsForUser(userID int64, courseID int64) ([]model.SheetPoints, error)
	RoleInCourse(userID int64, courseID int64) (authorize.CourseRole, error)
	UpdateRole(courseID, userID int64, role int) error
}

CourseStore defines course related database queries

type CreateUserAccountRequest

type CreateUserAccountRequest struct {
	User *struct {
		FirstName     string `json:"first_name" example:"Max"`
		LastName      string `json:"last_name" example:"Mustermensch"`
		Email         string `json:"email" example:"test@uni-tuebingen.de"`
		StudentNumber string `json:"student_number" example:"0815"`
		Semester      int    `json:"semester" example:"15" minval:"1"`
		Subject       string `json:"subject" example:"computer science"`
		Language      string `json:"language" example:"en" len:"2"`
	} `json:"user" required:"true"`
	Account *struct {
		Email             string `json:"email" example:"test@uni-tuebingen.de"`
		PlainPassword     string `json:"plain_password" example:"test"`
		EncryptedPassword string `json:"-"`
	} `json:"account" required:"true"`
}

CreateUserAccountRequest represents the incoming request from a registration form.

func (*CreateUserAccountRequest) Bind

func (body *CreateUserAccountRequest) Bind(r *http.Request) (err error)

Bind preprocesses a CreateUserAccountRequest.

func (*CreateUserAccountRequest) Validate

func (body *CreateUserAccountRequest) Validate() error

Validate validates a CreateUserAccountRequest.

type EmailRequest

type EmailRequest struct {
	Subject string `json:"subject" example:"Switch to another day"`
	Body    string `json:"body" example:"Xmax will be from now on on 26th of Nov."`
}

EmailRequest is the request payload containing email information.

func (*EmailRequest) Bind

func (body *EmailRequest) Bind(r *http.Request) error

Bind preprocesses a userRequest.

type EnrollmentResponse

type EnrollmentResponse struct {
	Role int64 `json:"role" example:"1"`
	User *struct {
		ID            int64       `json:"id" example:"13"`
		FirstName     string      `json:"first_name" example:"Max"`
		LastName      string      `json:"last_name" example:"Mustermensch"`
		AvatarURL     null.String `json:"avatar_url" example:"/example.com/file"`
		Email         string      `json:"email" example:"test@uni-tuebingen.de"`
		StudentNumber string      `json:"student_number" example:"0816"`
		Semester      int         `json:"semester" example:"8" minval:"1"`
		Subject       string      `json:"subject" example:"informatik"`
		Language      string      `json:"language" example:"de" len:"2"`
	} `json:"user"`
}

CourseResponse is the response payload for course management.

func (*EnrollmentResponse) Render

Render post-processes a CourseResponse.

type ErrResponse

type ErrResponse struct {
	Err            error `json:"-"` // low-level runtime error
	HTTPStatusCode int   `json:"-"` // http response status code

	StatusText       string            `json:"status"`           // user-level status message
	AppCode          int64             `json:"code,omitempty"`   // application-specific error code
	ErrorText        string            `json:"error,omitempty"`  // application-level error message, for debugging
	ValidationErrors validation.Errors `json:"errors,omitempty"` // user level model validation errors
}

ErrResponse renderer type for handling all sorts of errors.

func ErrBadRequestWithDetails

func ErrBadRequestWithDetails(err error) *ErrResponse

ErrBadRequestWithDetails returns status 400 with a text

func ErrInternalServerErrorWithDetails

func ErrInternalServerErrorWithDetails(err error) *ErrResponse

ErrInternalServerErrorWithDetails returns status 500 with a text

func ErrTimeoutWithDetails

func ErrTimeoutWithDetails(err error) *ErrResponse

ErrTimeoutWithDetails returns status 504 with a text

func ErrUnauthorizedWithDetails

func ErrUnauthorizedWithDetails(err error) *ErrResponse

ErrUnauthorizedWithDetails returns status 403 with a text e.g. "User doesn't have enough privilege"

func (*ErrResponse) Render

func (e *ErrResponse) Render(w http.ResponseWriter, r *http.Request) error

Render sets the application-specific error code in AppCode.

type ExamEnrollmentResponse

type ExamEnrollmentResponse struct {
	Status   int    `json:"status" example:"1"`
	Mark     string `json:"mark" example:"1"`
	UserID   int64  `json:"user_id" example:"42"`
	CourseID int64  `json:"course_id" example:"1"`
	ExamID   int64  `json:"exam_id" example:"1"`
}

ExamEnrollmentResponse is the response payload for course management.

func (*ExamEnrollmentResponse) Render

Render post-processes a ExamEnrollmentResponse.

type ExamRequest

type ExamRequest struct {
	Name        string    `json:"name" example:"Info 2"`
	Description string    `json:"description" example:"An example exam."`
	ExamTime    time.Time `json:"exam_time" example:"auto"`
}

ExamRequest is the request payload for exam management.

func (*ExamRequest) Bind

func (body *ExamRequest) Bind(r *http.Request) error

Bind preprocesses a ExamRequest.

func (*ExamRequest) Validate

func (body *ExamRequest) Validate() error

type ExamResource

type ExamResource struct {
	Stores *Stores
}

ExamResource specifies exam management handler.

func NewExamResource

func NewExamResource(stores *Stores) *ExamResource

NewExamResource create and returns a ExamResource.

func (*ExamResource) Context

func (rs *ExamResource) Context(next http.Handler) http.Handler

Context middleware is used to load an Exam object from the URL parameter `examID` passed through as the request. In case the Exam could not be found, we stop here and return a 404. We do NOT check whether the exam is authorized to get this exam.

func (*ExamResource) CreateHandler

func (rs *ExamResource) CreateHandler(w http.ResponseWriter, r *http.Request)

CreateHandler is public endpoint for URL: /courses/{course_id}/exams URLPARAM: course_id,integer METHOD: post TAG: exams REQUEST: ExamRequest RESPONSE: 204,ExamResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: create a new exam

func (*ExamResource) DeleteHandler

func (rs *ExamResource) DeleteHandler(w http.ResponseWriter, r *http.Request)

DeleteHandler is public endpoint for URL: /courses/{course_id}/exams/{exam_id} URLPARAM: course_id,integer URLPARAM: exam_id,integer METHOD: delete TAG: exams RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: delete a specific exam

func (*ExamResource) DisenrollExamHandler

func (rs *ExamResource) DisenrollExamHandler(w http.ResponseWriter, r *http.Request)

DisenrollExamHandler is public endpoint for URL: /courses/{course_id}/exams/{exam_id}/enrollments URLPARAM: course_id,integer URLPARAM: exam_id,integer METHOD: delete TAG: exams RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: disenroll a user from a exam

func (*ExamResource) EditHandler

func (rs *ExamResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /courses/{course_id}/exams/{exam_id} URLPARAM: course_id,integer URLPARAM: exam_id,integer METHOD: put TAG: exams REQUEST: ExamResponse RESPONSE: 204,NotContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: update a specific exam

func (*ExamResource) EnrollExamHandler

func (rs *ExamResource) EnrollExamHandler(w http.ResponseWriter, r *http.Request)

EnrollExamHandler is public endpoint for URL: /courses/{course_id}/exams/{exam_id}/enrollments URLPARAM: course_id,integer URLPARAM: exam_id,integer METHOD: post TAG: exams REQUEST: Empty RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: enroll a user into a exam

func (*ExamResource) GetExamEnrollmentsHandler

func (rs *ExamResource) GetExamEnrollmentsHandler(w http.ResponseWriter, r *http.Request)

GetExamEnrollmentsHandler is public endpoint for URL: /courses/{course_id}/exams/{exam_id}/enrollments URLPARAM: course_id,integer URLPARAM: exam_id,integer METHOD: get TAG: exams RESPONSE: 200,ExamEnrollmentResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Retrieve the specific account avatar from the request identity This lists all course enrollments of the request identity including role.

func (*ExamResource) GetHandler

func (rs *ExamResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /courses/{course_id}/exams/{exam_id} URLPARAM: course_id,integer URLPARAM: exam_id,integer METHOD: get TAG: exams RESPONSE: 200,ExamResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get a specific exam

func (*ExamResource) IndexHandler

func (rs *ExamResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses/{course_id}/exams METHOD: get TAG: exams RESPONSE: 200,ExamResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: list all exams

func (*ExamResource) UpdateEnrollExamHandler

func (rs *ExamResource) UpdateEnrollExamHandler(w http.ResponseWriter, r *http.Request)

UpdateEnrollExamHandler is public endpoint for URL: /courses/{course_id}/exams/{exam_id}/enrollments URLPARAM: course_id,integer URLPARAM: exam_id,integer METHOD: put TAG: exams REQUEST: UserExamRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: enroll a user into a exam

type ExamResponse

type ExamResponse struct {
	ID          int64     `json:"id" example:"1"`
	Name        string    `json:"name" example:"Info2"`
	Description string    `json:"description" example:"Some course description here"`
	ExamTime    time.Time `json:"exam_time" example:"auto"`
	CourseID    int64     `json:"course_id" example:"1"`
}

ExamResponse is the response payload for course management.

func (*ExamResponse) Render

func (body *ExamResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a ExamResponse.

type ExamStore

type ExamStore interface {
	Get(examID int64) (*model.Exam, error)
	ExamsOfCourse(courseID int64) ([]model.Exam, error)
	GetAll() ([]model.Exam, error)
	Create(p *model.Exam) (*model.Exam, error)
	Update(p *model.Exam) error
	Delete(examID int64) error
	Enroll(examID int64, userID int64) error
	Disenroll(examID int64, userID int64) error
	GetEnrollmentsOfUser(userID int64) ([]model.UserExam, error)
	GetEnrollmentsInCourseOfExam(courseID int64, examID int64) ([]model.UserExam, error)
	GetEnrollmentOfUser(examID int64, userID int64) (*model.UserExam, error)
	UpdateUserExam(p *model.UserExam) error
}

ExamStore defines exam related database queries

type GradeFromWorkerRequest

type GradeFromWorkerRequest struct {
	Log        string               `json:"log" example:"failed in line ..."`
	Status     symbol.TestingResult `json:"status" example:"1"`
	EnqueuedAt time.Time            `json:"enqueued_at"`
	StartedAt  time.Time            `json:"started_at"`
	FinishedAt time.Time            `json:"finished_at"`
}

GradeFromWorkerRequest represents the request a backendwork will sent after completion.

func (*GradeFromWorkerRequest) Bind

func (body *GradeFromWorkerRequest) Bind(r *http.Request) error

Bind preprocesses a GradeRequest.

func (*GradeFromWorkerRequest) Validate

func (body *GradeFromWorkerRequest) Validate() error

Validate validates an incoming GradeFromWorkerRequest.

type GradeOverviewResponse

type GradeOverviewResponse struct {
	Sheets       []SheetInfo       `json:"sheets" example:""`
	Achievements []AchievementInfo `json:"achievements" example:""`
}

GradeOverviewResponse captures the summary for all grades over all sheets for a subset of users.

func (*GradeOverviewResponse) Render

Render post-processes a GradeOverviewResponse.

type GradeRequest

type GradeRequest struct {
	// SubmissionID   int64  `json:"submission_id"`
	AcquiredPoints int    `json:"acquired_points" example:"13"`
	Feedback       string `json:"feedback" example:"Das war gut"`
}

GradeRequest is the request payload for submission management. This will mostly handle the Feedback from tutors. Other changes like execution state will be handle internally and is not user-facing.

func (*GradeRequest) Bind

func (body *GradeRequest) Bind(r *http.Request) error

Bind preprocesses a GradeRequest.

func (*GradeRequest) Validate

func (body *GradeRequest) Validate() error

Validate validates an incoming GradeRequest.

type GradeResource

type GradeResource struct {
	Stores *Stores
}

GradeResource specifies Grade management handler.

func NewGradeResource

func NewGradeResource(stores *Stores) *GradeResource

NewGradeResource create and returns a GradeResource.

func (*GradeResource) Context

func (rs *GradeResource) Context(next http.Handler) http.Handler

Context middleware is used to load an Grade object from the URL parameter `TaskID` passed through as the request. In case the Grade could not be found, we stop here and return a 404. We do NOT check whether the identity is authorized to get this Grade.

func (*GradeResource) EditHandler

func (rs *GradeResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /courses/{course_id}/grades/{grade_id} URLPARAM: course_id,integer URLPARAM: grade_id,integer METHOD: put TAG: grades REQUEST: GradeRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: edit a grade

func (*GradeResource) GetByIDHandler

func (rs *GradeResource) GetByIDHandler(w http.ResponseWriter, r *http.Request)

GetByIDHandler is public endpoint for URL: /courses/{course_id}/grades/{grade_id} URLPARAM: course_id,integer URLPARAM: grade_id,integer METHOD: get TAG: grades RESPONSE: 200,GradeResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get a grade

func (*GradeResource) IndexHandler

func (rs *GradeResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses/{course_id}/grades URLPARAM: course_id,integer QUERYPARAM: sheet_id,integer QUERYPARAM: task_id,integer QUERYPARAM: group_id,integer QUERYPARAM: user_id,integer QUERYPARAM: tutor_id,integer QUERYPARAM: feedback,string QUERYPARAM: acquired_points,integer QUERYPARAM: public_test_status,integer QUERYPARAM: private_test_status,integer QUERYPARAM: public_execution_state,integer QUERYPARAM: private_execution_state,integer METHOD: get TAG: grades RESPONSE: 200,GradeResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: Query grades in a course

func (*GradeResource) IndexMissingHandler

func (rs *GradeResource) IndexMissingHandler(w http.ResponseWriter, r *http.Request)

IndexMissingHandler is public endpoint for URL: /courses/{course_id}/grades/missing URLPARAM: course_id,integer QUERYPARAM: group_id,integer METHOD: get TAG: grades RESPONSE: 200,MissingGradeResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: the missing grades for the request identity

func (*GradeResource) IndexSummaryHandler

func (rs *GradeResource) IndexSummaryHandler(w http.ResponseWriter, r *http.Request)

IndexSummaryHandler is public endpoint for URL: /courses/{course_id}/grades/summary URLPARAM: course_id,integer QUERYPARAM: group_id,integer METHOD: get TAG: grades RESPONSE: 200,GradeOverviewResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: Query grades in a course DESCRIPTION: {"sheets":[{"id":179,"name":"1"},{"id":180,"name":"2"}],"achievements":[{"user_info":{"id":42,"first_name":"Sören","last_name":"Haase","student_number":"1161"},"points":[5,0]},{"user_info":{"id":43,"first_name":"Resi","last_name":"Naser","student_number":"1000"},"points":[8,7]}]}

func (*GradeResource) PrivateResultEditHandler

func (rs *GradeResource) PrivateResultEditHandler(w http.ResponseWriter, r *http.Request)

PrivateResultEditHandler is public endpoint for URL: /courses/{course_id}/grades/{grade_id}/private_result URLPARAM: course_id,integer URLPARAM: grade_id,integer METHOD: post TAG: internal REQUEST: GradeFromWorkerRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: update information for grade from background worker

func (*GradeResource) PublicResultEditHandler

func (rs *GradeResource) PublicResultEditHandler(w http.ResponseWriter, r *http.Request)

PublicResultEditHandler is public endpoint for URL: /courses/{course_id}/grades/{grade_id}/public_result URLPARAM: course_id,integer URLPARAM: grade_id,integer METHOD: post TAG: internal REQUEST: GradeFromWorkerRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: update information for grade from background worker

type GradeResponse

type GradeResponse struct {
	ID                    int64     `json:"id" example:"1"`
	UpdatedAt             time.Time `json:"updated_at" example:""`
	PublicExecutionState  int       `json:"public_execution_state" example:"1"`
	PrivateExecutionState int       `json:"private_execution_state" example:"1"`
	PublicTestLog         string    `json:"public_test_log" example:"Lorem Ipsum"`
	PrivateTestLog        string    `json:"private_test_log" example:"Lorem Ipsum"`
	PublicTestStatus      int       `json:"public_test_status" example:"1"`
	PrivateTestStatus     int       `json:"private_test_status" example:"0"`
	AcquiredPoints        int       `json:"acquired_points" example:"19"`
	Feedback              string    `json:"feedback" example:"Some feedback"`
	TutorID               int64     `json:"tutor_id" example:"2"`
	SubmissionID          int64     `json:"submission_id" example:"31"`
	FileURL               string    `json:"file_url" example:"/api/v1/submissions/61/file"`
	User                  *struct {
		ID        int64  `json:"id" example:"1"`
		FirstName string `json:"first_name" example:"Max"`
		LastName  string `json:"last_name" example:"Mustermensch"`
		Email     string `json:"email" example:"test@unit-tuebingen.de"`
	} `json:"user"`
}

GradeResponse is the response payload for Grade management.

func (*GradeResponse) Render

func (body *GradeResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a GradeResponse.

type GradeStore

type GradeStore interface {
	GetFiltered(
		courseID int64,
		sheetID int64,
		taskID int64,
		groupID int64,
		userID int64,
		tutorID int64,
		feedback string,
		acquiredPoints int,
		publicTestStatus int,
		privateTestStatus int,
		publicExecutationState int,
		privateExecutationState int,
	) ([]model.Grade, error)
	Get(id int64) (*model.Grade, error)
	GetForSubmission(id int64) (*model.Grade, error)
	Update(p *model.Grade) error
	IdentifyCourseOfGrade(gradeID int64) (*model.Course, error)
	GetAllMissingGrades(courseID int64, tutorID int64, groupID int64) ([]model.MissingGrade, error)
	Create(p *model.Grade) (*model.Grade, error)

	UpdatePrivateTestInfo(gradeID int64, log string, status symbol.TestingResult) error
	UpdatePublicTestInfo(gradeID int64, log string, status symbol.TestingResult) error
	IdentifyTaskOfGrade(gradeID int64) (*model.Task, error)
	GetOverviewGrades(courseID int64, groupID int64) ([]model.OverviewGrade, error)
}

GradeStore defines grades related database queries

type GroupBidRequest

type GroupBidRequest struct {
	Bid int `json:"bid" example:"5" minval:"0" maxval:"10"`
}

func (*GroupBidRequest) Bind

func (body *GroupBidRequest) Bind(r *http.Request) error

Bind preprocesses a GroupBidRequest.

func (*GroupBidRequest) Validate

func (body *GroupBidRequest) Validate() error

type GroupBidResponse

type GroupBidResponse struct {
	Bid int `json:"bid" example:"4" minval:"0" maxval:"10"`
}

GroupBidResponse returns the preference of a user to a exercise group

func (*GroupBidResponse) Render

func (body *GroupBidResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a GroupResponse.

type GroupBidsResponse

type GroupBidsResponse struct {
	ID      int64 `json:"id" example:"512"`
	UserID  int64 `json:"user_id" example:"112"`
	GroupID int64 `json:"group_id" example:"2"`
	Bid     int   `json:"bid" example:"6" minval:"0" maxval:"10"`
}

.............................................................................

func (*GroupBidsResponse) Render

func (body *GroupBidsResponse) Render(w http.ResponseWriter, r *http.Request) error

Render postprocesses a GroupBidsResponse before marshalling to JSON.

type GroupEnrollmentRequest

type GroupEnrollmentRequest struct {
	UserID int64 `json:"user_id" example:"15"`
}

GroupRequest is the request payload for course management.

func (*GroupEnrollmentRequest) Bind

func (body *GroupEnrollmentRequest) Bind(r *http.Request) error

Bind preprocesses a GroupRequest.

func (*GroupEnrollmentRequest) Validate

func (body *GroupEnrollmentRequest) Validate() error

type GroupRequest

type GroupRequest struct {
	// note, we will only use the id
	Tutor *struct {
		ID int64 `json:"id" example:"1"`
	} `json:"tutor"`
	// CourseID    int64  `json:"course_id"`
	Description string `json:"description" example:"Gruppe fuer ersties am Montag im Raum C25435"`
}

GroupRequest is the request payload for course management.

func (*GroupRequest) Bind

func (body *GroupRequest) Bind(r *http.Request) error

Bind preprocesses a GroupRequest.

func (*GroupRequest) Validate

func (body *GroupRequest) Validate() error

type GroupResource

type GroupResource struct {
	Stores *Stores
}

GroupResource specifies Group management handler.

func NewGroupResource

func NewGroupResource(stores *Stores) *GroupResource

NewGroupResource create and returns a GroupResource.

func (*GroupResource) ChangeBidHandler

func (rs *GroupResource) ChangeBidHandler(w http.ResponseWriter, r *http.Request)

ChangeBidHandler is public endpoint for URL: /courses/{course_id}/groups/{group_id}/bids URLPARAM: course_id,integer URLPARAM: group_id,integer METHOD: post TAG: groups REQUEST: GroupBidRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: change or add the bid for enrolling in a group

func (*GroupResource) Context

func (rs *GroupResource) Context(next http.Handler) http.Handler

Context middleware is used to load an group object from the URL parameter `TaskID` passed through as the request. In case the group could not be found, we stop here and return a 404. We do NOT check whether the identity is authorized to get this group.

func (*GroupResource) CreateHandler

func (rs *GroupResource) CreateHandler(w http.ResponseWriter, r *http.Request)

CreateHandler is public endpoint for URL: /courses/{course_id}/groups URLPARAM: course_id,integer METHOD: post TAG: groups REQUEST: GroupRequest RESPONSE: 204,SheetResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: create a new group

func (*GroupResource) DeleteHandler

func (rs *GroupResource) DeleteHandler(w http.ResponseWriter, r *http.Request)

DeleteHandler is public endpoint for URL: /courses/{course_id}/groups/{group_id} URLPARAM: course_id,integer URLPARAM: group_id,integer METHOD: delete TAG: groups RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: delete a specific group

func (*GroupResource) EditGroupEnrollmentHandler

func (rs *GroupResource) EditGroupEnrollmentHandler(w http.ResponseWriter, r *http.Request)

EditGroupEnrollmentHandler is public endpoint for URL: /courses/{course_id}/groups/{group_id}/enrollments URLPARAM: course_id,integer URLPARAM: group_id,integer METHOD: post TAG: groups REQUEST: GroupEnrollmentRequest RESPONSE: 204,NotContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: will assign a given user to a group or change the group assignment

func (*GroupResource) EditHandler

func (rs *GroupResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /courses/{course_id}/groups/{group_id} URLPARAM: course_id,integer URLPARAM: group_id,integer METHOD: put TAG: groups REQUEST: GroupRequest RESPONSE: 204,NotContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: update a specific group

func (*GroupResource) GetHandler

func (rs *GroupResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /courses/{course_id}/groups/{group_id} URLPARAM: course_id,integer URLPARAM: group_id,integer METHOD: get TAG: groups RESPONSE: 200,GroupResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get a specific group

func (*GroupResource) GetMineHandler

func (rs *GroupResource) GetMineHandler(w http.ResponseWriter, r *http.Request)

GetMineHandler is public endpoint for URL: /courses/{course_id}/groups/own URLPARAM: course_id,integer METHOD: get TAG: groups RESPONSE: 200,GroupResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the group the request identity is enrolled in

func (*GroupResource) IndexEnrollmentsHandler

func (rs *GroupResource) IndexEnrollmentsHandler(w http.ResponseWriter, r *http.Request)

IndexEnrollmentsHandler is public endpoint for URL: /courses/{course_id}/groups/{group_id}/enrollments URLPARAM: course_id,integer URLPARAM: group_id,integer QUERYPARAM: roles,string QUERYPARAM: first_name,string QUERYPARAM: last_name,string QUERYPARAM: email,string QUERYPARAM: subject,string QUERYPARAM: language,string METHOD: get TAG: enrollments RESPONSE: 200,EnrollmentResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: list all courses

func (*GroupResource) IndexHandler

func (rs *GroupResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses/{course_id}/groups URLPARAM: course_id,integer METHOD: get TAG: groups RESPONSE: 200,GroupResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get all groups in course DESCRIPTION: The ordering is abitary

func (*GroupResource) SendEmailHandler

func (rs *GroupResource) SendEmailHandler(w http.ResponseWriter, r *http.Request)

SendEmailHandler is public endpoint for URL: /courses/{course_id}/groups/{group_id}/emails URLPARAM: course_id,integer URLPARAM: group_id,integer METHOD: post TAG: groups TAG: email REQUEST: EmailRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: send email to entire group

type GroupResponse

type GroupResponse struct {
	ID          int64  `json:"id" example:"9841"`
	CourseID    int64  `json:"course_id" example:"1"`
	Description string `json:"description" example:"Group every tuesday in room e43"`

	// userResponse
	Tutor *struct {
		ID        int64       `json:"id" example:"1"`
		FirstName string      `json:"first_name" example:"Max"`
		LastName  string      `json:"last_name" example:"Mustermensch"`
		AvatarURL null.String `json:"avatar_url" example:"/url/to/file"`
		Email     string      `json:"email" example:"test@unit-tuebingen.de"`
		Language  string      `json:"language" example:"en" len:"2"`

		StudentNumber string `json:"student_number" example:"0815"`
		Semester      int    `json:"semester" example:"2" minval:"1"`
		Subject       string `json:"subject" example:"bio informatics"`
		Root          bool   `json:"root" example:"false"`
	} `json:"tutor"`
}

GroupResponse is the response payload for Group management.

func (*GroupResponse) Render

func (body *GroupResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a GroupResponse.

type GroupStore

type GroupStore interface {
	Get(groupID int64) (*model.Group, error)
	GetAll() ([]model.Group, error)
	Create(p *model.Group) (*model.Group, error)
	Update(p *model.Group) error
	Delete(taskID int64) error
	// GroupsOfCourse(courseID int64) ([]model.Group, error)
	GroupsOfCourse(courseID int64) ([]model.GroupWithTutor, error)
	GetInCourseWithUser(userID int64, courseID int64) ([]model.GroupWithTutor, error)
	GetMembers(groupID int64) ([]model.User, error)
	GetOfTutor(tutorID int64, courseID int64) ([]model.GroupWithTutor, error)
	IdentifyCourseOfGroup(groupID int64) (*model.Course, error)

	GetBidOfUserForGroup(userID int64, groupID int64) (bid int, err error)
	InsertBidOfUserForGroup(userID int64, groupID int64, bid int) (int, error)
	UpdateBidOfUserForGroup(userID int64, groupID int64, bid int) (int, error)

	GetBidsForCourseForUser(courseID int64, userID int64) ([]model.GroupBid, error)
	GetBidsForCourse(courseID int64) ([]model.GroupBid, error)

	GetGroupEnrollmentOfUserInCourse(userID int64, courseID int64) (*model.GroupEnrollment, error)
	CreateGroupEnrollmentOfUserInCourse(p *model.GroupEnrollment) (*model.GroupEnrollment, error)
	ChangeGroupEnrollmentOfUserInCourse(p *model.GroupEnrollment) error

	EnrolledUsers(courseID int64, groupID int64, roleFilter []string,
		filterFirstName string, filterLastName string, filterEmail string, filterSubject string,
		filterLanguage string) ([]model.UserCourse, error)
}

GroupStore specifies required database queries for Task management.

type H

type H map[string]interface{}

H is a wrapper for convenience

type LoginRequest

type LoginRequest struct {
	Email         string `json:"email" example:"test@uni-tuebingen.de"`
	PlainPassword string `json:"plain_password" example:"test"`
}

LoginRequest is the request for the login process containing the password and email as identifiers.

func (*LoginRequest) Bind

func (body *LoginRequest) Bind(r *http.Request) error

Bind preprocesses a loginRequest.

type MaterialRequest

type MaterialRequest struct {
	Name         string    `json:"name" example:"Einfuehrung"`
	Kind         int       `json:"kind" example:"1"`
	PublishAt    time.Time `json:"publish_at" example:"auto"`
	LectureAt    time.Time `json:"lecture_at" example:"auto"`
	RequiredRole int       `json:"required_role" example:"1"`
}

MaterialRequest is the request payload for Material management.

func (*MaterialRequest) Bind

func (body *MaterialRequest) Bind(r *http.Request) error

Bind preprocesses a MaterialRequest.

func (*MaterialRequest) Validate

func (body *MaterialRequest) Validate() error

Validate validates a `Material` object.

type MaterialResource

type MaterialResource struct {
	Stores *Stores
}

MaterialResource specifies Material management handler.

func NewMaterialResource

func NewMaterialResource(stores *Stores) *MaterialResource

NewMaterialResource create and returns a MaterialResource.

func (*MaterialResource) ChangeFileHandler

func (rs *MaterialResource) ChangeFileHandler(w http.ResponseWriter, r *http.Request)

ChangeFileHandler is public endpoint for URL: /courses/{course_id}/materials/{material_id}/file URLPARAM: course_id,integer URLPARAM: material_id,integer METHOD: post TAG: materials REQUEST: Zipfile RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: change the zip file of a sheet DESCRIPTION: This endpoint will only support pdf or zip files.

func (*MaterialResource) Context

func (rs *MaterialResource) Context(next http.Handler) http.Handler

Context middleware is used to load an Material object from the URL parameter `MaterialID` passed through as the request. In case the Material could not be found, we stop here and return a 404. We do NOT check whether the Material is authorized to get this Material.

func (*MaterialResource) CreateHandler

func (rs *MaterialResource) CreateHandler(w http.ResponseWriter, r *http.Request)

CreateHandler is public endpoint for URL: /courses/{course_id}/materials URLPARAM: course_id,integer METHOD: post TAG: materials REQUEST: MaterialRequest RESPONSE: 204,MaterialResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: create a new material DESCRIPTION: Kind means 0: slide, 1: supplementary

func (*MaterialResource) DeleteHandler

func (rs *MaterialResource) DeleteHandler(w http.ResponseWriter, r *http.Request)

DeleteHandler is public endpoint for URL: /courses/{course_id}/materials/{material_id} URLPARAM: course_id,integer URLPARAM: material_id,integer METHOD: delete TAG: materials RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: delete a specific material

func (*MaterialResource) EditHandler

func (rs *MaterialResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /courses/{course_id}/materials/{material_id} URLPARAM: course_id,integer URLPARAM: material_id,integer METHOD: put TAG: materials REQUEST: MaterialRequest RESPONSE: 204,NotContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: update a specific material DESCRIPTION: Kind means 0: slide, 1: supplementary

func (*MaterialResource) GetFileHandler

func (rs *MaterialResource) GetFileHandler(w http.ResponseWriter, r *http.Request)

GetFileHandler is public endpoint for URL: /courses/{course_id}/materials/{material_id}/file URLPARAM: course_id,integer URLPARAM: material_id,integer METHOD: get TAG: materials RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the zip file of a material

func (*MaterialResource) GetHandler

func (rs *MaterialResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /courses/{course_id}/materials/{material_id} URLPARAM: course_id,integer URLPARAM: material_id,integer METHOD: get TAG: materials RESPONSE: 200,MaterialResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get a specific material DESCRIPTION: Kind means 0: slide, 1: supplementary

func (*MaterialResource) IndexHandler

func (rs *MaterialResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses/{course_id}/materials URLPARAM: course_id,integer METHOD: get TAG: materials RESPONSE: 200,MaterialResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get all materials in course DESCRIPTION: The materials are ordered by the lecture date. Kind means 0: slide, 1: supplementary

type MaterialResponse

type MaterialResponse struct {
	ID           int64     `json:"id" example:"55"`
	Name         string    `json:"name" example:"Schleifen und Bedingungen"`
	FileURL      string    `json:"file_url" example:"/api/v1/materials/55/file"`
	Kind         int       `json:"kind" example:"0"`
	PublishAt    time.Time `json:"publish_at" example:"auto"`
	LectureAt    time.Time `json:"lecture_at" example:"auto"`
	RequiredRole int       `json:"required_role" example:"1"`
}

MaterialResponse is the response payload for Material management.

func (*MaterialResponse) Render

func (body *MaterialResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a MaterialResponse.

type MaterialStore

type MaterialStore interface {
	Get(sheetID int64) (*model.Material, error)
	Create(p *model.Material, courseID int64) (*model.Material, error)
	Update(p *model.Material) error
	Delete(sheetID int64) error
	MaterialsOfCourse(courseID int64, requiredRole int) ([]model.Material, error)
	IdentifyCourseOfMaterial(sheetID int64) (*model.Course, error)
	GetAll() ([]model.Material, error)
}

MaterialStore defines material related database queries

type MissingGradeResponse

type MissingGradeResponse struct {
	Grade *struct {
		ID                    int64     `json:"id" example:"1"`
		UpdatedAt             time.Time `json:"updated_at" example:""`
		PublicExecutionState  int       `json:"public_execution_state" example:"1"`
		PrivateExecutionState int       `json:"private_execution_state" example:"1"`
		PublicTestLog         string    `json:"public_test_log" example:"Lorem Ipsum"`
		PrivateTestLog        string    `json:"private_test_log" example:"Lorem Ipsum"`
		PublicTestStatus      int       `json:"public_test_status" example:"1"`
		PrivateTestStatus     int       `json:"private_test_status" example:"0"`
		AcquiredPoints        int       `json:"acquired_points" example:"19"`
		Feedback              string    `json:"feedback" example:"Some feedback"`
		TutorID               int64     `json:"tutor_id" example:"2"`
		SubmissionID          int64     `json:"submission_id" example:"31"`
		FileURL               string    `json:"file_url" example:"/api/v1/submissions/61/file"`
		User                  *struct {
			ID        int64  `json:"id" example:"1"`
			FirstName string `json:"first_name" example:"Max"`
			LastName  string `json:"last_name" example:"Mustermensch"`
			Email     string `json:"email" example:"test@unit-tuebingen.de"`
		} `json:"user"`
	} `json:"grade"`
	CourseID int64 `json:"course_id" example:"1"`
	SheetID  int64 `json:"sheet_id" example:"10"`
	TaskID   int64 `json:"task_id" example:"2"`
}

MissingGradeResponse is the response payload for showing tutors which grades are still in the loop. We expect them to write a feedback for all submissions.

func (*MissingGradeResponse) Render

Render post-processes a MissingGradeResponse.

type MissingTaskResponse

type MissingTaskResponse struct {
	Task *struct {
		ID                 int64       `json:"id" example:"684"`
		Name               string      `json:"name" example:"Task 1"`
		MaxPoints          int         `json:"max_points" example:"23"`
		PublicDockerImage  null.String `json:"public_docker_image" example:"DefaultJavaTestingImage"`
		PrivateDockerImage null.String `json:"private_docker_image" example:"DefaultJavaTestingImage"`
	} `json:"task"`
	CourseID int64 `json:"course_id" example:"1"`
	SheetID  int64 `json:"sheet_id" example:"8"`
}

MissingTaskResponse is the response payload for displaying

func (*MissingTaskResponse) Render

Render post-processes a TaskResponse.

type Producer

type Producer interface {
	Publish(body []byte) error
}

Producer is interface to pipe the workload over AMPQ to the backend workers

var DefaultSubmissionProducer Producer

DefaultSubmissionProducer is the producer which broadcasts all submissions amongst the workers.

type RawResponse

type RawResponse struct {
	Text string `json:"text" example:"some text"`
}

RawResponse is the response payload for course management.

func (*RawResponse) Render

func (body *RawResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a RawResponse.

type ResetPasswordRequest

type ResetPasswordRequest struct {
	Email string `json:"email" example:"test@uni-tuebingen.de"`
}

----------------------------------------------------------------------------- ResetPasswordRequest is the request whenever a user forgot his password and wants to receive an email with a new one.

func (*ResetPasswordRequest) Bind

func (body *ResetPasswordRequest) Bind(r *http.Request) error

type SheetInfo

type SheetInfo struct {
	ID   int64  `json:"id" example:"42"`
	Name string `json:"name" example:"sheet 0"`
}

for the swagger build relying on go.ast we need to duplicate code here

type SheetPointsResponse

type SheetPointsResponse struct {
	AquiredPoints    int `json:"acquired_points" example:"58"`
	AchievablePoints int `json:"achievable_points" example:"42"`
	MaxPoints        int `json:"max_points" example:"90"`
	SheetID          int `json:"sheet_id" example:"2"`
}

SheetPointsResponse is response for performance on a specific exercise sheet

func (*SheetPointsResponse) Render

Render postprocesses a SheetPointsResponse before marshalling to JSON.

type SheetRequest

type SheetRequest struct {
	Name      string    `json:"name" example:"Blatt 42"`
	PublishAt time.Time `json:"publish_at" example:"auto"`
	DueAt     time.Time `json:"due_at" example:"auto"`
}

SheetRequest is the request payload for Sheet management.

func (*SheetRequest) Bind

func (body *SheetRequest) Bind(r *http.Request) error

Bind preprocesses a SheetRequest.

func (*SheetRequest) Validate

func (body *SheetRequest) Validate() error

Validate validates a SheetRequest

type SheetResource

type SheetResource struct {
	Stores *Stores
}

SheetResource specifies Sheet management handler.

func NewSheetResource

func NewSheetResource(stores *Stores) *SheetResource

NewSheetResource create and returns a SheetResource.

func (*SheetResource) ChangeFileHandler

func (rs *SheetResource) ChangeFileHandler(w http.ResponseWriter, r *http.Request)

ChangeFileHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id}/file URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: post TAG: sheets REQUEST: Zipfile RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: change the zip file of a sheet

func (*SheetResource) Context

func (rs *SheetResource) Context(next http.Handler) http.Handler

Context middleware is used to load an Sheet object from the URL parameter `SheetID` passed through as the request. In case the Sheet could not be found, we stop here and return a 404. We do NOT check whether the Sheet is authorized to get this Sheet.

func (*SheetResource) CreateHandler

func (rs *SheetResource) CreateHandler(w http.ResponseWriter, r *http.Request)

CreateHandler is public endpoint for URL: /courses/{course_id}/sheets URLPARAM: course_id,integer METHOD: post TAG: sheets REQUEST: SheetRequest RESPONSE: 204,SheetResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: create a new sheet

func (*SheetResource) DeleteHandler

func (rs *SheetResource) DeleteHandler(w http.ResponseWriter, r *http.Request)

DeleteHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id} URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: delete TAG: sheets RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: delete a specific sheet

func (*SheetResource) EditHandler

func (rs *SheetResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id} URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: put TAG: sheets REQUEST: SheetRequest RESPONSE: 204,NotContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: update a specific sheet

func (*SheetResource) GetFileHandler

func (rs *SheetResource) GetFileHandler(w http.ResponseWriter, r *http.Request)

GetFileHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id}/file URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: get TAG: sheets RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the zip file of a sheet

func (*SheetResource) GetHandler

func (rs *SheetResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id} URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: get TAG: sheets RESPONSE: 200,SheetResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get a specific sheet

func (*SheetResource) IndexHandler

func (rs *SheetResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses/{course_id}/sheets URLPARAM: course_id,integer METHOD: get TAG: sheets RESPONSE: 200,SheetResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get all sheets in course DESCRIPTION: The sheets are ordered by their names

func (*SheetResource) PointsHandler

func (rs *SheetResource) PointsHandler(w http.ResponseWriter, r *http.Request)

PointsHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id}/points URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: get TAG: sheets RESPONSE: 200,NewTaskListResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: return all points from a sheet for the request identity

type SheetResponse

type SheetResponse struct {
	ID        int64     `json:"id" example:"13"`
	Name      string    `json:"name" example:"Blatt 0"`
	FileURL   string    `json:"file_url" example:"/api/v1/sheets/13/file"`
	PublishAt time.Time `json:"publish_at" example:"auto"`
	DueAt     time.Time `json:"due_at" example:"auto"`
}

SheetResponse is the response payload for Sheet management.

func (*SheetResponse) Render

func (body *SheetResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a SheetResponse.

type SheetStore

type SheetStore interface {
	Get(SheetID int64) (*model.Sheet, error)
	Update(p *model.Sheet) error
	GetAll() ([]model.Sheet, error)
	Create(p *model.Sheet, courseID int64) (*model.Sheet, error)
	Delete(SheetID int64) error
	SheetsOfCourse(courseID int64) ([]model.Sheet, error)
	IdentifyCourseOfSheet(sheetID int64) (*model.Course, error)
	PointsForUser(userID int64, sheetID int64) ([]model.TaskPoints, error)
}

SheetStore specifies required database queries for Sheet management.

type Stores

type Stores struct {
	Course     CourseStore
	User       UserStore
	Sheet      SheetStore
	Task       TaskStore
	Group      GroupStore
	Submission SubmissionStore
	Material   MaterialStore
	Grade      GradeStore
	Exam       ExamStore
}

Stores is the collection of stores. We use this struct to express a kind of hierarchy of database queries, e.g. stores.User.Get(1)

func NewStores

func NewStores(db *sqlx.DB) *Stores

NewStores build all stores and connect them to a database.

type SubmissionResource

type SubmissionResource struct {
	Stores    *Stores
	TokenAuth *authenticate.TokenAuth
}

SubmissionResource specifies Submission management handler.

func NewSubmissionResource

func NewSubmissionResource(stores *Stores, tokenAuth *authenticate.TokenAuth) *SubmissionResource

NewSubmissionResource create and returns a SubmissionResource.

func (*SubmissionResource) Context

func (rs *SubmissionResource) Context(next http.Handler) http.Handler

Context middleware is used to load an Submission object from the URL parameter `TaskID` passed through as the request. In case the Submission could not be found, we stop here and return a 404. We do NOT check whether the identity is authorized to get this Submission.

func (*SubmissionResource) GetCollectionFileHandler

func (rs *SubmissionResource) GetCollectionFileHandler(w http.ResponseWriter, r *http.Request)

GetCollectionFileHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/groups/{group_id}/file URLPARAM: course_id,integer URLPARAM: sheet_id,integer URLPARAM: task_id,integer URLPARAM: group_id,integer METHOD: get TAG: submissions RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the zip file containing all submissions for a given task and a given group

func (*SubmissionResource) GetCollectionHandler

func (rs *SubmissionResource) GetCollectionHandler(w http.ResponseWriter, r *http.Request)

GetCollectionHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/groups/{group_id} URLPARAM: course_id,integer URLPARAM: sheet_id,integer URLPARAM: task_id,integer URLPARAM: group_id,integer METHOD: get TAG: submissions RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the path to the zip file containing all submissions for a given task and a given group if exists

func (*SubmissionResource) GetFileByIDHandler

func (rs *SubmissionResource) GetFileByIDHandler(w http.ResponseWriter, r *http.Request)

GetFileByIDHandler is public endpoint for URL: /courses/{course_id}/submissions/{submission_id}/file URLPARAM: course_id,integer URLPARAM: submission_id,integer METHOD: get TAG: submissions RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the zip file of a specific submission

func (*SubmissionResource) GetFileHandler

func (rs *SubmissionResource) GetFileHandler(w http.ResponseWriter, r *http.Request)

GetFileHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/submission URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: get TAG: submissions RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the zip file containing the submission of the request identity for a given task

func (*SubmissionResource) IndexHandler

func (rs *SubmissionResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses/{course_id}/submissions URLPARAM: course_id,integer QUERYPARAM: sheet_id,integer QUERYPARAM: task_id,integer QUERYPARAM: group_id,integer QUERYPARAM: user_id,integer METHOD: get TAG: submissions RESPONSE: 200,SubmissionResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: Query submissions in a course

func (*SubmissionResource) UploadFileHandler

func (rs *SubmissionResource) UploadFileHandler(w http.ResponseWriter, r *http.Request)

UploadFileHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/submission URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: post TAG: submissions REQUEST: Zipfile RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: changes the zip file of a submission belonging to the request identity

type SubmissionResponse

type SubmissionResponse struct {
	ID      int64  `json:"id" example:"61"`
	UserID  int64  `json:"user_id" example:"357"`
	TaskID  int64  `json:"task_id" example:"12"`
	FileURL string `json:"file_url" example:"/api/v1/submissions/61/file"`
}

SubmissionResponse is the response payload for Submission management.

func (*SubmissionResponse) Render

Render post-processes a SubmissionResponse.

type SubmissionStore

type SubmissionStore interface {
	Get(submissionID int64) (*model.Submission, error)
	GetByUserAndTask(userID int64, taskID int64) (*model.Submission, error)
	Create(p *model.Submission) (*model.Submission, error)
	GetFiltered(filterCourseID, filterGroupID, filterUserID, filterSheetID, filterTaskID int64) ([]model.Submission, error)
}

SubmissionStore defines submission related database queries

type TaskPointsResponse

type TaskPointsResponse struct {
	AquiredPoints    int `json:"acquired_points" example:"58"`
	AchievablePoints int `json:"achievable_points" example:"42"`
	MaxPoints        int `json:"max_points" example:"90"`
	TaskID           int `json:"task_id" example:"2"`
}

TaskPointsResponse returns a performance summary for a task and student

func (*TaskPointsResponse) Render

Render post-processes a TaskPointsResponse.

type TaskRatingRequest

type TaskRatingRequest struct {
	Rating int `json:"rating" example:"2"`
}

TaskRatingRequest is the request payload when students give feedback rating

func (*TaskRatingRequest) Bind

func (body *TaskRatingRequest) Bind(r *http.Request) error

Bind preprocesses a TaskRatingRequest.

func (*TaskRatingRequest) Validate

func (body *TaskRatingRequest) Validate() error

Validate validates a TaskRatingRequest.

type TaskRatingResource

type TaskRatingResource struct {
	Stores *Stores
}

TaskRatingResource specifies TaskRating management handler.

func NewTaskRatingResource

func NewTaskRatingResource(stores *Stores) *TaskRatingResource

NewTaskRatingResource create and returns a TaskRatingResource.

func (*TaskRatingResource) ChangeHandler

func (rs *TaskRatingResource) ChangeHandler(w http.ResponseWriter, r *http.Request)

ChangeHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/ratings URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: post TAG: tasks REQUEST: TaskRatingRequest RESPONSE: 200,TaskRatingResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: updates and gets all stats (average rating, own rating, ..) for a task

func (*TaskRatingResource) GetHandler

func (rs *TaskRatingResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/ratings URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: get TAG: tasks RESPONSE: 200,TaskRatingResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get all stats (average rating, own rating, ..) for a task

type TaskRatingResponse

type TaskRatingResponse struct {
	TaskID        int64   `json:"task_id" example:"143"`
	AverageRating float32 `json:"average_rating" example:"3.15"`
	OwnRating     int     `json:"own_rating" example:"4"`
}

TaskRatingResponse is the response payload for TaskRating management.

func (*TaskRatingResponse) Render

Render post-processes a TaskRatingResponse.

type TaskRequest

type TaskRequest struct {
	MaxPoints          int    `json:"max_points" example:"25"`
	Name               string `json:"name" example:"Task 1"`
	PublicDockerImage  string `json:"public_docker_image" example:"DefaultJavaTestingImage"`
	PrivateDockerImage string `json:"private_docker_image" example:"DefaultJavaTestingImage"`
}

TaskRequest is the request payload for Task management.

func (*TaskRequest) Bind

func (body *TaskRequest) Bind(r *http.Request) error

Bind preprocesses a TaskRequest.

func (*TaskRequest) Validate

func (body *TaskRequest) Validate() error

Validate validates a TaskRequest.

type TaskResource

type TaskResource struct {
	Stores *Stores
}

TaskResource specifies Task management handler.

func NewTaskResource

func NewTaskResource(stores *Stores) *TaskResource

NewTaskResource create and returns a TaskResource.

func (*TaskResource) ChangePrivateTestFileHandler

func (rs *TaskResource) ChangePrivateTestFileHandler(w http.ResponseWriter, r *http.Request)

ChangePrivateTestFileHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/private_file URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: post TAG: tasks REQUEST: Zipfile RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: change the zip with the testing framework for the private tests

func (*TaskResource) ChangePublicTestFileHandler

func (rs *TaskResource) ChangePublicTestFileHandler(w http.ResponseWriter, r *http.Request)

ChangePublicTestFileHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/public_file URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: post TAG: tasks REQUEST: Zipfile RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: change the zip with the testing framework for the public tests

func (*TaskResource) Context

func (rs *TaskResource) Context(next http.Handler) http.Handler

Context middleware is used to load an Task object from the URL parameter `TaskID` passed through as the request. In case the Task could not be found, we stop here and return a 404. We do NOT check whether the identity is authorized to get this Task.

func (*TaskResource) CreateHandler

func (rs *TaskResource) CreateHandler(w http.ResponseWriter, r *http.Request)

CreateHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id}/tasks URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: post TAG: tasks REQUEST: TaskRequest RESPONSE: 204,TaskResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: create a new task

func (*TaskResource) DeleteHandler

func (rs *TaskResource) DeleteHandler(w http.ResponseWriter, r *http.Request)

DeleteHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id} URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: delete TAG: tasks RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: delete a specific task

func (*TaskResource) EditHandler

func (rs *TaskResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id} URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: put TAG: tasks REQUEST: TaskRequest RESPONSE: 204,NotContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: edit a specific task

func (*TaskResource) GetHandler

func (rs *TaskResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id} URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: get TAG: tasks RESPONSE: 200,TaskResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get a specific task

func (*TaskResource) GetPrivateTestFileHandler

func (rs *TaskResource) GetPrivateTestFileHandler(w http.ResponseWriter, r *http.Request)

GetPrivateTestFileHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/private_file URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: get TAG: tasks RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the zip with the testing framework for the private tests

func (*TaskResource) GetPublicTestFileHandler

func (rs *TaskResource) GetPublicTestFileHandler(w http.ResponseWriter, r *http.Request)

GetPublicTestFileHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/public_file URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: get TAG: tasks RESPONSE: 200,ZipFile RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: get the zip with the testing framework for the public tests

func (*TaskResource) GetSubmissionResultHandler

func (rs *TaskResource) GetSubmissionResultHandler(w http.ResponseWriter, r *http.Request)

GetSubmissionResultHandler is public endpoint for URL: /courses/{course_id}/tasks/{task_id}/result URLPARAM: course_id,integer URLPARAM: task_id,integer METHOD: get TAG: tasks RESPONSE: 200,GradeResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated RESPONSE: 403,Unauthorized SUMMARY: the the public results (grades) for a test and the request identity

func (*TaskResource) IndexHandler

func (rs *TaskResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /courses/{course_id}/sheets/{sheet_id}/tasks URLPARAM: course_id,integer URLPARAM: sheet_id,integer METHOD: get TAG: tasks RESPONSE: 200,TaskResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Get all tasks of a given sheet

func (*TaskResource) MissingIndexHandler

func (rs *TaskResource) MissingIndexHandler(w http.ResponseWriter, r *http.Request)

MissingIndexHandler is public endpoint for URL: /courses/{course_id}/tasks/missing URLPARAM: course_id,integer METHOD: get TAG: tasks RESPONSE: 200,MissingTaskResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Get all tasks which are not solved by the request identity

type TaskResponse

type TaskResponse struct {
	ID                 int64       `json:"id" example:"684"`
	Name               string      `json:"name" example:"Task 1"`
	MaxPoints          int         `json:"max_points" example:"23"`
	PublicDockerImage  null.String `json:"public_docker_image" example:"DefaultJavaTestingImage"`
	PrivateDockerImage null.String `json:"private_docker_image" example:"DefaultJavaTestingImage"`
}

TaskResponse is the response payload for Task management.

func (*TaskResponse) Render

func (body *TaskResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a TaskResponse.

type TaskStore

type TaskStore interface {
	Get(TaskID int64) (*model.Task, error)
	Update(p *model.Task) error
	GetAll() ([]model.Task, error)
	Create(p *model.Task, sheetID int64) (*model.Task, error)
	Delete(TaskID int64) error
	TasksOfSheet(sheetID int64) ([]model.Task, error)
	IdentifyCourseOfTask(taskID int64) (*model.Course, error)
	IdentifySheetOfTask(taskID int64) (*model.Sheet, error)

	GetAverageRating(taskID int64) (float32, error)
	GetRatingOfTaskByUser(taskID int64, userID int64) (*model.TaskRating, error)
	GetRating(taskRatingID int64) (*model.TaskRating, error)
	CreateRating(p *model.TaskRating) (*model.TaskRating, error)
	UpdateRating(p *model.TaskRating) error
	GetAllMissingTasksForUser(userID int64) ([]model.MissingTask, error)
}

TaskStore specifies required database queries for Task management.

type UpdatePasswordRequest

type UpdatePasswordRequest struct {
	Email              string `json:"email" example:"test@uni-tuebingen.de"`
	ResetPasswordToken string `json:"reset_password_token" example:"SDFOI34FZH4HUFH"`
	PlainPassword      string `json:"plain_password" example:"test"`
}

UpdatePasswordRequest is the request for a password reset.

func (*UpdatePasswordRequest) Bind

func (body *UpdatePasswordRequest) Bind(r *http.Request) error

Bind preprocesses a UpdatePasswordRequest.

type UserEnrollmentResponse

type UserEnrollmentResponse struct {
	ID       int64 `json:"id" example:"31"`
	CourseID int64 `json:"course_id" example:"1"`
	Role     int64 `json:"role" example:"1"`
}

UserEnrollmentResponse is the response payload for account management.

func (*UserEnrollmentResponse) Render

Render post-processes a userAccountCreatedResponse.

type UserExamRequest

type UserExamRequest struct {
	Status int    `json:"status" example:"1"`
	Mark   string `json:"mark" example:"1"`
	UserID int64  `json:"user_id" example:"42"`
}

ExamRequest is the request payload for exam management.

func (*UserExamRequest) Bind

func (body *UserExamRequest) Bind(r *http.Request) error

Bind preprocesses a ExamRequest.

func (*UserExamRequest) Validate

func (body *UserExamRequest) Validate() error

type UserInfo

type UserInfo struct {
	ID            int64  `json:"id" example:"42"`
	FirstName     string `json:"first_name" example:"max"`
	LastName      string `json:"last_name" example:"mustermensch"`
	StudentNumber string `json:"student_number" example:"0815"`
	Email         string `json:"email" example:"user@example.com"`
}

type UserMeRequest

type UserMeRequest struct {
	FirstName string `json:"first_name" example:"Max"`
	LastName  string `json:"last_name" example:"Mustermensch"`
	// Email         string `json:"email" example:"test@unit-tuebingen.de"`
	StudentNumber string `json:"student_number" example:"0815"`
	Semester      int    `json:"semester" example:"2" minval:"1"`
	Subject       string `json:"subject" example:"bio informatics"`
	Language      string `json:"language" example:"en" len:"2"`
}

UserMeRequest is the request payload for user management.

func (*UserMeRequest) Bind

func (body *UserMeRequest) Bind(r *http.Request) error

Bind preprocesses a UserMeRequest.

func (*UserMeRequest) Validate

func (body *UserMeRequest) Validate() error

type UserRequest

type UserRequest struct {
	FirstName     string `json:"first_name" example:"Max"`
	LastName      string `json:"last_name" example:"Mustermensch"`
	Email         string `json:"email" example:"test@unit-tuebingen.de"`
	StudentNumber string `json:"student_number" example:"0815"`
	Semester      int    `json:"semester" example:"2" minval:"1"`
	Subject       string `json:"subject" example:"bio informatics"`
	Language      string `json:"language" example:"en" len:"2"`
	PlainPassword string `json:"plain_password" example:"new_password" required:"false"`
}

UserRequest is the request payload for user management.

func (*UserRequest) Bind

func (body *UserRequest) Bind(r *http.Request) error

Bind preprocesses a UserRequest.

func (*UserRequest) Validate

func (body *UserRequest) Validate() error

type UserResource

type UserResource struct {
	Stores *Stores
}

UserResource specifies user management handler.

func NewUserResource

func NewUserResource(stores *Stores) *UserResource

NewUserResource create and returns a UserResource.

func (*UserResource) Context

func (rs *UserResource) Context(next http.Handler) http.Handler

Context middleware is used to load an User object from the URL parameter `userID` passed through as the request. In case the User could not be found, we stop here and return a 404. We do NOT check whether the user is authorized to get this user.

func (*UserResource) DeleteHandler

func (rs *UserResource) DeleteHandler(w http.ResponseWriter, r *http.Request)

DeleteHandler is public endpoint for URL: /users/{user_id} URLPARAM: user_id,integer METHOD: delete TAG: users REQUEST: UserRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: updating a specific user with given id.

func (*UserResource) EditHandler

func (rs *UserResource) EditHandler(w http.ResponseWriter, r *http.Request)

EditHandler is public endpoint for URL: /users/{user_id} URLPARAM: user_id,integer METHOD: put TAG: users REQUEST: UserRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: updating a specific user with given id.

func (*UserResource) EditMeHandler

func (rs *UserResource) EditMeHandler(w http.ResponseWriter, r *http.Request)

EditMeHandler is public endpoint for URL: /me METHOD: put TAG: users REQUEST: UserMeRequest RESPONSE: 204,NoContent RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: updating a the user record of the request identity

func (*UserResource) Find

func (rs *UserResource) Find(w http.ResponseWriter, r *http.Request)

Find is public endpoint for URL: /users/find QUERYPARAM: query,string METHOD: get TAG: users RESPONSE: 200,UserResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Query a specific user

func (*UserResource) GetAvatarHandler

func (rs *UserResource) GetAvatarHandler(w http.ResponseWriter, r *http.Request)

GetAvatarHandler is public endpoint for URL: /users/{user_id}/avatar URLPARAM: user_id,integer METHOD: get TAG: users RESPONSE: 200,UserResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Get user details

func (*UserResource) GetHandler

func (rs *UserResource) GetHandler(w http.ResponseWriter, r *http.Request)

GetHandler is public endpoint for URL: /users/{user_id} URLPARAM: user_id,integer METHOD: get TAG: users RESPONSE: 200,UserResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Get user details

func (*UserResource) GetMeHandler

func (rs *UserResource) GetMeHandler(w http.ResponseWriter, r *http.Request)

GetMeHandler is public endpoint for URL: /me METHOD: get TAG: users RESPONSE: 200,UserResponse RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Get own user details

func (*UserResource) IndexHandler

func (rs *UserResource) IndexHandler(w http.ResponseWriter, r *http.Request)

IndexHandler is public endpoint for URL: /users METHOD: get TAG: users RESPONSE: 200,UserResponseList RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: Get own user details (requires root)

func (*UserResource) SendEmailHandler

func (rs *UserResource) SendEmailHandler(w http.ResponseWriter, r *http.Request)

SendEmailHandler is public endpoint for URL: /users/{user_id}/emails URLPARAM: user_id,integer METHOD: post TAG: users TAG: email REQUEST: EmailRequest RESPONSE: 200,OK RESPONSE: 400,BadRequest RESPONSE: 401,Unauthenticated SUMMARY: send email to a specific user

type UserResponse

type UserResponse struct {
	ID            int64       `json:"id" example:"1"`
	FirstName     string      `json:"first_name" example:"Max"`
	LastName      string      `json:"last_name" example:"Mustermensch"`
	AvatarURL     null.String `json:"avatar_url" example:"/url/to/file"`
	Email         string      `json:"email" example:"test@unit-tuebingen.de"`
	StudentNumber string      `json:"student_number" example:"0815"`
	Semester      int         `json:"semester" example:"2" minval:"1"`
	Subject       string      `json:"subject" example:"bio informatics"`
	Language      string      `json:"language" example:"en" len:"2"`
	Root          bool        `json:"root" example:"false"`
}

UserResponse is the response payload for user management.

func (*UserResponse) Render

func (u *UserResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a UserResponse.

type UserStore

type UserStore interface {
	Get(userID int64) (*model.User, error)
	Update(p *model.User) error
	GetAll() ([]model.User, error)
	Create(p *model.User) (*model.User, error)
	Delete(userID int64) error
	FindByEmail(email string) (*model.User, error)
	Find(query string) ([]model.User, error)
	GetEnrollments(userID int64) ([]model.Enrollment, error)
}

UserStore defines user related database queries

type VersionResponse

type VersionResponse struct {
	Commit  string `json:"commit" example:"d725269a8a7498aae1dbb07786bed4c88b002661"`
	Version string `json:"version" example:"1"`
}

VersionResponse is the response payload for course management.

func (*VersionResponse) Render

func (body *VersionResponse) Render(w http.ResponseWriter, r *http.Request) error

Render post-processes a VersionResponse.

type VoidProducer

type VoidProducer struct{}

VoidProducer acts like a real producer, but will not trigger any background worker if you do not need these or within tests

func (*VoidProducer) Publish

func (t *VoidProducer) Publish(body []byte) error

Publish of VoidProducer does nothing on purpose (used in unit tests).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL