Skip to main content

rebuilderd/api/v1/
worker.rs

1use crate::api::header;
2use crate::api::v1::util::auth;
3use crate::api::v1::util::pagination::PaginateDsl;
4use crate::config::Config;
5use crate::db::Pool;
6use crate::models::NewWorker;
7use crate::schema::workers;
8use crate::web;
9use actix_web::{HttpRequest, HttpResponse, Responder, delete, get, post};
10use chrono::Utc;
11use diesel::{OptionalExtension, QueryDsl, RunQueryDsl, SqliteExpressionMethods};
12use rebuilderd_common::api::WORKER_KEY_HEADER;
13use rebuilderd_common::api::v1::{Page, RegisterWorkerRequest, ResultPage};
14use rebuilderd_common::errors::{Context, Error, format_err};
15use std::net::IpAddr;
16
17#[diesel::dsl::auto_type]
18fn workers_base() -> _ {
19    workers::table.select((
20        workers::id,
21        workers::name,
22        workers::address,
23        workers::status,
24        workers::last_ping,
25        workers::online,
26    ))
27}
28
29#[get("")]
30pub async fn get_workers(
31    pool: web::Data<Pool>,
32    page: web::Query<Page>,
33) -> web::Result<impl Responder> {
34    let mut connection = pool.get().map_err(Error::from)?;
35
36    let records = workers_base()
37        .paginate(page.into_inner())
38        .load::<rebuilderd_common::api::v1::Worker>(connection.as_mut())
39        .map_err(Error::from)?;
40
41    let total = workers_base()
42        .count()
43        .get_result::<i64>(connection.as_mut())
44        .map_err(Error::from)?;
45
46    Ok(HttpResponse::Ok().json(ResultPage { total, records }))
47}
48
49#[post("")]
50pub async fn register_worker(
51    req: HttpRequest,
52    cfg: web::Data<Config>,
53    pool: web::Data<Pool>,
54    request: web::Json<RegisterWorkerRequest>,
55) -> web::Result<impl Responder> {
56    let mut connection = pool.get().map_err(Error::from)?;
57    if auth::signup(&cfg, &req).is_err() {
58        return Ok(HttpResponse::Forbidden().finish());
59    }
60
61    let key = header(&req, WORKER_KEY_HEADER).context("Failed to get worker key")?;
62    let ip = if let Some(real_ip_header) = &cfg.real_ip_header {
63        let ip = header(&req, real_ip_header).context("Failed to locate real ip header")?;
64        ip.parse::<IpAddr>()
65            .context("Can't parse real ip header as ip address")?
66    } else {
67        let ci = req
68            .peer_addr()
69            .ok_or_else(|| format_err!("Can't determine client ip"))?;
70        ci.ip()
71    };
72
73    let new_worker = NewWorker {
74        key: key.to_string(),
75        name: request.name.clone(),
76        address: ip.to_string(),
77        status: None,
78        last_ping: Utc::now().naive_utc(),
79        online: true,
80    };
81
82    new_worker.upsert(connection.as_mut())?;
83
84    Ok(HttpResponse::NoContent().finish())
85}
86
87#[get("/{id}")]
88pub async fn get_worker(pool: web::Data<Pool>, id: web::Path<i32>) -> web::Result<impl Responder> {
89    let mut connection = pool.get().map_err(Error::from)?;
90
91    if let Some(record) = workers_base()
92        .filter(workers::id.is(id.into_inner()))
93        .get_result::<rebuilderd_common::api::v1::Worker>(connection.as_mut())
94        .optional()
95        .map_err(Error::from)?
96    {
97        Ok(HttpResponse::Ok().json(record))
98    } else {
99        Ok(HttpResponse::NotFound().finish())
100    }
101}
102
103#[delete("/{id}")]
104pub async fn unregister_worker(
105    req: HttpRequest,
106    cfg: web::Data<Config>,
107    pool: web::Data<Pool>,
108    id: web::Path<i32>,
109) -> web::Result<impl Responder> {
110    let mut connection = pool.get().map_err(Error::from)?;
111    if auth::worker(&cfg, &req, connection.as_mut()).is_err() {
112        return Ok(HttpResponse::Forbidden().finish());
113    }
114
115    let unregistered_count = diesel::delete(workers::table)
116        .filter(workers::id.is(id.into_inner()))
117        .execute(connection.as_mut())
118        .map_err(Error::from)?;
119
120    if unregistered_count < 1 {
121        Ok(HttpResponse::NotFound().finish())
122    } else {
123        Ok(HttpResponse::NoContent().finish())
124    }
125}