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
use async_graphql::{Context, Enum, Interface, Object, SimpleObject};

use crate::{
    gql::run_usecase,
    usecase::{SubscribeFeed, SubscribeFeedError, UnsubscribeFeed},
};

pub mod subscribe_feed;
pub mod unsubscribe_feed;

#[derive(Enum, PartialEq, Eq, Clone, Copy)]
pub enum ResponseCode {
    /// Operation success
    Ok,
    /// Principal does not have enough permissions
    Unauthorized,
    /// Given url is not valid feed url
    InvalidFeedUrl,
    /// Something went wrong
    InternalError,
}

#[derive(SimpleObject, Clone)]
pub struct ResponseStatus {
    code: ResponseCode,
    // TODO: add message
}

impl ResponseStatus {
    fn ok() -> Self {
        ResponseStatus {
            code: ResponseCode::Ok,
        }
    }

    #[allow(unused)]
    fn unauthorized() -> Self {
        ResponseStatus {
            code: ResponseCode::Unauthorized,
        }
    }

    fn invalid_feed_url() -> Self {
        Self {
            code: ResponseCode::InvalidFeedUrl,
        }
    }

    fn internal() -> Self {
        Self {
            code: ResponseCode::InternalError,
        }
    }
}

#[allow(clippy::large_enum_variant)]
#[derive(Interface)]
#[graphql(field(name = "status", method = "status", ty = "ResponseStatus"))]
enum MutationResponse {
    SubscribeFeed(subscribe_feed::SubscribeFeedSuccess),
    UnsubscribeFeed(unsubscribe_feed::UnsubscribeFeedSuccess),
}

#[derive(Interface)]
#[graphql(
    field(name = "status", ty = "ResponseStatus"),
    field(name = "message", ty = "String")
)]
enum ErrorResponse {
    SubscribeFeed(subscribe_feed::SubscribeFeedError),
    UnsubscribeFeed(unsubscribe_feed::UnsubscribeFeedError),
}

pub struct Mutation;

#[Object]
impl Mutation {
    /// Subscribe feed
    async fn subscribe_feed(
        &self,
        cx: &Context<'_>,
        input: subscribe_feed::SubscribeFeedInput,
    ) -> async_graphql::Result<subscribe_feed::SubscribeFeedResponse> {
        run_usecase!(SubscribeFeed, cx, input, |err: SubscribeFeedError| Ok(
            err.into()
        ))
    }

    /// Unsubscribe feed
    /// If given feed is not subscribed, this mutation will succeed
    async fn unsubscribe_feed(
        &self,
        cx: &Context<'_>,
        input: unsubscribe_feed::UnsubscribeFeedInput,
    ) -> async_graphql::Result<unsubscribe_feed::UnsubscribeFeedResponse> {
        run_usecase!(UnsubscribeFeed, cx, input, |err: anyhow::Error| Ok(
            err.into()
        ))
    }
}