Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions controller/src/application/auth.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use permissions::Permissions;
use server::AuthServer;
use user::AdminUser;

Expand All @@ -10,6 +11,7 @@ pub mod server;
pub mod user;

const DEFAULT_ADMIN_USERNAME: &str = "admin";
const DEFAULT_ADMIN_PERMISSIONS: Permissions = Permissions::ALL;

pub type AuthToken = String;
pub type OwnedAuthorization = Box<dyn GenericAuthorization + Send + Sync>;
Expand All @@ -21,8 +23,7 @@ pub trait GenericAuthorization {
fn get_user(&self) -> Option<&AdminUser>;
fn is_type(&self, auth: AuthType) -> bool;

#[allow(unused)]
fn is_allowed(&self, flag: u32) -> bool;
fn is_allowed(&self, flag: Permissions) -> bool;

fn recreate(&self) -> OwnedAuthorization;
}
Expand Down
34 changes: 26 additions & 8 deletions controller/src/application/auth/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use tokio::{fs, sync::RwLock};
use uuid::Uuid;

use crate::{
application::auth::DEFAULT_ADMIN_USERNAME,
application::auth::{
permissions::Permissions, DEFAULT_ADMIN_PERMISSIONS, DEFAULT_ADMIN_USERNAME,
},
storage::{SaveToTomlFile, Storage},
};

Expand All @@ -34,19 +36,29 @@ impl AuthManager {
.await?
{
info!("Loaded user {}", name);
tokens.insert(value.token().clone(), AdminUser::create(name));
tokens.insert(
value.token().clone(),
AdminUser::create(name, value.permissions().clone()),
);
}

if tokens.is_empty() {
let token = Self::create_user(DEFAULT_ADMIN_USERNAME).await?;
let token =
Self::create_user(DEFAULT_ADMIN_USERNAME, DEFAULT_ADMIN_PERMISSIONS).await?;
info!("-----------------------------------</>");
info!("No users found, created default admin user");
info!("Username: </>{}", DEFAULT_ADMIN_USERNAME);
info!("Token: {}", &token);
info!("-----------------------------------");
info!("Welcome to Atomic Cloud");
info!("-----------------------------------");
tokens.insert(token, AdminUser::create(DEFAULT_ADMIN_USERNAME.to_string()));
tokens.insert(
token,
AdminUser::create(
DEFAULT_ADMIN_USERNAME.to_string(),
DEFAULT_ADMIN_PERMISSIONS,
),
);
}

info!("Loaded {} user(s)", tokens.len());
Expand Down Expand Up @@ -82,13 +94,13 @@ impl AuthManager {
token
}

async fn create_user(username: &str) -> Result<String> {
async fn create_user(username: &str, permissions: Permissions) -> Result<String> {
let token = format!(
"actl_{}{}",
Uuid::new_v4().as_simple(),
Uuid::new_v4().as_simple()
);
StoredUser::new(&token)
StoredUser::new(&token, permissions)
.save(&Storage::user_file(username), true)
.await?;

Expand All @@ -102,21 +114,27 @@ mod stored {
use getset::Getters;
use serde::{Deserialize, Serialize};

use crate::storage::{LoadFromTomlFile, SaveToTomlFile};
use crate::{
application::auth::permissions::Permissions,
storage::{LoadFromTomlFile, SaveToTomlFile},
};

#[derive(Serialize, Deserialize, Getters)]
pub struct StoredUser {
#[getset(get = "pub")]
token: String,
#[getset(get = "pub")]
permissions: Permissions,
}

impl StoredUser {
pub fn new<'a, T>(token: T) -> Self
pub fn new<'a, T>(token: T, permissions: Permissions) -> Self
where
T: Into<Cow<'a, str>>,
{
Self {
token: token.into().into_owned(),
permissions,
}
}
}
Expand Down
40 changes: 32 additions & 8 deletions controller/src/application/auth/permissions.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
use bitflags::bitflags;
use serde::{Deserialize, Serialize};

bitflags! {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
#[serde(transparent)]
pub struct Permissions: u32 {
const READ = 1;
const WRITE = 1 << 1;
const EXECUTE = 1 << 2;
const DELETE = 1 << 3;
const CREATE = 1 << 4;
const MODIFY = 1 << 5;
const LIST = 1 << 6;
const ALL = Self::READ.bits() | Self::WRITE.bits() | Self::EXECUTE.bits() | Self::DELETE.bits() | Self::CREATE.bits() | Self::MODIFY.bits() | Self::LIST.bits();
const REQUEST_STOP = 1;

const SET_RESOURCE = 1 << 1;
const DELETE_RESOURCE = 1 << 2;

const CREATE_NODE = 1 << 3;
const UPDATE_NODE = 1 << 4;
const GET_NODE = 1 << 5;

const CREATE_GROUP = 1 << 6;
const UPDATE_GROUP = 1 << 7;
const GET_GROUP = 1 << 8;

const SCHEDULE_SERVER = 1 << 9;
const GET_SERVER = 1 << 10;

const WRITE_TO_SCREEN = 1 << 11;
const READ_SCREEN = 1 << 12;

const GET_USER = 1 << 13;

const TRANSFER_USER = 1 << 14;

const READ_POWER_EVENTS = 1 << 15;
const READ_READY_EVENTS = 1 << 16;

const LIST = 1 << 17;

const ALL = Self::REQUEST_STOP.bits() | Self::SET_RESOURCE.bits() | Self::DELETE_RESOURCE.bits() | Self::CREATE_NODE.bits() | Self::UPDATE_NODE.bits() | Self::GET_NODE.bits() | Self::CREATE_GROUP.bits() | Self::UPDATE_GROUP.bits() | Self::GET_GROUP.bits() | Self::SCHEDULE_SERVER.bits() | Self::GET_SERVER.bits() | Self::WRITE_TO_SCREEN.bits() | Self::READ_SCREEN.bits() | Self::GET_USER.bits() | Self::TRANSFER_USER.bits() | Self::READ_POWER_EVENTS.bits() | Self::READ_READY_EVENTS.bits() | Self::LIST.bits();
}
}
7 changes: 5 additions & 2 deletions controller/src/application/auth/server.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use getset::Getters;
use uuid::Uuid;

use super::{user::AdminUser, AuthType, GenericAuthorization, OwnedAuthorization};
use super::{
permissions::Permissions, user::AdminUser, AuthType, GenericAuthorization, OwnedAuthorization,
};

#[derive(Getters)]
pub struct AuthServer {
Expand All @@ -10,7 +12,8 @@ pub struct AuthServer {
}

impl GenericAuthorization for AuthServer {
fn is_allowed(&self, _flag: u32) -> bool {
fn is_allowed(&self, _flag: Permissions) -> bool {
// Server are allowed to do everything in there extra "client" gRPC area
true
}

Expand Down
20 changes: 14 additions & 6 deletions controller/src/application/auth/user.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use getset::Getters;

use super::{server::AuthServer, AuthType, GenericAuthorization, OwnedAuthorization};
use super::{
permissions::Permissions, server::AuthServer, AuthType, GenericAuthorization,
OwnedAuthorization,
};

#[derive(Getters)]
pub struct AdminUser {
#[getset(get = "pub")]
username: String,
#[getset(get = "pub")]
permissions: Permissions,
}

impl GenericAuthorization for AdminUser {
fn is_allowed(&self, _flag: u32) -> bool {
true
fn is_allowed(&self, flag: Permissions) -> bool {
self.permissions.contains(flag)
}

fn get_user(&self) -> Option<&AdminUser> {
Expand All @@ -24,12 +29,15 @@ impl GenericAuthorization for AdminUser {
}

fn recreate(&self) -> OwnedAuthorization {
AdminUser::create(self.username.clone())
AdminUser::create(self.username.clone(), self.permissions.clone())
}
}

impl AdminUser {
pub fn create(username: String) -> OwnedAuthorization {
Box::new(Self { username })
pub fn create(username: String, permissions: Permissions) -> OwnedAuthorization {
Box::new(Self {
username,
permissions,
})
}
}
7 changes: 6 additions & 1 deletion controller/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{net::SocketAddr, time::Duration};
use anyhow::Result;
use serde::Deserialize;
use tokio::fs;
use uuid::Uuid;

use crate::storage::{LoadFromTomlFile, Storage};

Expand Down Expand Up @@ -46,7 +47,11 @@ impl Config {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).await?;
}
fs::write(&path, DEFAULT_CONFIG).await?;
fs::write(
&path,
DEFAULT_CONFIG.replace("%RANDOM%", &Uuid::new_v4().to_string()),
)
.await?;
Self::from_file(&path).await
}
}
Expand Down
Loading