diff --git a/doc/dbus/bus/org.opensuse.Agama.Users1.bus.xml b/doc/dbus/bus/org.opensuse.Agama.Users1.bus.xml
index c5e07f0f2d..fcb0439338 100644
--- a/doc/dbus/bus/org.opensuse.Agama.Users1.bus.xml
+++ b/doc/dbus/bus/org.opensuse.Agama.Users1.bus.xml
@@ -1,10 +1,6 @@
-
+
-
-
-
-
-
@@ -26,10 +22,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -43,7 +51,7 @@
-
+
@@ -53,11 +61,7 @@
-
-
+
-
-
-
diff --git a/doc/dbus/org.opensuse.Agama.Users1.doc.xml b/doc/dbus/org.opensuse.Agama.Users1.doc.xml
index 334469be64..50c3971583 100644
--- a/doc/dbus/org.opensuse.Agama.Users1.doc.xml
+++ b/doc/dbus/org.opensuse.Agama.Users1.doc.xml
@@ -2,49 +2,23 @@
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-
-
+
-
-
-
-
-
-
+
@@ -54,25 +28,7 @@
-
-
-
-
-
-
-
-
+
diff --git a/rust/agama-lib/src/users.rs b/rust/agama-lib/src/users.rs
index 092800dc30..b3cfe15ca2 100644
--- a/rust/agama-lib/src/users.rs
+++ b/rust/agama-lib/src/users.rs
@@ -27,7 +27,7 @@ pub mod proxies;
mod settings;
mod store;
-pub use client::{FirstUser, UsersClient};
+pub use client::{FirstUser, RootUser, UsersClient};
pub use http_client::UsersHTTPClient;
pub use settings::{FirstUserSettings, RootUserSettings, UserSettings};
pub use store::UsersStore;
diff --git a/rust/agama-lib/src/users/client.rs b/rust/agama-lib/src/users/client.rs
index 6faafd8961..d3bace6b63 100644
--- a/rust/agama-lib/src/users/client.rs
+++ b/rust/agama-lib/src/users/client.rs
@@ -20,7 +20,7 @@
//! Implements a client to access Agama's users service.
-use super::proxies::{FirstUser as FirstUserFromDBus, Users1Proxy};
+use super::proxies::{FirstUser as FirstUserFromDBus, RootUser as RootUserFromDBus, Users1Proxy};
use crate::error::ServiceError;
use serde::{Deserialize, Serialize};
use zbus::Connection;
@@ -37,8 +37,6 @@ pub struct FirstUser {
pub password: String,
/// Whether the password is hashed (true) or is plain text (false)
pub hashed_password: bool,
- /// Whether auto-login should enabled or not
- pub autologin: bool,
}
impl FirstUser {
@@ -49,7 +47,42 @@ impl FirstUser {
user_name: data.1,
password: data.2,
hashed_password: data.3,
- autologin: data.4,
+ })
+ }
+}
+
+/// Represents the settings for the first user
+#[derive(Serialize, Deserialize, Clone, Debug, Default, utoipa::ToSchema)]
+#[serde(rename_all = "camelCase")]
+pub struct RootUser {
+ /// Root user password
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub password: Option,
+ /// Whether the password is hashed (true) or is plain text (false or None)
+ pub hashed_password: Option,
+ /// SSH public key
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub ssh_public_key: Option,
+}
+
+impl RootUser {
+ pub fn from_dbus(dbus_data: RootUserFromDBus) -> zbus::Result {
+ let password = if dbus_data.0.is_empty() {
+ None
+ } else {
+ Some(dbus_data.0)
+ };
+
+ let ssh_public_key = if dbus_data.2.is_empty() {
+ None
+ } else {
+ Some(dbus_data.2)
+ };
+
+ Ok(Self {
+ password,
+ hashed_password: Some(dbus_data.1),
+ ssh_public_key,
})
}
}
@@ -72,6 +105,10 @@ impl<'a> UsersClient<'a> {
FirstUser::from_dbus(self.users_proxy.first_user().await)
}
+ pub async fn root_user(&self) -> zbus::Result {
+ RootUser::from_dbus(self.users_proxy.root_user().await?)
+ }
+
/// SetRootPassword method
pub async fn set_root_password(&self, value: &str, hashed: bool) -> Result {
Ok(self.users_proxy.set_root_password(value, hashed).await?)
@@ -81,16 +118,6 @@ impl<'a> UsersClient<'a> {
Ok(self.users_proxy.remove_root_password().await?)
}
- /// Whether the root password is set or not
- pub async fn is_root_password(&self) -> Result {
- Ok(self.users_proxy.root_password_set().await?)
- }
-
- /// Returns the SSH key for the root user
- pub async fn root_ssh_key(&self) -> zbus::Result {
- self.users_proxy.root_sshkey().await
- }
-
/// SetRootSSHKey method
pub async fn set_root_sshkey(&self, value: &str) -> Result {
Ok(self.users_proxy.set_root_sshkey(value).await?)
@@ -107,7 +134,6 @@ impl<'a> UsersClient<'a> {
&first_user.user_name,
&first_user.password,
first_user.hashed_password,
- first_user.autologin,
std::collections::HashMap::new(),
)
.await
diff --git a/rust/agama-lib/src/users/http_client.rs b/rust/agama-lib/src/users/http_client.rs
index 1008ed48d8..8bee230a43 100644
--- a/rust/agama-lib/src/users/http_client.rs
+++ b/rust/agama-lib/src/users/http_client.rs
@@ -18,8 +18,8 @@
// To contact SUSE LLC about this file by physical or electronic mail, you may
// find current contact information at www.suse.com.
-use super::client::FirstUser;
-use crate::users::model::{RootConfig, RootPatchSettings};
+use super::client::{FirstUser, RootUser};
+use crate::users::model::RootPatchSettings;
use crate::{base_http_client::BaseHTTPClient, error::ServiceError};
pub struct UsersHTTPClient {
@@ -46,21 +46,15 @@ impl UsersHTTPClient {
result
}
- async fn root_config(&self) -> Result {
+ pub async fn root_user(&self) -> Result {
self.client.get("/users/root").await
}
- /// Whether the root password is set or not
- pub async fn is_root_password(&self) -> Result {
- let root_config = self.root_config().await?;
- Ok(root_config.password)
- }
-
/// SetRootPassword method.
/// Returns 0 if successful (always, for current backend)
pub async fn set_root_password(&self, value: &str, hashed: bool) -> Result {
let rps = RootPatchSettings {
- sshkey: None,
+ ssh_public_key: None,
password: Some(value.to_owned()),
hashed_password: Some(hashed),
};
@@ -68,17 +62,11 @@ impl UsersHTTPClient {
Ok(ret)
}
- /// Returns the SSH key for the root user
- pub async fn root_ssh_key(&self) -> Result {
- let root_config = self.root_config().await?;
- Ok(root_config.sshkey)
- }
-
/// SetRootSSHKey method.
/// Returns 0 if successful (always, for current backend)
pub async fn set_root_sshkey(&self, value: &str) -> Result {
let rps = RootPatchSettings {
- sshkey: Some(value.to_owned()),
+ ssh_public_key: Some(value.to_owned()),
password: None,
hashed_password: None,
};
diff --git a/rust/agama-lib/src/users/model.rs b/rust/agama-lib/src/users/model.rs
index 90e07fecfe..ce71c9d003 100644
--- a/rust/agama-lib/src/users/model.rs
+++ b/rust/agama-lib/src/users/model.rs
@@ -20,19 +20,11 @@
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Default, Serialize, Deserialize, utoipa::ToSchema)]
-pub struct RootConfig {
- /// returns if password for root is set or not
- pub password: bool,
- /// empty string mean no sshkey is specified
- pub sshkey: String,
-}
-
#[derive(Clone, Debug, Default, Serialize, Deserialize, utoipa::ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct RootPatchSettings {
/// empty string here means remove ssh key for root
- pub sshkey: Option,
+ pub ssh_public_key: Option,
/// empty string here means remove password for root
pub password: Option,
/// specify if patched password is provided in plain text (default) or hashed
diff --git a/rust/agama-lib/src/users/proxies.rs b/rust/agama-lib/src/users/proxies.rs
index f75921b2ee..ecfc1c246c 100644
--- a/rust/agama-lib/src/users/proxies.rs
+++ b/rust/agama-lib/src/users/proxies.rs
@@ -1,4 +1,4 @@
-// Copyright (c) [2024] SUSE LLC
+// Copyright (c) [2024-2025] SUSE LLC
//
// All Rights Reserved.
//
@@ -31,8 +31,8 @@
//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
//! following zbus API can be used:
//!
-//! * [`zbus::fdo::IntrospectableProxy`]
//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
//!
//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
//!
@@ -48,7 +48,6 @@ use zbus::proxy;
/// * user name
/// * password
/// * hashed_password (true = hashed, false = plain text)
-/// * auto-login (enabled or not)
/// * some optional and additional data
// NOTE: Manually added to this file.
pub type FirstUser = (
@@ -56,10 +55,18 @@ pub type FirstUser = (
String,
String,
bool,
- bool,
std::collections::HashMap,
);
+/// Root user as it comes from D-Bus.
+///
+/// It is composed of:
+///
+/// * password (an empty string if it is not set)
+/// * hashed_password (true = hashed, false = plain text)
+/// * SSH public key
+pub type RootUser = (String, bool, String);
+
#[proxy(
default_service = "org.opensuse.Agama.Manager1",
default_path = "/org/opensuse/Agama/Users1",
@@ -80,7 +87,6 @@ pub trait Users1 {
user_name: &str,
password: &str,
hashed_password: bool,
- auto_login: bool,
data: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
) -> zbus::Result<(bool, Vec)>;
@@ -98,11 +104,7 @@ pub trait Users1 {
#[zbus(property)]
fn first_user(&self) -> zbus::Result;
- /// RootPasswordSet property
+ /// RootUser property
#[zbus(property)]
- fn root_password_set(&self) -> zbus::Result;
-
- /// RootSSHKey property
- #[zbus(property, name = "RootSSHKey")]
- fn root_sshkey(&self) -> zbus::Result;
+ fn root_user(&self) -> zbus::Result;
}
diff --git a/rust/agama-lib/src/users/settings.rs b/rust/agama-lib/src/users/settings.rs
index 18da06a493..5aa359958a 100644
--- a/rust/agama-lib/src/users/settings.rs
+++ b/rust/agama-lib/src/users/settings.rs
@@ -45,8 +45,6 @@ pub struct FirstUserSettings {
pub password: Option,
/// Whether the password is hashed or is plain text
pub hashed_password: Option,
- /// Whether auto-login should enabled or not
- pub autologin: Option,
}
/// Root user settings
diff --git a/rust/agama-lib/src/users/store.rs b/rust/agama-lib/src/users/store.rs
index 77995a027f..5235a4b66e 100644
--- a/rust/agama-lib/src/users/store.rs
+++ b/rust/agama-lib/src/users/store.rs
@@ -44,16 +44,17 @@ impl UsersStore {
let first_user = self.users_client.first_user().await?;
let first_user = FirstUserSettings {
user_name: Some(first_user.user_name),
- autologin: Some(first_user.autologin),
full_name: Some(first_user.full_name),
password: Some(first_user.password),
hashed_password: Some(first_user.hashed_password),
};
- let mut root_user = RootUserSettings::default();
- let ssh_public_key = self.users_client.root_ssh_key().await?;
- if !ssh_public_key.is_empty() {
- root_user.ssh_public_key = Some(ssh_public_key)
- }
+ let root_user = self.users_client.root_user().await?;
+ let root_user = RootUserSettings {
+ password: root_user.password,
+ hashed_password: root_user.hashed_password,
+ ssh_public_key: root_user.ssh_public_key,
+ };
+
Ok(UserSettings {
first_user: Some(first_user),
root: Some(root_user),
@@ -76,7 +77,6 @@ impl UsersStore {
let first_user = FirstUser {
user_name: settings.user_name.clone().unwrap_or_default(),
full_name: settings.full_name.clone().unwrap_or_default(),
- autologin: settings.autologin.unwrap_or_default(),
password: settings.password.clone().unwrap_or_default(),
hashed_password: settings.hashed_password.unwrap_or_default(),
};
@@ -128,8 +128,7 @@ mod test {
"fullName": "Tux",
"userName": "tux",
"password": "fish",
- "hashedPassword": false,
- "autologin": true
+ "hashedPassword": false
}"#,
);
});
@@ -139,8 +138,9 @@ mod test {
.header("content-type", "application/json")
.body(
r#"{
- "sshkey": "keykeykey",
- "password": true
+ "sshPublicKey": "keykeykey",
+ "password": "nots3cr3t",
+ "hashedPassword": false
}"#,
);
});
@@ -154,12 +154,11 @@ mod test {
user_name: Some("tux".to_owned()),
password: Some("fish".to_owned()),
hashed_password: Some(false),
- autologin: Some(true),
};
let root_user = RootUserSettings {
// FIXME this is weird: no matter what HTTP reports, we end up with None
- password: None,
- hashed_password: None,
+ password: Some("nots3cr3t".to_owned()),
+ hashed_password: Some(false),
ssh_public_key: Some("keykeykey".to_owned()),
};
let expected = UserSettings {
@@ -184,7 +183,7 @@ mod test {
when.method(PUT)
.path("/api/users/first")
.header("content-type", "application/json")
- .body(r#"{"fullName":"Tux","userName":"tux","password":"fish","hashedPassword":false,"autologin":true}"#);
+ .body(r#"{"fullName":"Tux","userName":"tux","password":"fish","hashedPassword":false}"#);
then.status(200);
});
// note that we use 2 requests for root
@@ -192,14 +191,14 @@ mod test {
when.method(PATCH)
.path("/api/users/root")
.header("content-type", "application/json")
- .body(r#"{"sshkey":null,"password":"1234","hashedPassword":false}"#);
+ .body(r#"{"sshPublicKey":null,"password":"1234","hashedPassword":false}"#);
then.status(200).body("0");
});
let root_mock2 = server.mock(|when, then| {
when.method(PATCH)
.path("/api/users/root")
.header("content-type", "application/json")
- .body(r#"{"sshkey":"keykeykey","password":null,"hashedPassword":null}"#);
+ .body(r#"{"sshPublicKey":"keykeykey","password":null,"hashedPassword":null}"#);
then.status(200).body("0");
});
let url = server.url("/api");
@@ -211,7 +210,6 @@ mod test {
user_name: Some("tux".to_owned()),
password: Some("fish".to_owned()),
hashed_password: Some(false),
- autologin: Some(true),
};
let root_user = RootUserSettings {
password: Some("1234".to_owned()),
diff --git a/rust/agama-server/src/users/web.rs b/rust/agama-server/src/users/web.rs
index 260ec35133..0b7912e74e 100644
--- a/rust/agama-server/src/users/web.rs
+++ b/rust/agama-server/src/users/web.rs
@@ -33,11 +33,7 @@ use crate::{
};
use agama_lib::{
error::ServiceError,
- users::{
- model::{RootConfig, RootPatchSettings},
- proxies::Users1Proxy,
- FirstUser, UsersClient,
- },
+ users::{model::RootPatchSettings, proxies::Users1Proxy, FirstUser, RootUser, UsersClient},
};
use axum::{extract::State, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
use tokio_stream::{Stream, StreamExt};
@@ -54,23 +50,15 @@ struct UsersState<'a> {
/// * `connection`: D-Bus connection to listen for events.
pub async fn users_streams(dbus: zbus::Connection) -> Result {
const FIRST_USER_ID: &str = "first_user";
- const ROOT_PASSWORD_ID: &str = "root_password";
- const ROOT_SSHKEY_ID: &str = "root_sshkey";
- // here we have three streams, but only two events. Reason is
- // that we have three streams from dbus about property change
- // and unify two root user properties into single event to http API
+ const ROOT_USER_ID: &str = "root_user";
let result: EventStreams = vec![
(
FIRST_USER_ID,
Box::pin(first_user_changed_stream(dbus.clone()).await?),
),
(
- ROOT_PASSWORD_ID,
- Box::pin(root_password_changed_stream(dbus.clone()).await?),
- ),
- (
- ROOT_SSHKEY_ID,
- Box::pin(root_ssh_key_changed_stream(dbus.clone()).await?),
+ ROOT_USER_ID,
+ Box::pin(root_user_changed_stream(dbus.clone()).await?),
),
];
@@ -91,7 +79,6 @@ async fn first_user_changed_stream(
user_name: user.1,
password: user.2,
hashed_password: user.3,
- autologin: user.4,
};
return Some(Event::FirstUserChanged(user_struct));
}
@@ -101,39 +88,18 @@ async fn first_user_changed_stream(
Ok(stream)
}
-async fn root_password_changed_stream(
+async fn root_user_changed_stream(
dbus: zbus::Connection,
) -> Result + Send, Error> {
let proxy = Users1Proxy::new(&dbus).await?;
let stream = proxy
- .receive_root_password_set_changed()
+ .receive_root_user_changed()
.await
.then(|change| async move {
- if let Ok(is_set) = change.get().await {
- return Some(Event::RootChanged {
- password: Some(is_set),
- sshkey: None,
- });
- }
- None
- })
- .filter_map(|e| e);
- Ok(stream)
-}
-
-async fn root_ssh_key_changed_stream(
- dbus: zbus::Connection,
-) -> Result + Send, Error> {
- let proxy = Users1Proxy::new(&dbus).await?;
- let stream = proxy
- .receive_root_sshkey_changed()
- .await
- .then(|change| async move {
- if let Ok(key) = change.get().await {
- return Some(Event::RootChanged {
- password: None,
- sshkey: Some(key),
- });
+ if let Ok(user) = change.get().await {
+ if let Ok(root) = RootUser::from_dbus(user) {
+ return Some(Event::RootUserChanged(root));
+ }
}
None
})
@@ -232,7 +198,7 @@ async fn patch_root(
Json(config): Json,
) -> Result {
let mut retcode1 = 0;
- if let Some(key) = config.sshkey {
+ if let Some(key) = config.ssh_public_key {
retcode1 = state.users.set_root_sshkey(&key).await?;
}
@@ -258,13 +224,10 @@ async fn patch_root(
path = "/root",
context_path = "/api/users",
responses(
- (status = 200, description = "Configuration for the root user", body = RootConfig),
+ (status = 200, description = "Configuration for the root user", body = RootUser),
(status = 400, description = "The D-Bus service could not perform the action"),
)
)]
-async fn get_root_config(State(state): State>) -> Result, Error> {
- let password = state.users.is_root_password().await?;
- let sshkey = state.users.root_ssh_key().await?;
- let config = RootConfig { password, sshkey };
- Ok(Json(config))
+async fn get_root_config(State(state): State>) -> Result, Error> {
+ Ok(Json(state.users.root_user().await?))
}
diff --git a/rust/agama-server/src/web/docs/users.rs b/rust/agama-server/src/web/docs/users.rs
index 42034d58a9..4f32219cb4 100644
--- a/rust/agama-server/src/web/docs/users.rs
+++ b/rust/agama-server/src/web/docs/users.rs
@@ -45,7 +45,7 @@ impl ApiDocBuilder for UsersApiDocBuilder {
fn components(&self) -> utoipa::openapi::Components {
ComponentsBuilder::new()
.schema_from::()
- .schema_from::()
+ .schema_from::()
.schema_from::()
.schema_from::()
.schema(
diff --git a/rust/agama-server/src/web/event.rs b/rust/agama-server/src/web/event.rs
index 1fb4d08697..11f5da9ae0 100644
--- a/rust/agama-server/src/web/event.rs
+++ b/rust/agama-server/src/web/event.rs
@@ -33,7 +33,7 @@ use agama_lib::{
},
ISCSINode,
},
- users::FirstUser,
+ users::{FirstUser, RootUser},
};
use serde::Serialize;
use std::collections::HashMap;
@@ -64,10 +64,7 @@ pub enum Event {
},
RegistrationChanged,
FirstUserChanged(FirstUser),
- RootChanged {
- password: Option,
- sshkey: Option,
- },
+ RootUserChanged(RootUser),
NetworkChange {
#[serde(flatten)]
change: NetworkChange,
diff --git a/service/lib/agama/dbus/users.rb b/service/lib/agama/dbus/users.rb
index 57b30a0b82..27fafa3993 100644
--- a/service/lib/agama/dbus/users.rb
+++ b/service/lib/agama/dbus/users.rb
@@ -59,22 +59,20 @@ def issues
private_constant :USERS_INTERFACE
FUSER_SIG = "in FullName:s, in UserName:s, in Password:s, in HashedPassword:b, " \
- "in AutoLogin:b, in data:a{sv}"
+ "in data:a{sv}"
private_constant :FUSER_SIG
dbus_interface USERS_INTERFACE do
- dbus_reader :root_password_set, "b"
+ dbus_reader :root_user, "(sbs)"
- dbus_reader :root_ssh_key, "s", dbus_name: "RootSSHKey"
-
- dbus_reader :first_user, "(sssbba{sv})"
+ dbus_reader :first_user, "(sssba{sv})"
dbus_method :SetRootPassword,
"in Value:s, in Hashed:b, out result:u" do |value, hashed|
logger.info "Setting Root Password"
backend.assign_root_password(value, hashed)
- dbus_properties_changed(USERS_INTERFACE, { "RootPasswordSet" => !value.empty? }, [])
+ dbus_properties_changed(USERS_INTERFACE, { "RootUser" => root_user }, [])
0
end
@@ -82,7 +80,7 @@ def issues
logger.info "Clearing the root password"
backend.remove_root_password
- dbus_properties_changed(USERS_INTERFACE, { "RootPasswordSet" => backend.root_password? },
+ dbus_properties_changed(USERS_INTERFACE, { "RootUser" => root_user },
[])
0
end
@@ -91,18 +89,17 @@ def issues
logger.info "Setting Root ssh key"
backend.root_ssh_key = (value)
- dbus_properties_changed(USERS_INTERFACE, { "RootSSHKey" => value }, [])
+ dbus_properties_changed(USERS_INTERFACE, { "RootUser" => root_user }, [])
0
end
- dbus_method :SetFirstUser,
- # It returns an Struct with the first field with the result of the operation as a boolean
- # and the second parameter as an array of issues found in case of failure
- FUSER_SIG + ", out result:(bas)" do
- |full_name, user_name, password, hashed_password, auto_login, data|
+ # It returns an Struct with the first field with the result of the operation as a boolean
+ # and the second parameter as an array of issues found in case of failure
+ dbus_method :SetFirstUser, FUSER_SIG + ", out result:(bas)" do |full_name, user_name,
+ password, hashed_password, data|
logger.info "Setting first user #{full_name}"
user_issues = backend.assign_first_user(full_name, user_name, password,
- hashed_password, auto_login, data)
+ hashed_password, data)
if user_issues.empty?
dbus_properties_changed(USERS_INTERFACE, { "FirstUser" => first_user }, [])
@@ -129,29 +126,30 @@ def issues
end
end
- def root_ssh_key
- backend.root_ssh_key
+ def root_user
+ root = backend.root_user
+
+ [
+ root.password_content || "",
+ root.password&.value&.encrypted?,
+ root.authorized_keys.first || ""
+ ]
end
def first_user
user = backend.first_user
- return ["", "", "", false, false, {}] unless user
+ return ["", "", "", false, {}] unless user
[
user.full_name,
user.name,
user.password_content || "",
user.password&.value&.encrypted? || false,
- backend.autologin?(user),
{}
]
end
- def root_password_set
- backend.root_password?
- end
-
private
# @return [Agama::Users]
diff --git a/service/lib/agama/users.rb b/service/lib/agama/users.rb
index 7fa0f921de..b47eaac915 100644
--- a/service/lib/agama/users.rb
+++ b/service/lib/agama/users.rb
@@ -42,24 +42,11 @@ def initialize(logger)
update_issues
end
- def root_ssh_key
- root_user.authorized_keys.first || ""
- end
-
def root_ssh_key=(value)
root_user.authorized_keys = [value] # just one supported for now
update_issues
end
- # NOTE: the root user is created if it does not exist
- def root_password?
- !!root_user.password_content
- end
-
- def root_ssh_key?
- !root_ssh_key.empty?
- end
-
def assign_root_password(value, hashed)
pwd = if hashed
Y2Users::Password.create_encrypted(value)
@@ -72,12 +59,18 @@ def assign_root_password(value, hashed)
update_issues
end
- # Whether the given user is configured for autologin
+ # Root user
#
- # @param [Y2Users::User] user
- # @return [Boolean]
- def autologin?(user)
- config.login.autologin_user == user
+ # @return [Y2Users::User]
+ def root_user
+ return @root_user if @root_user
+
+ @root_user = config.users.root
+ return @root_user if @root_user
+
+ @root_user = Y2Users::User.create_root
+ config.attach(@root_user)
+ @root_user
end
# First created user
@@ -100,10 +93,9 @@ def remove_root_password
# @param user_name [String]
# @param password [String]
# @param hashed_password [Boolean] true = hashed password, false = plain text password
- # @param auto_login [Boolean]
# @param _data [Hash]
# @return [Array] the list of fatal issues found
- def assign_first_user(full_name, user_name, password, hashed_password, auto_login, _data)
+ def assign_first_user(full_name, user_name, password, hashed_password, _data)
remove_first_user
user = Y2Users::User.new(user_name)
@@ -118,8 +110,6 @@ def assign_first_user(full_name, user_name, password, hashed_password, auto_logi
return fatal_issues.map(&:message) unless fatal_issues.empty?
config.attach(user)
- config.login ||= Y2Users::LoginConfig.new
- config.login.autologin_user = auto_login ? user : nil
update_issues
[]
end
@@ -190,15 +180,17 @@ def config
@config
end
- def root_user
- return @root_user if @root_user
+ # NOTE: the root user is created if it does not exist
+ def root_password?
+ !!root_user.password_content
+ end
- @root_user = config.users.root
- return @root_user if @root_user
+ def root_ssh_key
+ root_user.authorized_keys.first || ""
+ end
- @root_user = Y2Users::User.create_root
- config.attach(@root_user)
- @root_user
+ def root_ssh_key?
+ !root_ssh_key.empty?
end
end
end
diff --git a/service/test/agama/dbus/users_test.rb b/service/test/agama/dbus/users_test.rb
index 7dc02cf856..4e60be3eae 100644
--- a/service/test/agama/dbus/users_test.rb
+++ b/service/test/agama/dbus/users_test.rb
@@ -70,7 +70,7 @@
let(:user) { nil }
it "returns default data" do
- expect(subject.first_user).to eq(["", "", "", false, false, {}])
+ expect(subject.first_user).to eq(["", "", "", false, {}])
end
end
@@ -84,12 +84,8 @@
password_content: password.value.to_s)
end
- before do
- allow(backend).to receive(:autologin?).with(user).and_return(true)
- end
-
it "returns the first user data" do
- expect(subject.first_user).to eq(["Test user", "test", password.value.to_s, true, true, {}])
+ expect(subject.first_user).to eq(["Test user", "test", password.value.to_s, true, {}])
end
end
end
diff --git a/service/test/agama/users_test.rb b/service/test/agama/users_test.rb
index 38b93ae1c9..848c24934e 100644
--- a/service/test/agama/users_test.rb
+++ b/service/test/agama/users_test.rb
@@ -37,6 +37,13 @@
describe "#assign_root_password" do
let(:root_user) { instance_double(Y2Users::User) }
+ describe "#root_user" do
+ it "returns the root user" do
+ root = subject.root_user
+ expect(root.name).to eq("root")
+ end
+ end
+
context "when the password is hashed" do
it "sets the password as hashed" do
subject.assign_root_password("hashed", true)
@@ -57,31 +64,17 @@
describe "#remove_root_password" do
it "removes the password" do
subject.assign_root_password("12345", false)
- expect { subject.remove_root_password }.to change { subject.root_password? }
- .from(true).to(false)
- end
- end
-
- describe "#root_password?" do
- it "returns true if the root password is set" do
- subject.assign_root_password("12345", false)
- expect(subject.root_password?).to eq(true)
- end
-
- it "returns false if the root password is not set" do
- expect(subject.root_password?).to eq(false)
- end
-
- it "returns true if the root password is set to nil" do
- subject.assign_root_password("", false)
- expect(subject.root_password?).to eq(false)
+ root = subject.root_user
+ expect(root.password).to be_kind_of(Y2Users::Password)
+ subject.remove_root_password
+ expect(root.password).to be_nil
end
end
describe "#assign_first_user" do
context "when the options given do not present any issue" do
it "adds the user to the user's configuration" do
- subject.assign_first_user("Jane Doe", "jane", "12345", false, false, {})
+ subject.assign_first_user("Jane Doe", "jane", "12345", false, {})
user = users_config.users.by_name("jane")
expect(user.full_name).to eq("Jane Doe")
expect(user.password).to eq(Y2Users::Password.create_plain("12345"))
@@ -89,11 +82,11 @@
context "when a first user exists" do
before do
- subject.assign_first_user("Jane Doe", "jane", "12345", false, false, {})
+ subject.assign_first_user("Jane Doe", "jane", "12345", false, {})
end
it "replaces the user with the new one" do
- subject.assign_first_user("John Doe", "john", "12345", false, false, {})
+ subject.assign_first_user("John Doe", "john", "12345", false, {})
user = users_config.users.by_name("jane")
expect(user).to be_nil
@@ -104,23 +97,23 @@
end
it "returns an empty array of issues" do
- issues = subject.assign_first_user("Jane Doe", "jane", "12345", false, false, {})
+ issues = subject.assign_first_user("Jane Doe", "jane", "12345", false, {})
expect(issues).to be_empty
end
end
context "when the given arguments presents some critical error" do
it "does not add the user to the config" do
- subject.assign_first_user("Jonh Doe", "john", "", false, false, {})
+ subject.assign_first_user("Jonh Doe", "john", "", false, {})
user = users_config.users.by_name("john")
expect(user).to be_nil
- subject.assign_first_user("Ldap user", "ldap", "12345", false, false, {})
+ subject.assign_first_user("Ldap user", "ldap", "12345", false, {})
user = users_config.users.by_name("ldap")
expect(user).to be_nil
end
it "returns an array with all the issues" do
- issues = subject.assign_first_user("Root user", "root", "12345", false, false, {})
+ issues = subject.assign_first_user("Root user", "root", "12345", false, {})
expect(issues.size).to eql(1)
end
end
@@ -128,7 +121,7 @@
describe "#remove_first_user" do
before do
- subject.assign_first_user("Jane Doe", "jane", "12345", false, false, {})
+ subject.assign_first_user("Jane Doe", "jane", "12345", false, {})
end
it "removes the already defined first user" do
@@ -156,7 +149,7 @@
end
it "writes system and installer defined users" do
- subject.assign_first_user("Jane Doe", "jane", "12345", false, false, {})
+ subject.assign_first_user("Jane Doe", "jane", "12345", false, {})
expect(Y2Users::Linux::Writer).to receive(:new) do |target_config, _old_config|
user_names = target_config.users.map(&:name)
@@ -196,7 +189,7 @@
context "when a first user is defined" do
before do
- subject.assign_first_user("Jane Doe", "jdoe", "123456", false, false, {})
+ subject.assign_first_user("Jane Doe", "jdoe", "123456", false, {})
end
it "returns an empty list" do