shared/api/endpoints/course.rs
1//! Endpoints for Course
2use crate::domain::course::{CourseAdminDataUpdatePath, CourseUpdateAdminDataRequest};
3use crate::{
4 api::Method,
5 domain::{
6 course::{
7 CourseBrowsePath, CourseBrowseQuery, CourseBrowseResponse, CourseClonePath,
8 CourseCreatePath, CourseCreateRequest, CourseDeletePath, CourseGetDraftPath,
9 CourseGetLivePath, CourseId, CoursePlayPath, CoursePublishPath, CourseResponse,
10 CourseSearchPath, CourseSearchQuery, CourseSearchResponse, CourseUpdateDraftDataPath,
11 CourseUpdateDraftDataRequest,
12 },
13 CreateResponse,
14 },
15 error::{EmptyError, MetadataNotFound},
16};
17
18pub mod unit;
19
20use super::ApiEndpoint;
21
22/// Create a Course and it's draft and live data copies.
23///
24/// * New Courses are all set to `PrivacyLevel::Unlisted` by default
25///
26/// # Flow:
27/// 1. Create a Course and its two data copies with [`Create`]
28/// 2. Optionally update Course info such as privacy, author with [`Update`]
29/// 3. Make updates to draft data:
30/// a. Patch Course data through [`UpdateDraftData`]
31
32/// 4. Finalize draft changes by calling [`Publish`]
33///
34/// # Authorization
35/// * TokenUser
36/// * One of `Admin`, `AdminAsset`, or `ManageSelfAsset`
37pub struct Create;
38impl ApiEndpoint for Create {
39 type Req = CourseCreateRequest;
40 type Res = CreateResponse<CourseId>;
41 type Path = CourseCreatePath;
42 type Err = MetadataNotFound;
43 const METHOD: Method = Method::Post;
44}
45
46/// Get a Course's live data by ID.
47///
48/// # Authorization
49/// * Creator ID of Course
50/// * One of `Admin`, `AdminAsset`,, or `ManageSelfAsset` for owned Courses
51///
52/// # Errors
53///
54pub struct GetLive;
55impl ApiEndpoint for GetLive {
56 type Req = ();
57 type Res = CourseResponse;
58 type Path = CourseGetLivePath;
59 type Err = EmptyError;
60 const METHOD: Method = Method::Get;
61}
62
63/// Get a Course's draft data by ID.
64///
65/// # Authorization
66/// * Creator ID of Course
67/// * One of `Admin`, `AdminAsset`,, or `ManageSelfAsset` for owned Courses
68///
69/// # Errors
70/// * [`Unauthorized`](http::StatusCode::UNAUTHORIZED) if authorization is not valid.
71///
72pub struct GetDraft;
73impl ApiEndpoint for GetDraft {
74 type Req = ();
75 type Res = CourseResponse;
76 type Path = CourseGetDraftPath;
77 type Err = EmptyError;
78 const METHOD: Method = Method::Get;
79}
80
81/// Update the draft data of a Course.
82///
83/// Note that a copy of the Course's draft or live data can not be fetched directly, but only as a part
84/// of one of the following routes:
85/// * [`GetLive`] fetches live copies
86/// * [`Search`]
87///
88/// See [`Course Data`](crate::domain::course::CourseData) for the over-the-wire representation.
89///
90/// # Authorization
91/// * One of `Admin`, `AdminAsset`, or `ManageSelfAsset` for owned Courses
92pub struct UpdateDraftData;
93impl ApiEndpoint for UpdateDraftData {
94 type Req = CourseUpdateDraftDataRequest;
95 type Res = ();
96 type Path = CourseUpdateDraftDataPath;
97 type Err = MetadataNotFound;
98 const METHOD: Method = Method::Patch;
99}
100
101/// Publish a Course draft to live by copying over the Coursedata.
102///
103/// # Authorization
104/// * Creator ID of Course
105/// * One of `Admin`, `AdminAsset`, or `ManageSelfAsset`
106pub struct Publish;
107impl ApiEndpoint for Publish {
108 type Req = ();
109 type Res = ();
110 type Path = CoursePublishPath;
111 type Err = EmptyError;
112 const METHOD: Method = Method::Put;
113}
114
115/// Browse Courses. Returns the draft data copies in the response.
116///
117/// # Authorization
118/// * None
119pub struct Browse;
120impl ApiEndpoint for Browse {
121 type Req = CourseBrowseQuery;
122 type Res = CourseBrowseResponse;
123 type Path = CourseBrowsePath;
124 type Err = EmptyError;
125 const METHOD: Method = Method::Get;
126}
127
128/// Search for Courses.
129///
130/// # Authorization
131/// * None
132pub struct Search;
133impl ApiEndpoint for Search {
134 type Req = CourseSearchQuery;
135 type Res = CourseSearchResponse;
136 type Path = CourseSearchPath;
137 type Err = EmptyError;
138 const METHOD: Method = Method::Get;
139}
140
141/// Delete a Course.
142///
143/// # Authorization
144/// * Creator ID of Course
145/// * One of `Admin`, `AdminAsset`, or `ManageSelfAsset` for owned Courses
146pub struct Delete;
147impl ApiEndpoint for Delete {
148 type Req = ();
149 type Res = ();
150 type Path = CourseDeletePath;
151 type Err = EmptyError;
152 const METHOD: Method = Method::Delete;
153}
154
155/// Clone a Course. This clones both the draft and live.
156///
157/// # Authorization
158/// * One of `Admin`, `AdminAsset`, or `ManageSelfAsset`
159///
160/// # Errors
161/// * [`Unauthorized`](http::StatusCode::UNAUTHORIZED) if authorization is not valid.
162/// * [`Forbidden`](http::StatusCode::FORBIDDEN) if the user does not have sufficient permission to perform the action.
163/// * ['NotFound'](http::StatusCode::NOT_FOUND) if the resource does not exist.
164/// * ['BadRequest'](http::StatusCode::BAD_REQUEST) if the request is malformed or the Course is a draft.
165pub struct Clone;
166impl ApiEndpoint for Clone {
167 type Path = CourseClonePath;
168 type Req = ();
169 type Res = CreateResponse<CourseId>;
170 type Err = EmptyError;
171 const METHOD: Method = Method::Post;
172}
173
174/// Add to play count for a Course
175///
176/// # Authorization
177/// * None
178pub struct Play;
179impl ApiEndpoint for Play {
180 type Req = ();
181 type Res = ();
182 type Path = CoursePlayPath;
183 type Err = EmptyError;
184 const METHOD: Method = Method::Put;
185}
186
187/// Update an admin data for a JIG.
188///
189/// # Authorization
190///
191/// * Standard + [`UserScope::AdminAsset`](crate::domain::user::UserScope)
192///
193/// # Errors
194///
195/// * [`Unauthorized`](http::StatusCode::UNAUTHORIZED) if authorization is not valid.
196/// * [`Forbidden`](http::StatusCode::FORBIDDEN) if the user does not have sufficient permission to perform the action.
197/// * [`BadRequest`](http::StatusCode::BAD_REQUEST) if the request is missing/invalid.
198pub struct CourseAdminDataUpdate;
199impl ApiEndpoint for CourseAdminDataUpdate {
200 type Path = CourseAdminDataUpdatePath;
201 type Req = CourseUpdateAdminDataRequest;
202 type Res = ();
203 type Err = EmptyError;
204 const METHOD: Method = Method::Patch;
205}