shared/api/endpoints/image/
user.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! Routes for the user image library

use crate::{
    api::{ApiEndpoint, Method},
    domain::{
        image::{
            user::{
                UserImageCreatePath, UserImageCreateRequest, UserImageDeletePath, UserImageGetPath,
                UserImageListPath, UserImageListQuery, UserImageListResponse, UserImageResponse,
                UserImageUploadPath, UserImageUploadRequest, UserImageUploadResponse,
            },
            ImageId,
        },
        CreateResponse,
    },
    error::EmptyError,
};

/// List user library images.
///
/// # Notes
/// * Request includes an optional query, called as a query string.
pub struct List;
impl ApiEndpoint for List {
    type Path = UserImageListPath;
    type Req = UserImageListQuery;
    type Res = UserImageListResponse;
    type Err = EmptyError;
    const METHOD: Method = Method::Get;
}

/// Get an user library image by ID.
///
/// # Errors
/// * [`NotFound`](http::StatusCode::NOT_FOUND) if the image with the requested ID is not found for the user.
/// Note that it will still return NOT_FOUND if an user image with the ID exists but is not owner by the
/// requesting user.
/// * TODO other errors here...
pub struct Get;
impl ApiEndpoint for Get {
    type Path = UserImageGetPath;
    type Req = ();
    type Res = UserImageResponse;
    type Err = EmptyError;
    const METHOD: Method = Method::Get;
}

/// Create an user library image.
pub struct Create;
impl ApiEndpoint for Create {
    type Path = UserImageCreatePath;
    type Req = UserImageCreateRequest;
    type Res = CreateResponse<ImageId>;
    type Err = EmptyError;
    const METHOD: Method = Method::Post;
}

/// Upload an image to the user image library.
/// # Flow:
///
/// 1. User requests an upload session URI directly to Google Cloud Storage
///     a. User uploads to processing bucket
/// 2. Firestore is notified of `processing = true, ready = false` status at document `uploads/media/user/{id}`
/// 3. Animation is processed and uploaded to the final bucket
/// 4. Firestore is notified of `processing = true, ready = true` status at document `uploads/media/user/{id}`
///
/// # Notes:
///
/// * Can be used to update the raw data associated with the image.
/// * If the client wants to re-upload an image after it has been successfully processed, it must repeat
/// the entire flow instead of uploading to the same session URI.
///
/// # Errors:
///
/// * [`401 - Unauthorized`](http::StatusCode::UNAUTHORIZED) if authorization is not valid.
/// * [`403 - Forbidden`](http::StatusCode::FORBIDDEN) if the user does not have sufficient permission to perform the action.
/// * [`501 - NotImplemented`](http::StatusCode::NOT_IMPLEMENTED) when the s3/gcs service is disabled.
pub struct Upload;
impl ApiEndpoint for Upload {
    type Path = UserImageUploadPath;
    // raw bytes
    type Req = UserImageUploadRequest;
    type Res = UserImageUploadResponse;
    type Err = EmptyError;
    const METHOD: Method = Method::Put;
}

/// Delete an image from the user library.
///
/// # Errors
/// * [`NotFound`](http::StatusCode::NOT_FOUND) if the image with the requested ID is not found for the user.
/// Note that it will still return NOT_FOUND if an user image with the ID exists but is not owner by the
/// requesting user.
/// * TODO other errors here...
pub struct Delete;
impl ApiEndpoint for Delete {
    type Path = UserImageDeletePath;
    type Req = ();
    type Res = ();
    type Err = EmptyError;
    const METHOD: Method = Method::Delete;
}