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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use super::*;
use crate::zones::FileZone;
use crate::zones::FileZoneRecord;
use axum::extract::Path;
use axum::extract::State;
use axum::routing::{delete, post, put};
use axum::Json;
use serde::Deserialize;
use serde::Serialize;

pub mod auth;
pub(crate) mod docs;
pub mod filezone;
pub mod filezonerecord;
use tower_sessions::Session;

#[macro_export]
/// message, status
macro_rules! error_result_json {
    ($msg:expr, $status:expr) => {
        Err(($status, Json(ErrorResult::from($msg))))
    };
}

#[derive(Serialize)]
pub struct NotImplemented {
    response: String,
}

impl Default for NotImplemented {
    fn default() -> Self {
        Self {
            response: "This endpoint is not yet implemented".to_string(),
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[allow(dead_code)]
pub struct ErrorResult {
    #[allow(dead_code)]
    pub message: String,
}

impl From<&str> for ErrorResult {
    fn from(input: &str) -> Self {
        ErrorResult {
            message: input.to_string(),
        }
    }
}

/// This gets applied to DBEntities
#[async_trait]
trait APIEntity {
    /// Save the entity to the database
    async fn api_create(
        State(state): State<GoatState>,
        session: Session,
        Json(payload): Json<serde_json::Value>,
    ) -> Result<Json<Box<Self>>, (StatusCode, Json<ErrorResult>)>;
    /// HTTP Put <https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT>
    async fn api_update(
        State(state): State<GoatState>,
        session: Session,
        Json(payload): Json<serde_json::Value>,
    ) -> Result<Json<String>, (StatusCode, Json<ErrorResult>)>;
    async fn api_get(
        State(state): State<GoatState>,
        session: Session,
        Path(id): Path<i64>,
    ) -> Result<Json<Box<Self>>, (StatusCode, Json<ErrorResult>)>;

    /// Delete an object
    /// <https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE>
    async fn api_delete(
        State(state): State<GoatState>,
        session: Session,
        Path(id): Path<i64>,
    ) -> Result<StatusCode, (StatusCode, Json<ErrorResult>)>;
}

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct FileZoneResponse {
    pub message: String,
    pub zone: Option<FileZone>,
    pub id: Option<i64>,
}

#[derive(Serialize)]
pub struct GoatNSVersion {
    version: String,
}
impl Default for GoatNSVersion {
    fn default() -> Self {
        Self {
            version: format!("GoatNS {}", env!("CARGO_PKG_VERSION")),
        }
    }
}

pub async fn version_get() -> Json<GoatNSVersion> {
    Json::from(GoatNSVersion::default())
}

pub fn new() -> Router<GoatState> {
    Router::new()
        .route("/zone", post(FileZone::api_create))
        .route("/zone", put(FileZone::api_update))
        .route("/zone/:id", get(FileZone::api_get))
        .route("/zone/:id", delete(FileZone::api_delete))
        .route("/record", post(FileZoneRecord::api_create))
        .route("/record", put(FileZoneRecord::api_update))
        .route("/record/:id", get(FileZoneRecord::api_get))
        .route("/record/:id", delete(FileZoneRecord::api_delete))
        .route("/login", post(auth::login))
}