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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use std::path::Path;
use reqwest::{Client, Response};
use base64::{Engine as _, engine::general_purpose};
use crate::models::structs::{ChildAssociationEntry, NodeBodyUpdate, NodeEntry};

use anyhow::Result;
use serde_json::json;
use tokio::fs::File;
use tokio::io::AsyncReadExt;
use crate::alfresco::params::QueryParamsBuilder;

pub struct NodesApi {
    pub base_url: String,
    pub client: Client,
}

impl NodesApi {
    pub fn new(base_url: &str, client: Client) -> Self {
        NodesApi {
            base_url: format!("{}/alfresco/api/-default-/public/alfresco/versions/1", base_url),
            client,
        }
    }

    pub async fn get_node(&self, ticket: &String, node_id: &String, include: Option<&Vec<String>>, relative_path: Option<&String>, fields: Option<&Vec<String>>) -> Result<NodeEntry> {
        let formatted_url = format!("{}/nodes/{}", self.base_url, node_id);
        let ticket_b64 = general_purpose::STANDARD.encode(ticket);

        let mut params_builder = QueryParamsBuilder::new()
            .set_relative_path(relative_path);

        if let Some(field_list) = fields {
            for field in field_list {
                params_builder = params_builder.push_field(Some(field));
            }
        }

        if let Some(include_list) = include {
            for include in include_list {
                params_builder = params_builder.push_include(Some(include));
            }
        }

        let raw_response = self.client.get(&formatted_url)
            .header("Authorization", format!("Basic {}", ticket_b64))
            .query(&params_builder.build())
            .send()
            .await?;

        let parsed = raw_response.json::<NodeEntry>().await?;

        Ok(parsed)
    }

    pub async fn update_node(&self, ticket: &String, node_id: &String, include: Option<&Vec<String>>, fields: Option<&Vec<String>>, body: NodeBodyUpdate) -> Result<NodeEntry> {
        let formatted_url = format!("{}/nodes/{}", self.base_url, node_id);
        let ticket_b64 = general_purpose::STANDARD.encode(ticket);

        let mut params_builder = QueryParamsBuilder::new();

        if let Some(field_list) = fields {
            for field in field_list {
                params_builder = params_builder.push_field(Some(field));
            }
        }

        if let Some(include_list) = include {
            for include in include_list {
                params_builder = params_builder.push_include(Some(include));
            }
        }

        let raw_response: Response = self.client.put(&formatted_url)
            .header("Authorization", format!("Basic {}", ticket_b64))
            .query(&params_builder.build())
            .json(&body)
            .send()
            .await?;

        let parsed = raw_response.json::<NodeEntry>().await?;
        // let parsed = raw_response.text().await?;
        Ok(parsed)
    }

    pub async fn upload_file(&self, ticket: &String, parent_id: &String, file_path: &String, overwrite: &bool, relative_path: Option<&String>) -> Result<NodeEntry> {
        let formatted_url = format!("{}/nodes/{}/children", self.base_url, parent_id);
        let ticket_b64 = general_purpose::STANDARD.encode(ticket);

        let mut file = File::open(file_path).await?;
        let mut buffer = Vec::new();
        file.read_to_end(&mut buffer).await?;

        let path = Path::new(file_path);
        let file_name = path.file_name().unwrap().to_owned().into_string().unwrap();
        println!("{:?}", &file_name);
        let file_part = reqwest::multipart::Part::bytes(buffer).file_name(file_name.clone());

        let mut form = reqwest::multipart::Form::new()
            .part("filedata", file_part)
            .text("overwrite", overwrite.to_string())
            .text("name", file_name.clone())
            .text("nodeType", "cm:content")
            .text("renditions", "doclib");

        if relative_path.is_some() {
            form = form.text("relativePath", relative_path.unwrap().clone());
        }

        let raw_response = self.client.post(&formatted_url)
            .header("Authorization", format!("Basic {}", ticket_b64))
            .multipart(form)
            .send()
            .await?;


        let parsed = raw_response.json::<NodeEntry>().await?;

        Ok(parsed)
    }

    pub async fn create_secondary_children(&self, ticket: &String, parent_id: &String, child_id: &String, assoc_type: &String, fields: Option<&Vec<String>>) -> Result<ChildAssociationEntry> {
        let formatted_url = format!("{}/nodes/{}/secondary-children", self.base_url, parent_id);
        let ticket_b64 = general_purpose::STANDARD.encode(ticket);

        let mut params_builder = QueryParamsBuilder::new();

        if let Some(field_list) = fields {
            for field in field_list {
                params_builder = params_builder.push_field(Some(field));
            }
        }

        let raw_response = self.client.post(&formatted_url)
            .header("Authorization", format!("Basic {}", ticket_b64))
            .json(&json!({
                "childId": child_id,
                "assocType": assoc_type,
            }))
            .send()
            .await?;

        let parsed = raw_response.json::<ChildAssociationEntry>().await?;

        Ok(parsed)
    }

}