Add authentication #1
					 8 changed files with 42 additions and 20 deletions
				
			
		use enum for role and fix dns client for async
				commit
				
					
					
						ebe1552032
					
				
			
		
							
								
								
									
										1
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -795,6 +795,7 @@ dependencies = [
 | 
			
		|||
 "rocket_contrib",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "serde_json",
 | 
			
		||||
 "tokio",
 | 
			
		||||
 "toml",
 | 
			
		||||
 "trust-dns-client",
 | 
			
		||||
 "trust-dns-proto",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,3 +22,4 @@ djangohashers = { version = "1.4.0", features = ["with_argon2"], default-feature
 | 
			
		|||
jsonwebtoken = "7.2.0"
 | 
			
		||||
chrono = { version = "0.4", features = ["serde"] }
 | 
			
		||||
humantime = "2.1.0"
 | 
			
		||||
tokio = "1"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,3 +3,4 @@
 | 
			
		|||
 | 
			
		||||
[print_schema]
 | 
			
		||||
file = "src/schema.rs"
 | 
			
		||||
import_types = ["diesel::sql_types::*", "crate::models::users::*"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,5 +8,5 @@ CREATE TABLE localuser (
 | 
			
		|||
 | 
			
		||||
CREATE TABLE user (
 | 
			
		||||
  id VARCHAR NOT NULL PRIMARY KEY,
 | 
			
		||||
  role VARCHAR NOT NULL
 | 
			
		||||
  role TEXT CHECK(role IN ('admin', 'zoneadmin')) NOT NULL -- note: migrate to postgres so enum are actually a thing
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								src/main.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,8 +4,15 @@
 | 
			
		|||
#[macro_use] extern crate rocket_contrib;
 | 
			
		||||
#[macro_use] extern crate diesel;
 | 
			
		||||
 | 
			
		||||
use trust_dns_client::client::SyncClient;
 | 
			
		||||
use trust_dns_client::tcp::TcpClientConnection;
 | 
			
		||||
use trust_dns_client::client::AsyncClient;
 | 
			
		||||
use trust_dns_client::tcp::TcpClientStream;
 | 
			
		||||
use trust_dns_proto::xfer::dns_multiplexer::DnsMultiplexer;
 | 
			
		||||
use trust_dns_proto::iocompat::AsyncIoTokioAsStd;
 | 
			
		||||
use trust_dns_client::rr::dnssec::Signer;
 | 
			
		||||
use tokio::net::TcpStream as TokioTcpStream;
 | 
			
		||||
use tokio::task;
 | 
			
		||||
 | 
			
		||||
use std::sync::{Arc, Mutex};
 | 
			
		||||
 | 
			
		||||
mod models;
 | 
			
		||||
mod config;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,19 +26,22 @@ use routes::zones::*;
 | 
			
		|||
#[database("db")]
 | 
			
		||||
pub struct DbConn(diesel::SqliteConnection);
 | 
			
		||||
 | 
			
		||||
type DnsClient = SyncClient<TcpClientConnection>;
 | 
			
		||||
type DnsClient = Arc<Mutex<AsyncClient>>;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[launch]
 | 
			
		||||
fn rocket() -> rocket::Rocket {
 | 
			
		||||
async fn rocket() -> rocket::Rocket {
 | 
			
		||||
    let app_config = config::load("config.toml".into());
 | 
			
		||||
    println!("{:#?}", app_config);
 | 
			
		||||
 | 
			
		||||
    let conn = TcpClientConnection::new(app_config.dns.server).unwrap();
 | 
			
		||||
    let client = SyncClient::new(conn);
 | 
			
		||||
    let (stream, handle) = TcpClientStream::<AsyncIoTokioAsStd<TokioTcpStream>>::new(app_config.dns.server);
 | 
			
		||||
    let multiplexer = DnsMultiplexer::<_, Signer>::new(stream, handle, None);
 | 
			
		||||
    let client = AsyncClient::connect(multiplexer);
 | 
			
		||||
    let (client, bg) = client.await.expect("connection failed");
 | 
			
		||||
    task::spawn(bg);
 | 
			
		||||
 | 
			
		||||
    rocket::ignite()
 | 
			
		||||
        .manage(client)
 | 
			
		||||
        .manage(Arc::new(Mutex::new(client)))
 | 
			
		||||
        .manage(app_config)
 | 
			
		||||
        .attach(DbConn::fairing())
 | 
			
		||||
        .mount("/api/v1", routes![get_zone_records, create_auth_token, create_user])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,10 +27,11 @@ const BEARER: &'static str = "Bearer ";
 | 
			
		|||
const AUTH_HEADER: &'static str = "Authentication";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, DbEnum, Deserialize)]
 | 
			
		||||
#[serde(rename_all = "snake_case")]
 | 
			
		||||
#[derive(Debug, DbEnum, Deserialize, Clone)]
 | 
			
		||||
#[serde(rename_all = "kebab-case")]
 | 
			
		||||
pub enum Role {
 | 
			
		||||
    Admin,
 | 
			
		||||
    #[db_rename = "zoneadmin"]
 | 
			
		||||
    ZoneAdmin,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +41,7 @@ pub enum Role {
 | 
			
		|||
#[table_name = "user"]
 | 
			
		||||
pub struct User {
 | 
			
		||||
    pub id: String,
 | 
			
		||||
    pub role: String,
 | 
			
		||||
    pub role: Role,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Queryable, Identifiable, Insertable)]
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +90,7 @@ pub struct AuthTokenRequest {
 | 
			
		|||
#[derive(Debug)]
 | 
			
		||||
pub struct UserInfo {
 | 
			
		||||
    pub id: String,
 | 
			
		||||
    pub role: String,
 | 
			
		||||
    pub role: Role,
 | 
			
		||||
    pub username: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +177,7 @@ impl LocalUser {
 | 
			
		|||
        let new_user = User {
 | 
			
		||||
            id: new_user_id.clone(),
 | 
			
		||||
            // TODO: Use role from request
 | 
			
		||||
            role: "zoneadmin".into(),
 | 
			
		||||
            role: Role::ZoneAdmin,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let new_localuser = LocalUser {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,28 +3,31 @@ use rocket::http::Status;
 | 
			
		|||
 | 
			
		||||
use rocket_contrib::json::Json;
 | 
			
		||||
 | 
			
		||||
use trust_dns_client::client::{Client};
 | 
			
		||||
use trust_dns_client::client::ClientHandle;
 | 
			
		||||
use trust_dns_client::op::{DnsResponse, ResponseCode};
 | 
			
		||||
use trust_dns_client::rr::{DNSClass, Name, RecordType};
 | 
			
		||||
 | 
			
		||||
use crate::models::dns;
 | 
			
		||||
use crate::models::errors::ErrorResponse;
 | 
			
		||||
use crate::models::errors::{ErrorResponse, make_500};
 | 
			
		||||
use crate::models::users::UserInfo;
 | 
			
		||||
use crate::DnsClient;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[get("/zones/<zone>/records")]
 | 
			
		||||
pub fn get_zone_records(
 | 
			
		||||
    client: State<DnsClient>,
 | 
			
		||||
pub async fn get_zone_records(
 | 
			
		||||
    client: State<'_, DnsClient>,
 | 
			
		||||
    user_info: Result<UserInfo, ErrorResponse>,
 | 
			
		||||
    zone: String
 | 
			
		||||
) -> Result<Json<Vec<dns::Record>>, ErrorResponse> {
 | 
			
		||||
    user_info?;
 | 
			
		||||
    println!("{:#?}", user_info?);
 | 
			
		||||
 | 
			
		||||
    // TODO: Implement FromParam for Name
 | 
			
		||||
    let name = Name::from_utf8(&zone).unwrap();
 | 
			
		||||
 | 
			
		||||
    let response: DnsResponse = client.query(&name, DNSClass::IN, RecordType::AXFR).unwrap();
 | 
			
		||||
    let response: DnsResponse = {
 | 
			
		||||
        let query = client.lock().unwrap().query(name.clone(), DNSClass::IN, RecordType::AXFR);
 | 
			
		||||
        query.await.map_err(make_500)?
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if response.response_code() != ResponseCode::NoError {
 | 
			
		||||
        return ErrorResponse::new(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,6 @@
 | 
			
		|||
table! {
 | 
			
		||||
    use diesel::sql_types::*;
 | 
			
		||||
 | 
			
		||||
    localuser (user_id) {
 | 
			
		||||
        user_id -> Text,
 | 
			
		||||
        username -> Text,
 | 
			
		||||
| 
						 | 
				
			
			@ -7,9 +9,12 @@ table! {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
table! {
 | 
			
		||||
    use diesel::sql_types::*;
 | 
			
		||||
    use crate::models::users::*;
 | 
			
		||||
 | 
			
		||||
    user (id) {
 | 
			
		||||
        id -> Text,
 | 
			
		||||
        role -> Text,
 | 
			
		||||
        role -> RoleMapping,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue