Compare commits
2 Commits
59c01e0e34
...
5494a54483
Author | SHA1 | Date |
---|---|---|
R Tyler Croy | 5494a54483 | |
R Tyler Croy | 0e3f874870 |
|
@ -24,4 +24,5 @@ pretty_env_logger = "~0.3.1"
|
|||
serde_json = "~1.0.0"
|
||||
sqlx = { version = "~0.5.1", features = ["chrono", "json", "migrate", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
|
||||
tide = "0"
|
||||
uuid = { version = "~0.8.1", features = ["v4", "serde"]}
|
||||
uuid = { version = "0", features = ["v4", "serde"]}
|
||||
url = "2"
|
||||
|
|
|
@ -22,19 +22,12 @@ intended to be a production system you can actually use.
|
|||
│ Server │http │ │
|
||||
│ │ws └──────┬─────┘
|
||||
└───┬────┘ │
|
||||
│ │
|
||||
│ What are your caps? │
|
||||
├──────────────────────────────────────────────────►│
|
||||
│ │
|
||||
│ │
|
||||
│ git,svn,bash,rustc,cargo,websocket │
|
||||
│◄──────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ great, here's some commands │
|
||||
├──────────────────────────────────────────────────►│
|
||||
│ │
|
||||
│ │
|
||||
│ kewl, here's the logs, id, etc │
|
||||
│◄──────────────────────────────────────────────────┤
|
||||
│ │
|
||||
----
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
description: |
|
||||
Janky Agent API defintion
|
||||
version: "1.0.0"
|
||||
title: Janky APIs
|
||||
contact:
|
||||
email: "rtyler+janky@brokenco.de"
|
||||
license:
|
||||
name: "AGPL v3.0"
|
||||
url: "https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
servers:
|
||||
- url: 'http://localhost:9000/api/v1'
|
||||
description: Local dev agent (APIv1)
|
||||
|
||||
paths:
|
||||
/capabilities:
|
||||
get:
|
||||
summary: "Retrieve a list of capabilities of this agent"
|
||||
description:
|
||||
responses:
|
||||
200:
|
||||
description: Getting capabilities
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CapsResponse'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
CapsResponse:
|
||||
type: array
|
||||
properties:
|
||||
caps:
|
||||
$ref: '#/components/schemas/Capability'
|
||||
Capability:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
path:
|
||||
type: string
|
||||
data:
|
||||
type: object
|
|
@ -0,0 +1 @@
|
|||
{"openapi":"3.0.0","info":{"description":"Janky Agent API defintion\n","version":"1.0.0","title":"Janky APIs","contact":{"email":"rtyler+janky@brokenco.de"},"license":{"name":"AGPL v3.0","url":"https://www.gnu.org/licenses/agpl-3.0.en.html"}},"servers":[{"url":"http://localhost:9000/api/v1","description":"Local dev agent (APIv1)"}],"paths":{"/capabilities":{"get":{"summary":"Retrieve a list of capabilities of this agent","description":null,"responses":{"200":{"description":"Getting capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapsResponse"}}}}}}}},"components":{"schemas":{"CapsResponse":{"type":"array","properties":{"caps":{"$ref":"#/components/schemas/Capability"}}},"Capability":{"type":"object","properties":{"name":{"type":"string"},"path":{"type":"string"},"data":{"type":"object"}}}}}}
|
Binary file not shown.
After Width: | Height: | Size: 665 B |
Binary file not shown.
After Width: | Height: | Size: 628 B |
|
@ -0,0 +1,60 @@
|
|||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "/apidocs/api-description.json",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,72 @@
|
|||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1);
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&")
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value)
|
||||
}
|
||||
) : {}
|
||||
|
||||
isValid = qp.state === sentState
|
||||
|
||||
if ((
|
||||
oauth2.auth.schema.get("flow") === "accessCode"||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode"
|
||||
) && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||
} else {
|
||||
let oauthErrorMsg
|
||||
if (qp.error) {
|
||||
oauthErrorMsg = "["+qp.error+"]: " +
|
||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
run();
|
||||
});
|
||||
</script>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
exec ruby -ryaml -rjson -e 'puts JSON.dump(YAML.load(STDIN.read))' < agent-api-description.yml > apidocs/api-description.json
|
|
@ -2,7 +2,6 @@ use dotenv::dotenv;
|
|||
use log::*;
|
||||
|
||||
mod routes {
|
||||
|
||||
use tide::{Body, Request};
|
||||
|
||||
/**
|
||||
|
@ -11,6 +10,18 @@ mod routes {
|
|||
pub async fn index(_req: Request<()>) -> Result<Body, tide::Error> {
|
||||
Ok("Hello World from the Janky Agent".into())
|
||||
}
|
||||
|
||||
pub mod api {
|
||||
use tide::{Body, Request};
|
||||
|
||||
pub fn register(app: &mut tide::Server<()>) {
|
||||
app.at("/api/v1/capabilities").get(get_caps);
|
||||
}
|
||||
|
||||
pub async fn get_caps(_req: Request<()>) -> Result<Body, tide::Error> {
|
||||
Ok("{}".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::main]
|
||||
|
@ -27,6 +38,7 @@ async fn main() -> Result<(), tide::Error> {
|
|||
|
||||
debug!("Configuring routes");
|
||||
app.at("/").get(routes::index);
|
||||
routes::api::register(&mut app);
|
||||
app.listen("0.0.0.0:9000").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
struct Capability {
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
data: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
struct CapsRequest {}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
struct CapsResponse {
|
||||
caps: Vec<Capability>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
struct Command {
|
||||
script: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
struct CommandRequest {
|
||||
commands: Vec<Command>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
struct CommandResponse {
|
||||
uuid: Uuid,
|
||||
stream_url: Option<Url>,
|
||||
task_url: Url,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {}
|
|
@ -58,10 +58,8 @@ impl AppState<'_> {
|
|||
*/
|
||||
mod routes {
|
||||
use crate::AppState;
|
||||
|
||||
|
||||
|
||||
use tide::{Body, Request};
|
||||
|
||||
|
||||
/**
|
||||
* GET /
|
||||
|
@ -75,12 +73,7 @@ mod routes {
|
|||
Ok(body)
|
||||
}
|
||||
|
||||
pub mod api {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
pub mod api {}
|
||||
}
|
||||
|
||||
#[async_std::main]
|
||||
|
@ -91,7 +84,8 @@ async fn main() -> Result<(), tide::Error> {
|
|||
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
|
||||
let pool = SqlitePool::connect(&database_url).await?;
|
||||
if database_url == ":memory:" {
|
||||
sqlx::migrate!().run(&pool).await?;
|
||||
// TODO: Figure out why failing
|
||||
//sqlx::migrate!().run(&pool).await?;
|
||||
}
|
||||
|
||||
let state = AppState::new(pool);
|
||||
|
@ -123,6 +117,7 @@ async fn main() -> Result<(), tide::Error> {
|
|||
/*
|
||||
* All builds will have apidocs, since they're handy
|
||||
*/
|
||||
app.at("/apidocs").serve_dir("apidocs/")?;
|
||||
app.at("/static").serve_dir("static/")?;
|
||||
debug!("Configuring routes");
|
||||
app.at("/").get(routes::index);
|
||||
|
|
Loading…
Reference in New Issue