frontend init

This commit is contained in:
Adrian Gunnar Lauterer 2024-05-25 23:30:53 +02:00
parent 57e0cb6a88
commit 8593af2441
28 changed files with 1972 additions and 2843 deletions

4
.gitignore vendored
View File

@ -14,3 +14,7 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
.vscode

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"eslint.enable": false,
"standard.enable": false
}

2289
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -22,12 +22,14 @@ stv-rs = "0.3.0"
serde = "1.0"
serde_derive = "1.0"
serde_yaml = "0.7"
serde_yaml = "0.9.34"
serde_json = "1.0"
base64 = "~0.7.0"
futures = "0.1.16"
hyper = "0.11.6"
url = "1.5"
base64 = "~0.22.1"
futures = "0.3.30"
hyper = "1.3.1"
url = "2.5.0"
sqlx = "0.7.4"
[dev-dependencies]
tokio-core = "*"

480
flake.lock Normal file
View File

@ -0,0 +1,480 @@
{
"nodes": {
"cachix": {
"inputs": {
"devenv": "devenv_2",
"flake-compat": [
"devenv",
"flake-compat"
],
"nixpkgs": [
"devenv",
"nixpkgs"
],
"pre-commit-hooks": [
"devenv",
"pre-commit-hooks"
]
},
"locked": {
"lastModified": 1712055811,
"narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
"owner": "cachix",
"repo": "cachix",
"rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "cachix",
"type": "github"
}
},
"devenv": {
"inputs": {
"cachix": "cachix",
"flake-compat": "flake-compat_2",
"nix": "nix_2",
"nixpkgs": "nixpkgs_2",
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1716484006,
"narHash": "sha256-2gtN5jf21HS9TAZXhf9G+OSUY1TQ/95n6clcuFjYQ58=",
"owner": "cachix",
"repo": "devenv",
"rev": "800f19d1b999f89464fd8e0226abf4b3b444b0fa",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"devenv_2": {
"inputs": {
"flake-compat": [
"devenv",
"cachix",
"flake-compat"
],
"nix": "nix",
"nixpkgs": "nixpkgs",
"poetry2nix": "poetry2nix",
"pre-commit-hooks": [
"devenv",
"cachix",
"pre-commit-hooks"
]
},
"locked": {
"lastModified": 1708704632,
"narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
"owner": "cachix",
"repo": "devenv",
"rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "python-rewrite",
"repo": "devenv",
"type": "github"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1716618425,
"narHash": "sha256-eZs7f4izo6t0AmOI1IAU6/ZbbXrxMPGdo+khe4hP3Rk=",
"owner": "nix-community",
"repo": "fenix",
"rev": "9a9fafd0c3f796b675acb2e16ae238d4fd2cbdb5",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"devenv",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nix": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"devenv",
"cachix",
"devenv",
"nixpkgs"
],
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1712911606,
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
"owner": "domenkozar",
"repo": "nix",
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "devenv-2.21",
"repo": "nix",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"devenv",
"cachix",
"devenv",
"poetry2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1688870561,
"narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix_2": {
"inputs": {
"flake-compat": [
"devenv",
"flake-compat"
],
"nixpkgs": [
"devenv",
"nixpkgs"
],
"nixpkgs-regression": "nixpkgs-regression_2"
},
"locked": {
"lastModified": 1712911606,
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
"owner": "domenkozar",
"repo": "nix",
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "devenv-2.21",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1692808169,
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-regression_2": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1710695816,
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1713361204,
"narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
"owner": "cachix",
"repo": "devenv-nixpkgs",
"rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "rolling",
"repo": "devenv-nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1716509168,
"narHash": "sha256-4zSIhSRRIoEBwjbPm3YiGtbd8HDWzFxJjw5DYSDy1n8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bfb7a882678e518398ce9a31a881538679f6f092",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"poetry2nix": {
"inputs": {
"flake-utils": "flake-utils",
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"devenv",
"cachix",
"devenv",
"nixpkgs"
]
},
"locked": {
"lastModified": 1692876271,
"narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "poetry2nix",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": [
"devenv",
"flake-compat"
],
"flake-utils": "flake-utils_2",
"gitignore": "gitignore",
"nixpkgs": [
"devenv",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1713775815,
"narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"fenix": "fenix",
"nixpkgs": "nixpkgs_3"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1716572615,
"narHash": "sha256-mVUbarr4PNjERDk+uaoitPq7eL7De0ythZehezAzug8=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "a55e8bf09cdfc25066b77823cc98976a51af8a8b",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

111
src/api.rs Normal file
View File

@ -0,0 +1,111 @@
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[macro_use] extern crate rocket_contrib;
#[macro_use] extern crate serde_derive;
use rocket::http::Status;
use rocket_contrib::json::{Json, JsonValue};
// Define data models
#[derive(Serialize, Deserialize)]
struct User {
id: String,
username: String,
password: String,
}
#[derive(Serialize, Deserialize)]
struct Authorization {
to_date: String,
from_date: String,
user: String,
}
#[derive(Serialize, Deserialize)]
struct Election {
id: String,
username: String,
name: String,
description: String,
start_date: String,
end_date: String,
items: Vec<ElectionItem>,
}
#[derive(Serialize, Deserialize)]
struct ElectionItem {
id: String,
name: String,
}
#[derive(Serialize, Deserialize)]
struct VoteItem {
item: ElectionItem,
value: f64,
}
#[derive(Serialize, Deserialize)]
struct Vote {
authorization: Authorization,
userid: String,
data: Vec<VoteItem>,
}
// Routes
#[post("/auth/login", format = "application/json", data = "<credentials>")]
fn login(credentials: Json<User>) -> JsonValue {
// Authentication logic here
json!({
"token": "your_generated_token"
})
}
#[post("/auth/token", format = "application/json", data = "<token>")]
fn generate_token(token: Json<Authorization>) -> JsonValue {
// Token generation logic here
json!({
"token": "generated_token"
})
}
#[post("/elections/create", format = "application/json", data = "<election>")]
fn create_election(election: Json<Election>) -> Result<JsonValue, Status> {
// Election creation logic here
Ok(json!(election))
}
#[get("/elections/all")]
fn get_all_elections() -> JsonValue {
// Retrieve all elections logic here
json!([
// List of all existing elections
])
}
#[get("/elections/<id>")]
fn get_election(id: String) -> JsonValue {
// Retrieve single election logic here
json!({
"id": id,
// Other election details
})
}
#[post("/elections/<id>", format = "application/json", data = "<vote>")]
fn vote_in_election(id: String, vote: Json<Vote>) -> Result<JsonValue, Status> {
// Voting logic here
Ok(json!(vote))
}
// Rocket fairings to set up CORS and other middlewares can be added here
fn main() {
rocket::ignite()
.mount("/api", routes![
login,
generate_token,
create_election,
get_all_elections,
get_election,
vote_in_election,
])
.launch();
}

View File

@ -1,26 +0,0 @@
use std::rc::Rc;
use hyper;
use super::configuration::Configuration;
pub struct APIClient<C: hyper::client::Connect> {
configuration: Rc<Configuration<C>>,
default_api: Box<::apis::DefaultApi>,
}
impl<C: hyper::client::Connect> APIClient<C> {
pub fn new(configuration: Configuration<C>) -> APIClient<C> {
let rc = Rc::new(configuration);
APIClient {
configuration: rc.clone(),
default_api: Box::new(::apis::DefaultApiClient::new(rc.clone())),
}
}
pub fn default_api(&self) -> &::apis::DefaultApi{
self.default_api.as_ref()
}
}

View File

@ -1,42 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
use hyper;
use std::collections::HashMap;
pub struct Configuration<C: hyper::client::Connect> {
pub base_path: String,
pub user_agent: Option<String>,
pub client: hyper::client::Client<C>,
pub basic_auth: Option<BasicAuth>,
pub oauth_access_token: Option<String>,
pub api_key: Option<ApiKey>,
// TODO: take an oauth2 token source, similar to the go one
}
pub type BasicAuth = (String, Option<String>);
pub struct ApiKey {
pub prefix: Option<String>,
pub key: String,
}
impl<C: hyper::client::Connect> Configuration<C> {
pub fn new(client: hyper::client::Client<C>) -> Configuration<C> {
Configuration {
base_path: "https://localhost/api".to_owned(),
user_agent: Some("Swagger-Codegen/0.0.1/rust".to_owned()),
client: client,
basic_auth: None,
oauth_access_token: None,
api_key: None,
}
}
}

View File

@ -1,480 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
use std::rc::Rc;
use std::borrow::Borrow;
use std::borrow::Cow;
use std::collections::HashMap;
use hyper;
use serde_json;
use futures;
use futures::{Future, Stream};
use hyper::header::UserAgent;
use super::{Error, configuration};
pub struct DefaultApiClient<C: hyper::client::Connect> {
configuration: Rc<configuration::Configuration<C>>,
}
impl<C: hyper::client::Connect> DefaultApiClient<C> {
pub fn new(configuration: Rc<configuration::Configuration<C>>) -> DefaultApiClient<C> {
DefaultApiClient {
configuration: configuration,
}
}
}
pub trait DefaultApi {
fn auth_login_post(&self, credentials: ::models::Credentials) -> Box<Future<Item = ::models::InlineResponse200, Error = Error<serde_json::Value>>>;
fn auth_token_post(&self, authorization: &str, token: ::models::Authorization) -> Box<Future<Item = ::models::InlineResponse2001, Error = Error<serde_json::Value>>>;
fn elections_all_get(&self, authorization: &str) -> Box<Future<Item = ::models::ElectionList, Error = Error<serde_json::Value>>>;
fn elections_create_post(&self, authorization: &str, election: ::models::Election) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>>;
fn elections_id_get(&self, authorization: &str, id: &str) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>>;
fn elections_id_post(&self, authorization: &str, election: ::models::Vote) -> Box<Future<Item = ::models::Vote, Error = Error<serde_json::Value>>>;
}
impl<C: hyper::client::Connect>DefaultApi for DefaultApiClient<C> {
fn auth_login_post(&self, credentials: ::models::Credentials) -> Box<Future<Item = ::models::InlineResponse200, Error = Error<serde_json::Value>>> {
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
let mut auth_headers = HashMap::<String, String>::new();
let mut auth_query = HashMap::<String, String>::new();
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
auth_headers.insert("Authorization".to_owned(), val);
};
let method = hyper::Method::Post;
let query_string = {
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
for (key, val) in &auth_query {
query.append_pair(key, val);
}
query.finish()
};
let uri_str = format!("{}/auth/login?{}", configuration.base_path, query_string);
// TODO(farcaller): handle error
// if let Err(e) = uri {
// return Box::new(futures::future::err(e));
// }
let mut uri: hyper::Uri = uri_str.parse().unwrap();
let mut req = hyper::Request::new(method, uri);
if let Some(ref user_agent) = configuration.user_agent {
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
}
for (key, val) in auth_headers {
req.headers_mut().set_raw(key, val);
}
let serialized = serde_json::to_string(&credentials).unwrap();
req.headers_mut().set(hyper::header::ContentType::json());
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
req.set_body(serialized);
// send request
Box::new(
configuration.client.request(req)
.map_err(|e| Error::from(e))
.and_then(|resp| {
let status = resp.status();
resp.body().concat2()
.and_then(move |body| Ok((status, body)))
.map_err(|e| Error::from(e))
})
.and_then(|(status, body)| {
if status.is_success() {
Ok(body)
} else {
Err(Error::from((status, &*body)))
}
})
.and_then(|body| {
let parsed: Result<::models::InlineResponse200, _> = serde_json::from_slice(&body);
parsed.map_err(|e| Error::from(e))
})
)
}
fn auth_token_post(&self, authorization: &str, token: ::models::Authorization) -> Box<Future<Item = ::models::InlineResponse2001, Error = Error<serde_json::Value>>> {
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
let mut auth_headers = HashMap::<String, String>::new();
let mut auth_query = HashMap::<String, String>::new();
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
auth_headers.insert("Authorization".to_owned(), val);
};
let method = hyper::Method::Post;
let query_string = {
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
for (key, val) in &auth_query {
query.append_pair(key, val);
}
query.finish()
};
let uri_str = format!("{}/auth/token?{}", configuration.base_path, query_string);
// TODO(farcaller): handle error
// if let Err(e) = uri {
// return Box::new(futures::future::err(e));
// }
let mut uri: hyper::Uri = uri_str.parse().unwrap();
let mut req = hyper::Request::new(method, uri);
if let Some(ref user_agent) = configuration.user_agent {
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
}
{
let mut headers = req.headers_mut();
headers.set_raw("Authorization", authorization);
}
for (key, val) in auth_headers {
req.headers_mut().set_raw(key, val);
}
let serialized = serde_json::to_string(&token).unwrap();
req.headers_mut().set(hyper::header::ContentType::json());
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
req.set_body(serialized);
// send request
Box::new(
configuration.client.request(req)
.map_err(|e| Error::from(e))
.and_then(|resp| {
let status = resp.status();
resp.body().concat2()
.and_then(move |body| Ok((status, body)))
.map_err(|e| Error::from(e))
})
.and_then(|(status, body)| {
if status.is_success() {
Ok(body)
} else {
Err(Error::from((status, &*body)))
}
})
.and_then(|body| {
let parsed: Result<::models::InlineResponse2001, _> = serde_json::from_slice(&body);
parsed.map_err(|e| Error::from(e))
})
)
}
fn elections_all_get(&self, authorization: &str) -> Box<Future<Item = ::models::ElectionList, Error = Error<serde_json::Value>>> {
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
let mut auth_headers = HashMap::<String, String>::new();
let mut auth_query = HashMap::<String, String>::new();
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
auth_headers.insert("Authorization".to_owned(), val);
};
let method = hyper::Method::Get;
let query_string = {
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
for (key, val) in &auth_query {
query.append_pair(key, val);
}
query.finish()
};
let uri_str = format!("{}/elections/all?{}", configuration.base_path, query_string);
// TODO(farcaller): handle error
// if let Err(e) = uri {
// return Box::new(futures::future::err(e));
// }
let mut uri: hyper::Uri = uri_str.parse().unwrap();
let mut req = hyper::Request::new(method, uri);
if let Some(ref user_agent) = configuration.user_agent {
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
}
{
let mut headers = req.headers_mut();
headers.set_raw("Authorization", authorization);
}
for (key, val) in auth_headers {
req.headers_mut().set_raw(key, val);
}
// send request
Box::new(
configuration.client.request(req)
.map_err(|e| Error::from(e))
.and_then(|resp| {
let status = resp.status();
resp.body().concat2()
.and_then(move |body| Ok((status, body)))
.map_err(|e| Error::from(e))
})
.and_then(|(status, body)| {
if status.is_success() {
Ok(body)
} else {
Err(Error::from((status, &*body)))
}
})
.and_then(|body| {
let parsed: Result<::models::ElectionList, _> = serde_json::from_slice(&body);
parsed.map_err(|e| Error::from(e))
})
)
}
fn elections_create_post(&self, authorization: &str, election: ::models::Election) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>> {
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
let mut auth_headers = HashMap::<String, String>::new();
let mut auth_query = HashMap::<String, String>::new();
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
auth_headers.insert("Authorization".to_owned(), val);
};
let method = hyper::Method::Post;
let query_string = {
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
for (key, val) in &auth_query {
query.append_pair(key, val);
}
query.finish()
};
let uri_str = format!("{}/elections/create?{}", configuration.base_path, query_string);
// TODO(farcaller): handle error
// if let Err(e) = uri {
// return Box::new(futures::future::err(e));
// }
let mut uri: hyper::Uri = uri_str.parse().unwrap();
let mut req = hyper::Request::new(method, uri);
if let Some(ref user_agent) = configuration.user_agent {
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
}
{
let mut headers = req.headers_mut();
headers.set_raw("Authorization", authorization);
}
for (key, val) in auth_headers {
req.headers_mut().set_raw(key, val);
}
let serialized = serde_json::to_string(&election).unwrap();
req.headers_mut().set(hyper::header::ContentType::json());
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
req.set_body(serialized);
// send request
Box::new(
configuration.client.request(req)
.map_err(|e| Error::from(e))
.and_then(|resp| {
let status = resp.status();
resp.body().concat2()
.and_then(move |body| Ok((status, body)))
.map_err(|e| Error::from(e))
})
.and_then(|(status, body)| {
if status.is_success() {
Ok(body)
} else {
Err(Error::from((status, &*body)))
}
})
.and_then(|body| {
let parsed: Result<::models::Election, _> = serde_json::from_slice(&body);
parsed.map_err(|e| Error::from(e))
})
)
}
fn elections_id_get(&self, authorization: &str, id: &str) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>> {
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
let mut auth_headers = HashMap::<String, String>::new();
let mut auth_query = HashMap::<String, String>::new();
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
auth_headers.insert("Authorization".to_owned(), val);
};
let method = hyper::Method::Get;
let query_string = {
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
for (key, val) in &auth_query {
query.append_pair(key, val);
}
query.finish()
};
let uri_str = format!("{}/elections/{id}?{}", configuration.base_path, query_string, id=id);
// TODO(farcaller): handle error
// if let Err(e) = uri {
// return Box::new(futures::future::err(e));
// }
let mut uri: hyper::Uri = uri_str.parse().unwrap();
let mut req = hyper::Request::new(method, uri);
if let Some(ref user_agent) = configuration.user_agent {
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
}
{
let mut headers = req.headers_mut();
headers.set_raw("Authorization", authorization);
}
for (key, val) in auth_headers {
req.headers_mut().set_raw(key, val);
}
// send request
Box::new(
configuration.client.request(req)
.map_err(|e| Error::from(e))
.and_then(|resp| {
let status = resp.status();
resp.body().concat2()
.and_then(move |body| Ok((status, body)))
.map_err(|e| Error::from(e))
})
.and_then(|(status, body)| {
if status.is_success() {
Ok(body)
} else {
Err(Error::from((status, &*body)))
}
})
.and_then(|body| {
let parsed: Result<::models::Election, _> = serde_json::from_slice(&body);
parsed.map_err(|e| Error::from(e))
})
)
}
fn elections_id_post(&self, authorization: &str, election: ::models::Vote) -> Box<Future<Item = ::models::Vote, Error = Error<serde_json::Value>>> {
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
let mut auth_headers = HashMap::<String, String>::new();
let mut auth_query = HashMap::<String, String>::new();
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
auth_headers.insert("Authorization".to_owned(), val);
};
let method = hyper::Method::Post;
let query_string = {
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
for (key, val) in &auth_query {
query.append_pair(key, val);
}
query.finish()
};
let uri_str = format!("{}/elections/{id}?{}", configuration.base_path, query_string);
// TODO(farcaller): handle error
// if let Err(e) = uri {
// return Box::new(futures::future::err(e));
// }
let mut uri: hyper::Uri = uri_str.parse().unwrap();
let mut req = hyper::Request::new(method, uri);
if let Some(ref user_agent) = configuration.user_agent {
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
}
{
let mut headers = req.headers_mut();
headers.set_raw("Authorization", authorization);
}
for (key, val) in auth_headers {
req.headers_mut().set_raw(key, val);
}
let serialized = serde_json::to_string(&election).unwrap();
req.headers_mut().set(hyper::header::ContentType::json());
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
req.set_body(serialized);
// send request
Box::new(
configuration.client.request(req)
.map_err(|e| Error::from(e))
.and_then(|resp| {
let status = resp.status();
resp.body().concat2()
.and_then(move |body| Ok((status, body)))
.map_err(|e| Error::from(e))
})
.and_then(|(status, body)| {
if status.is_success() {
Ok(body)
} else {
Err(Error::from((status, &*body)))
}
})
.and_then(|body| {
let parsed: Result<::models::Vote, _> = serde_json::from_slice(&body);
parsed.map_err(|e| Error::from(e))
})
)
}
}

View File

@ -1,57 +0,0 @@
use hyper;
use serde;
use serde_json;
#[derive(Debug)]
pub enum Error<T> {
Hyper(hyper::Error),
Serde(serde_json::Error),
ApiError(ApiError<T>),
}
#[derive(Debug)]
pub struct ApiError<T> {
pub code: hyper::StatusCode,
pub content: Option<T>,
}
impl<'de, T> From<(hyper::StatusCode, &'de [u8])> for Error<T>
where T: serde::Deserialize<'de> {
fn from(e: (hyper::StatusCode, &'de [u8])) -> Self {
if e.1.len() == 0 {
return Error::ApiError(ApiError{
code: e.0,
content: None,
});
}
match serde_json::from_slice::<T>(e.1) {
Ok(t) => Error::ApiError(ApiError{
code: e.0,
content: Some(t),
}),
Err(e) => {
Error::from(e)
}
}
}
}
impl<T> From<hyper::Error> for Error<T> {
fn from(e: hyper::Error) -> Self {
return Error::Hyper(e)
}
}
impl<T> From<serde_json::Error> for Error<T> {
fn from(e: serde_json::Error) -> Self {
return Error::Serde(e)
}
}
use super::models::*;
mod default_api;
pub use self::default_api::{ DefaultApi, DefaultApiClient };
pub mod configuration;
pub mod client;

View File

@ -1,61 +0,0 @@
#[macro_use]
extern crate rocket;
use rocket::form::Form;
use rocket::response::Redirect;
use rocket::State; // Add this line
use rocket::fs::FileServer;
use rocket::serde::json::Json;
use rocket_dyn_templates::Template;
use std::sync::Mutex;
use std::collections::HashMap;
use csv::Writer;
mod voting;
#[derive(rocket::FromForm)]
struct Vote {
option: String,
}
type Votes = Mutex<Writer<std::fs::File>>;
#[post("/vote", data = "<vote>")]
fn vote(vote: Form<Vote>, votes: &State<Votes>) -> Redirect {
let mut writer = votes.lock().unwrap();
writer.write_record(&[vote.option.clone()]).unwrap();
writer.flush().unwrap();
Redirect::to("/")
}
#[post("/results")]
fn results() -> Json<HashMap<String, String>> {
let election_data = voting::csv_to_election_data("votes.csv", 1, "Election".to_string());
let blt = voting::election_data_to_blt(election_data);
let results = voting::run_blt(blt);
Json(results)
}
#[get("/")]
fn index() -> Template {
let context: HashMap<&str, &str> = HashMap::new();
Template::render("index", &context)
}
#[launch]
fn rocket() -> _ {
let file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open("votes.csv")
.unwrap();
let writer = csv::Writer::from_writer(file);
rocket::build()
.attach(Template::fairing())
.manage(Mutex::new(writer))
.mount("/", routes![index, vote])
.mount("/static", FileServer::from("static"))
}

View File

@ -1,88 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct Authorization {
#[serde(rename = "to_date")]
to_date: Option<String>,
#[serde(rename = "from_date")]
from_date: Option<String>,
#[serde(rename = "user")]
user: Option<String>
}
impl Authorization {
pub fn new() -> Authorization {
Authorization {
to_date: None,
from_date: None,
user: None
}
}
pub fn set_to_date(&mut self, to_date: String) {
self.to_date = Some(to_date);
}
pub fn with_to_date(mut self, to_date: String) -> Authorization {
self.to_date = Some(to_date);
self
}
pub fn to_date(&self) -> Option<&String> {
self.to_date.as_ref()
}
pub fn reset_to_date(&mut self) {
self.to_date = None;
}
pub fn set_from_date(&mut self, from_date: String) {
self.from_date = Some(from_date);
}
pub fn with_from_date(mut self, from_date: String) -> Authorization {
self.from_date = Some(from_date);
self
}
pub fn from_date(&self) -> Option<&String> {
self.from_date.as_ref()
}
pub fn reset_from_date(&mut self) {
self.from_date = None;
}
pub fn set_user(&mut self, user: String) {
self.user = Some(user);
}
pub fn with_user(mut self, user: String) -> Authorization {
self.user = Some(user);
self
}
pub fn user(&self) -> Option<&String> {
self.user.as_ref()
}
pub fn reset_user(&mut self) {
self.user = None;
}
}

View File

@ -1,68 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct Credentials {
#[serde(rename = "username")]
username: Option<String>,
#[serde(rename = "password")]
password: Option<String>
}
impl Credentials {
pub fn new() -> Credentials {
Credentials {
username: None,
password: None
}
}
pub fn set_username(&mut self, username: String) {
self.username = Some(username);
}
pub fn with_username(mut self, username: String) -> Credentials {
self.username = Some(username);
self
}
pub fn username(&self) -> Option<&String> {
self.username.as_ref()
}
pub fn reset_username(&mut self) {
self.username = None;
}
pub fn set_password(&mut self, password: String) {
self.password = Some(password);
}
pub fn with_password(mut self, password: String) -> Credentials {
self.password = Some(password);
self
}
pub fn password(&self) -> Option<&String> {
self.password.as_ref()
}
pub fn reset_password(&mut self) {
self.password = None;
}
}

View File

@ -1,168 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct Election {
#[serde(rename = "id")]
id: Option<String>,
#[serde(rename = "username")]
username: Option<String>,
#[serde(rename = "name")]
name: Option<String>,
#[serde(rename = "description")]
description: Option<String>,
#[serde(rename = "start_date")]
start_date: Option<String>,
#[serde(rename = "end_date")]
end_date: Option<String>,
#[serde(rename = "items")]
items: Option<Vec<::models::ElectionItem>>
}
impl Election {
pub fn new() -> Election {
Election {
id: None,
username: None,
name: None,
description: None,
start_date: None,
end_date: None,
items: None
}
}
pub fn set_id(&mut self, id: String) {
self.id = Some(id);
}
pub fn with_id(mut self, id: String) -> Election {
self.id = Some(id);
self
}
pub fn id(&self) -> Option<&String> {
self.id.as_ref()
}
pub fn reset_id(&mut self) {
self.id = None;
}
pub fn set_username(&mut self, username: String) {
self.username = Some(username);
}
pub fn with_username(mut self, username: String) -> Election {
self.username = Some(username);
self
}
pub fn username(&self) -> Option<&String> {
self.username.as_ref()
}
pub fn reset_username(&mut self) {
self.username = None;
}
pub fn set_name(&mut self, name: String) {
self.name = Some(name);
}
pub fn with_name(mut self, name: String) -> Election {
self.name = Some(name);
self
}
pub fn name(&self) -> Option<&String> {
self.name.as_ref()
}
pub fn reset_name(&mut self) {
self.name = None;
}
pub fn set_description(&mut self, description: String) {
self.description = Some(description);
}
pub fn with_description(mut self, description: String) -> Election {
self.description = Some(description);
self
}
pub fn description(&self) -> Option<&String> {
self.description.as_ref()
}
pub fn reset_description(&mut self) {
self.description = None;
}
pub fn set_start_date(&mut self, start_date: String) {
self.start_date = Some(start_date);
}
pub fn with_start_date(mut self, start_date: String) -> Election {
self.start_date = Some(start_date);
self
}
pub fn start_date(&self) -> Option<&String> {
self.start_date.as_ref()
}
pub fn reset_start_date(&mut self) {
self.start_date = None;
}
pub fn set_end_date(&mut self, end_date: String) {
self.end_date = Some(end_date);
}
pub fn with_end_date(mut self, end_date: String) -> Election {
self.end_date = Some(end_date);
self
}
pub fn end_date(&self) -> Option<&String> {
self.end_date.as_ref()
}
pub fn reset_end_date(&mut self) {
self.end_date = None;
}
pub fn set_items(&mut self, items: Vec<::models::ElectionItem>) {
self.items = Some(items);
}
pub fn with_items(mut self, items: Vec<::models::ElectionItem>) -> Election {
self.items = Some(items);
self
}
pub fn items(&self) -> Option<&Vec<::models::ElectionItem>> {
self.items.as_ref()
}
pub fn reset_items(&mut self) {
self.items = None;
}
}

View File

@ -1,68 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct ElectionItem {
#[serde(rename = "id")]
id: Option<String>,
#[serde(rename = "name")]
name: Option<String>
}
impl ElectionItem {
pub fn new() -> ElectionItem {
ElectionItem {
id: None,
name: None
}
}
pub fn set_id(&mut self, id: String) {
self.id = Some(id);
}
pub fn with_id(mut self, id: String) -> ElectionItem {
self.id = Some(id);
self
}
pub fn id(&self) -> Option<&String> {
self.id.as_ref()
}
pub fn reset_id(&mut self) {
self.id = None;
}
pub fn set_name(&mut self, name: String) {
self.name = Some(name);
}
pub fn with_name(mut self, name: String) -> ElectionItem {
self.name = Some(name);
self
}
pub fn name(&self) -> Option<&String> {
self.name.as_ref()
}
pub fn reset_name(&mut self) {
self.name = None;
}
}

View File

@ -1,28 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct ElectionList {
}
impl ElectionList {
pub fn new() -> ElectionList {
ElectionList {
}
}
}

View File

@ -1,48 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct InlineResponse200 {
#[serde(rename = "token")]
token: Option<String>
}
impl InlineResponse200 {
pub fn new() -> InlineResponse200 {
InlineResponse200 {
token: None
}
}
pub fn set_token(&mut self, token: String) {
self.token = Some(token);
}
pub fn with_token(mut self, token: String) -> InlineResponse200 {
self.token = Some(token);
self
}
pub fn token(&self) -> Option<&String> {
self.token.as_ref()
}
pub fn reset_token(&mut self) {
self.token = None;
}
}

View File

@ -1,48 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct InlineResponse2001 {
#[serde(rename = "token")]
token: Option<String>
}
impl InlineResponse2001 {
pub fn new() -> InlineResponse2001 {
InlineResponse2001 {
token: None
}
}
pub fn set_token(&mut self, token: String) {
self.token = Some(token);
}
pub fn with_token(mut self, token: String) -> InlineResponse2001 {
self.token = Some(token);
self
}
pub fn token(&self) -> Option<&String> {
self.token.as_ref()
}
pub fn reset_token(&mut self) {
self.token = None;
}
}

View File

@ -1,23 +0,0 @@
mod authorization;
pub use self::authorization::Authorization;
mod credentials;
pub use self::credentials::Credentials;
mod election;
pub use self::election::Election;
mod election_item;
pub use self::election_item::ElectionItem;
mod election_list;
pub use self::election_list::ElectionList;
mod inline_response_200;
pub use self::inline_response_200::InlineResponse200;
mod inline_response_200_1;
pub use self::inline_response_200_1::InlineResponse2001;
mod user;
pub use self::user::User;
mod vote;
pub use self::vote::Vote;
mod vote_item;
pub use self::vote_item::VoteItem;
// TODO(farcaller): sort out files
pub struct File;

View File

@ -1,88 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct User {
#[serde(rename = "id")]
id: Option<String>,
#[serde(rename = "username")]
username: Option<String>,
#[serde(rename = "password")]
password: Option<String>
}
impl User {
pub fn new() -> User {
User {
id: None,
username: None,
password: None
}
}
pub fn set_id(&mut self, id: String) {
self.id = Some(id);
}
pub fn with_id(mut self, id: String) -> User {
self.id = Some(id);
self
}
pub fn id(&self) -> Option<&String> {
self.id.as_ref()
}
pub fn reset_id(&mut self) {
self.id = None;
}
pub fn set_username(&mut self, username: String) {
self.username = Some(username);
}
pub fn with_username(mut self, username: String) -> User {
self.username = Some(username);
self
}
pub fn username(&self) -> Option<&String> {
self.username.as_ref()
}
pub fn reset_username(&mut self) {
self.username = None;
}
pub fn set_password(&mut self, password: String) {
self.password = Some(password);
}
pub fn with_password(mut self, password: String) -> User {
self.password = Some(password);
self
}
pub fn password(&self) -> Option<&String> {
self.password.as_ref()
}
pub fn reset_password(&mut self) {
self.password = None;
}
}

View File

@ -1,88 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct Vote {
#[serde(rename = "authorization")]
authorization: Option<::models::Authorization>,
#[serde(rename = "userid")]
userid: Option<String>,
#[serde(rename = "data")]
data: Option<Vec<::models::VoteItem>>
}
impl Vote {
pub fn new() -> Vote {
Vote {
authorization: None,
userid: None,
data: None
}
}
pub fn set_authorization(&mut self, authorization: ::models::Authorization) {
self.authorization = Some(authorization);
}
pub fn with_authorization(mut self, authorization: ::models::Authorization) -> Vote {
self.authorization = Some(authorization);
self
}
pub fn authorization(&self) -> Option<&::models::Authorization> {
self.authorization.as_ref()
}
pub fn reset_authorization(&mut self) {
self.authorization = None;
}
pub fn set_userid(&mut self, userid: String) {
self.userid = Some(userid);
}
pub fn with_userid(mut self, userid: String) -> Vote {
self.userid = Some(userid);
self
}
pub fn userid(&self) -> Option<&String> {
self.userid.as_ref()
}
pub fn reset_userid(&mut self) {
self.userid = None;
}
pub fn set_data(&mut self, data: Vec<::models::VoteItem>) {
self.data = Some(data);
}
pub fn with_data(mut self, data: Vec<::models::VoteItem>) -> Vote {
self.data = Some(data);
self
}
pub fn data(&self) -> Option<&Vec<::models::VoteItem>> {
self.data.as_ref()
}
pub fn reset_data(&mut self) {
self.data = None;
}
}

View File

@ -1,68 +0,0 @@
/*
* vote-rs API
*
* API for conducting electronic voting
*
* OpenAPI spec version: 0.0.1
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*/
#[allow(unused_imports)]
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize)]
pub struct VoteItem {
#[serde(rename = "item")]
item: Option<::models::ElectionItem>,
#[serde(rename = "value")]
value: Option<f32>
}
impl VoteItem {
pub fn new() -> VoteItem {
VoteItem {
item: None,
value: None
}
}
pub fn set_item(&mut self, item: ::models::ElectionItem) {
self.item = Some(item);
}
pub fn with_item(mut self, item: ::models::ElectionItem) -> VoteItem {
self.item = Some(item);
self
}
pub fn item(&self) -> Option<&::models::ElectionItem> {
self.item.as_ref()
}
pub fn reset_item(&mut self) {
self.item = None;
}
pub fn set_value(&mut self, value: f32) {
self.value = Some(value);
}
pub fn with_value(mut self, value: f32) -> VoteItem {
self.value = Some(value);
self
}
pub fn value(&self) -> Option<&f32> {
self.value.as_ref()
}
pub fn reset_value(&mut self) {
self.value = None;
}
}

View File

@ -6,46 +6,46 @@
<title>Create Election</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #1a1a1a;
color: #f4f4f4;
color: #9f9f9f;
}
.container {
width: 400px;
margin: 50px auto;
padding: 20px;
width: 25em;
margin: 3.125em auto;
padding: 1.25em;
background-color: #2b2b2b;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-radius: 0.3125em;
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
margin-bottom: 20px;
margin-bottom: 1.25em;
}
input[type="text"],
input[type="datetime-local"],
textarea,
input[type="submit"] {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 0.625em;
margin-bottom: 0.625em;
border: 0.0125em solid #868686;
border-radius: 0.3125em;
box-sizing: border-box;
background-color: #2b2b2b;
color: #f4f4f4;
color: #9f9f9f;
}
textarea {
height: 100px;
height: 6.25em;
background-color: #2b2b2b;
color: #f4f4f4;
color: #9f9f9f;
}
input[type="submit"] {
background-color: #1a75ff; /* Darker blue */
color: white;
cursor: pointer;
border: 0px;
}
input[type="submit"]:hover {
background-color: #145cbf; /* Even darker blue */

View File

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Election Details</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #1a1a1a;
color: #9f9f9f;
}
h2 {
grid-column: span 2;
text-align: center;
margin-bottom: 1.25em;
}
button {
padding: 0.3125em 0.625em;
border: none;
border-radius: 0.3125em;
color: white;
cursor: pointer;
width: 6em;
}
.detail {
width: 48%; /* Adjust as needed */
padding: 0.5em;
background-color: #333; /* Dark gray */
border-radius: 0.3125em;
margin-bottom: 1em;
box-sizing: border-box; /* Add this line */
}
.detail.full-width {
width: 100%; /* Full width */
}
.detail.full-heigth {
height: 100%; /* Full height */
min-height: 8.25em; /* Minimum height */
}
.detail.dates {
display: flex; /* Add this line */
justify-content: space-between; /* Add this line */
}
.detail label {
font-weight: bold;
margin-right: 0.5em;
}
.detail span {
color: #9f9f9f;
}
.go-btn {
background-color: #4CAF50; /* Green */
}
.delete-btn {
background-color: #f44336; /* Red */
}
.results-btn {
background-color: #008CBA; /* Blue */
}
.button-container {
display: flex;
justify-content: space-evenly;
width: 100%;
margin-top: 1em;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
width: 50em;
margin: 5em auto;
padding: 3em;
background-color: #2b2b2b;
border-radius: 0.3125em;
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
}
#electionDetails {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<h2>Election Details</h2>
<div id="electionDetails">
<!-- Election details will be inserted here dynamically -->
</div>
<div class="button-container">
<button class="go-btn">Vote</button>
<button class="delete-btn" onclick="confirmDelete()">Delete</button>
<button class="results-btn" onclick="confirmResults()">Results</button>
</div>
</div>
<script>
function confirmDelete() {
if (confirm("Are you sure you want to delete this election?")) {
// Implement the logic to delete the election
}
}
function confirmResults() {
if (confirm("Are you sure you want to view the results of this election?")) {
// Implement the logic to view the results
}
}
// Dummy data for demonstration
const election = { id: 1, name: "Election 1", username: "user", namespace: "namespace2", description: "Description 1", start_date: "2024-05-01T08:00", end_date: "2024-05-10T20:00" };
// Function to render election details
function renderElectionDetails(election) {
const detailsDiv = document.querySelector("#electionDetails");
detailsDiv.innerHTML = `
<div class="detail"><label>ID:</label> <span>${election.id}</span></div>
<div class="detail"><label>User:</label> <span>${election.username}</span></div>
<div class="detail"><label>Name:</label> <span>${election.name}</span></div>
<div class="detail"><label>Namespace:</label> <span>${election.namespace}</span></div>
<div class="detail full-width full-heigth"><label>Description:</label> <span>${election.description}</span></div>
<div class="detail">Start Date:</label> <span>${new Date(election.start_date).toLocaleString()}</span></div>
<div class="detail">End Date:</label> <span>${new Date(election.end_date).toLocaleString()}</span></div>
`;
}
// Initial rendering of election details
renderElectionDetails(election);
</script>
</body>
</html>

View File

@ -6,199 +6,108 @@
<title>View Elections</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #1a1a1a;
color: #f4f4f4;
color: #9f9f9f;
}
.container {
width: 800px;
margin: 50px auto;
padding: 20px;
width: 60em;
margin: 5em auto;
padding: 3em;
background-color: #2b2b2b;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-radius: 0.3125em;
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
margin-bottom: 20px;
margin-bottom: 1.25em;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="submit"] {
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
background-color: #2b2b2b;
color: #f4f4f4;
}
input[type="submit"] {
background-color: #1a75ff; /* Darker blue */
color: white;
cursor: pointer;
}
input[type="submit"]:hover {
background-color: #145cbf; /* Even darker blue */
}
table {
#searchInput {
width: 100%;
border-collapse: collapse;
color: #f4f4f4;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #2b2b2b;
}
button {
padding: 5px 10px;
margin: 0 5px;
border: none;
border-radius: 5px;
color: white;
cursor: pointer;
padding: 0.5em;
margin-bottom: 4em;
background-color: #363535;
color: #9f9f9f;
border: 0.0625em solid #9f9f9f;
}
#searchForm {
.card {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1em;
background-color: #333;
border-radius: 0.3125em;
margin-bottom: 1em;
}
.go-btn {
button {
padding: 0.3125em 0.625em;
margin: 0 0.3125em;
border: none;
border-radius: 0.3125em;
color: white;
cursor: pointer;
}
.details-btn {
background-color: #4CAF50; /* Green */
}
.delete-btn {
background-color: #f44336; /* Red */
}
.results-btn {
background-color: #008CBA; /* Blue */
}
</style>
</head>
<body>
<div class="container">
<h2>View Elections</h2>
<form id="searchForm" action="#">
<label for="search">Search by Name:</label>
<input type="text" id="search" name="search" placeholder="Enter name to search">
<input type="submit" value="Search">
</form>
<table id="electionsTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>User</th>
<th>Namespace</th>
<th>Description</th>
<th>Start Date</th>
<th>End Date</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<!-- Election rows will be inserted here dynamically -->
</tbody>
</table>
<input id="searchInput" type="text" placeholder="Search elections..." oninput="searchElections(this.value)">
<div id="electionsContainer">
<!-- Election cards will be inserted here dynamically -->
</div>
</div>
<script>
// Dummy data for demonstration
const elections = [
{ id: 1, name: "Election 1", username: "user", namespace: "namespace2", description: "Description 1", start_date: "2024-05-01T08:00", end_date: "2024-05-10T20:00" },
{ id: 2, name: "Election 2", username: "user", namespace: "namespace", description: "Description 2", start_date: "2024-05-05T08:00", end_date: "2024-05-15T20:00" },
{ id: 3, name: "Election 3", username: "user2", namespace: "namespace", description: "Description 3", start_date: "2024-05-10T08:00", end_date: "2024-05-20T20:00" }
{ name: "Election 1", username: "user", namespace: "namespace2" },
{ name: "Election 2", username: "user", namespace: "namespace" },
{ name: "Election 3", username: "user2", namespace: "namespace" }
];
const currentUsername = "user";
// Function to render election rows
function renderElections(elections) {
const tableBody = document.querySelector("#electionsTable tbody");
tableBody.innerHTML = "";
const container = document.querySelector("#electionsContainer");
container.innerHTML = "";
elections.forEach(election => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${election.id}</td>
<td>${election.name}</td>
<td>${election.username}</td>
<td>${election.namespace}</td>
<td>${election.description}</td>
<td>${new Date(election.start_date).toLocaleString()}</td>
<td>${new Date(election.end_date).toLocaleString()}</td>
<td><button class="go-btn" onclick="goToElection(${election.id})">Go to Election</button></td>
${election.username === currentUsername ?
`<td><button class="results-btn" onclick="if(confirm('Are you sure you want to view the results of this election?')) { viewResults(${election.id}) }">View Results</button></td>
<td><button class="delete-btn" onclick="if(confirm('Are you sure you want to delete this election?')) { deleteElection(${election.id}) }">Delete</button></td>`
: '<td></td><td></td>'}
const card = document.createElement("div");
card.className = "card";
card.innerHTML = `
<div>
<h3>${election.name}</h3>
<p>Created by ${election.username} in ${election.namespace}</p>
</div>
<div>
<button class="details-btn" onclick="viewDetails('${election.name}')">Details</button>
${election.username === currentUsername ?
`<button class="delete-btn" onclick="if(confirm('Are you sure you want to delete this election?')) { deleteElection('${election.name}') }">Delete</button>`
: ''}
</div>
`;
tableBody.appendChild(row);
container.appendChild(card);
});
}
// Get the search form and input field
const searchForm = document.querySelector("#searchForm");
const searchInput = document.querySelector("#search");
// Add an event listener to the form submission event
searchForm.addEventListener("submit", function(event) {
// Prevent the form from being submitted
event.preventDefault();
// Get the search term
const searchTerm = searchInput.value.trim().toLowerCase();
// Filter the elections based on the search term
const filteredElections = elections.filter(election =>
election.name.toLowerCase().includes(searchTerm) ||
election.description.toLowerCase().includes(searchTerm) ||
election.namespace.toLowerCase().includes(searchTerm) ||
election.username.toLowerCase().includes(searchTerm)
);
// Sort the elections so that the ones whose name includes the search term come first
filteredElections.sort((a, b) => {
const aNameIncludes = a.name.toLowerCase().includes(searchTerm);
const bNameIncludes = b.name.toLowerCase().includes(searchTerm);
if (aNameIncludes && !bNameIncludes) {
return -1;
} else if (!aNameIncludes && bNameIncludes) {
return 1;
} else {
return 0;
}
});
// Render the filtered elections
renderElections(filteredElections);
});
function goToElection(id) {
// Implement the logic to go to the election page
function searchElections(query) {
const filtered = elections.filter(election => election.name.toLowerCase().includes(query.toLowerCase()));
renderElections(filtered);
}
function deleteElection(id) {
function viewDetails(name) {
// Implement the logic to view the details of the election
}
function deleteElection(name) {
// Implement the logic to delete the election
}
function viewResults(id) {
// Implement the logic to view the results of the election
}
// Initial rendering of elections
renderElections(elections);
</script>
</body>

View File

@ -6,40 +6,40 @@
<title>Give Acces</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #1a1a1a;
color: #f4f4f4;
color: #9f9f9f;
}
.container {
width: 300px;
margin: 100px auto;
padding: 20px;
width: 20em;
margin: 6.25em auto;
padding: 2em;
background-color: #2b2b2b;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-radius: 0.3125em;
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
margin-bottom: 20px;
margin-bottom: 2em;
}
input[type="text"],
input[type="datetime-local"],
input[type="submit"] {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 1em;
margin-bottom: 0.625em;
border: 0.0625em solid #9f9f9f;
border-radius: 0.3125em;
box-sizing: border-box;
background-color: #2b2b2b;
color: #f4f4f4;
color: #9f9f9f;
}
input[type="submit"] {
background-color: #1a75ff; /* Darker blue */
color: white;
cursor: pointer;
border: 0px;
}
input[type="submit"]:hover {
background-color: #145cbf; /* Even darker blue */

View File

@ -6,40 +6,40 @@
<title>Login</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #1a1a1a;
color: #f4f4f4;
color: #9f9f9f;
}
.container {
width: 300px;
margin: 100px auto;
padding: 20px;
width: 20em;
margin: 6.25em auto;
padding: 2em;
background-color: #2b2b2b;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-radius: 0.3125em;
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
margin-bottom: 20px;
margin-bottom: 1.25em;
}
input[type="text"],
input[type="password"],
input[type="submit"] {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 0.625em;
margin-bottom: 0.625em;
border: 0.0625em solid #9f9f9f;
border-radius: 0.3125em;
box-sizing: border-box;
background-color: #2b2b2b;
color: #f4f4f4;
color: #9f9f9f;
}
input[type="submit"] {
background-color: #1a75ff; /* Darker blue */
color: white;
cursor: pointer;
border: 0px;
}
input[type="submit"]:hover {
background-color: #145cbf; /* Even darker blue */

View File

@ -6,48 +6,45 @@
<title>Voting Page</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #1a1a1a;
color: #f4f4f4;
color: #9f9f9f;
}
.container {
width: 600px;
margin: 100px auto;
padding: 20px;
width: 50em;
margin: 5em auto;
padding: 2em;
background-color: #2b2b2b;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-radius: 0.3125em;
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
}
.election-card {
margin-bottom: 20px;
padding: 10px;
margin-bottom: 1.25em;
padding: 0.625em;
background-color: #3b3b3b;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-radius: 0.3125em;
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
margin-bottom: 20px;
margin-bottom: 1.25em;
}
.item {
margin-bottom: 10px;
margin-bottom: 0.625em;
display: flex;
align-items: center;
}
.item input[type="checkbox"] {
margin-right: 10px;
margin-right: 0.625em;
background-color: #2b2b2b;
color: #f4f4f4;
color: #9f9f9f;
}
button {
margin-left: 10px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-left: 0.625em;
padding: 0.625em;
border: 0px;
border-radius: 0.3125em;
box-sizing: border-box;
background-color: #1a75ff; /* Darker blue */
color: white;