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