about summary refs log tree commit diff
path: root/src/micropub/get.rs
blob: 718714a3f83f01d2a7baca90d049ef2fd4f97513 (plain) (blame)
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
use crate::database::{MicropubChannel, Storage};
use crate::indieauth::User;
use crate::ApplicationState;
use tide::prelude::{json, Deserialize};
use tide::{Request, Response, Result};

#[derive(Deserialize)]
struct QueryOptions {
    q: String,
    url: Option<String>,
}

pub async fn get_handler<Backend>(req: Request<ApplicationState<Backend>>) -> Result
where
    Backend: Storage + Send + Sync,
{
    let user = req.ext::<User>().unwrap();
    let backend = &req.state().storage;
    let media_endpoint = &req.state().media_endpoint;
    let query = req.query::<QueryOptions>().unwrap_or(QueryOptions {
        q: "".to_string(),
        url: None,
    });
    match &*query.q {
        "config" => {
            let channels: Vec<MicropubChannel>;
            match backend.get_channels(user.me.as_str()).await {
                Ok(chans) => channels = chans,
                Err(err) => return Ok(err.into())
            }
            Ok(Response::builder(200).body(json!({
                "q": ["source", "config", "channel"],
                "channels": channels,
                "media-endpoint": media_endpoint
            })).build())
        },
        "channel" => {
            let channels: Vec<MicropubChannel>;
            match backend.get_channels(user.me.as_str()).await {
                Ok(chans) => channels = chans,
                Err(err) => return Ok(err.into())
            }
            Ok(Response::builder(200).body(json!(channels)).build())
        }
        "source" => {
            if user.check_scope("create") || user.check_scope("update") || user.check_scope("delete") || user.check_scope("undelete") {
                if let Some(url) = query.url {
                    match backend.get_post(&url).await {
                        Ok(post) => if let Some(post) = post {
                            Ok(Response::builder(200).body(post).build())
                        } else {
                            Ok(Response::builder(404).build())
                        },
                        Err(err) => Ok(err.into())
                    }
                } else {
                    Ok(Response::builder(400).body(json!({
                        "error": "invalid_request",
                        "error_description": "Please provide `url`."
                    })).build())
                }
            } else {
                Ok(Response::builder(401).body(json!({
                    "error": "insufficient_scope",
                    "error_description": "You don't have the required scopes to proceed.",
                    "scope": "update"
                })).build())
            }
        },
        // TODO: ?q=food, ?q=geo, ?q=contacts
        // Depends on indexing posts
        // Errors
        "" => Ok(Response::builder(400).body(json!({
            "error": "invalid_request",
            "error_description": "No ?q= parameter specified. Try ?q=config maybe?"
        })).build()),
        _ => Ok(Response::builder(400).body(json!({
            "error": "invalid_request",
            "error_description": "Unsupported ?q= query. Try ?q=config and see the q array for supported values."
        })).build())
    }
}