mirror of
https://github.com/CachyOS/New-Cli-Installer.git
synced 2025-01-23 14:32:22 +08:00
🧹 move user creation into gucc
This commit is contained in:
parent
4d0abe4a38
commit
32393932e9
@ -19,6 +19,7 @@ add_library(${PROJECT_NAME} SHARED
|
||||
src/luks.cpp include/gucc/luks.hpp
|
||||
src/zfs.cpp include/gucc/zfs.hpp
|
||||
src/btrfs.cpp include/gucc/btrfs.hpp
|
||||
src/user.cpp include/gucc/user.hpp
|
||||
#src/chwd_profiles.cpp src/chwd_profiles.hpp
|
||||
#src/disk.cpp src/disk.hpp
|
||||
)
|
||||
|
@ -11,6 +11,7 @@ auto safe_getenv(const char* env_name) noexcept -> std::string_view;
|
||||
void exec(const std::vector<std::string>& vec) noexcept;
|
||||
auto exec(std::string_view command, bool interactive = false) noexcept -> std::string;
|
||||
void arch_chroot(std::string_view command, std::string_view mountpoint, bool interactive = false) noexcept;
|
||||
auto arch_chroot_checked(std::string_view command, std::string_view mountpoint) noexcept -> bool;
|
||||
|
||||
} // namespace gucc::utils
|
||||
|
||||
|
25
gucc/include/gucc/user.hpp
Normal file
25
gucc/include/gucc/user.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef USER_HPP
|
||||
#define USER_HPP
|
||||
|
||||
#include <string> // for string
|
||||
#include <string_view> // for string_view
|
||||
#include <vector> // for vector
|
||||
|
||||
namespace gucc::user {
|
||||
|
||||
struct UserInfo final {
|
||||
std::string_view username;
|
||||
std::string_view password;
|
||||
std::string_view shell;
|
||||
std::string_view sudoers_group;
|
||||
};
|
||||
|
||||
// Create group on the system
|
||||
auto create_group(std::string_view group, std::string_view mountpoint) noexcept -> bool;
|
||||
|
||||
// Create user on the system
|
||||
auto create_new_user(const user::UserInfo& user_info, const std::vector<std::string>& default_groups, std::string_view mountpoint) noexcept -> bool;
|
||||
|
||||
} // namespace gucc::user
|
||||
|
||||
#endif // USER_HPP
|
@ -9,6 +9,7 @@ gucc_lib = library('gucc',
|
||||
'src/luks.cpp',
|
||||
'src/zfs.cpp',
|
||||
'src/btrfs.cpp',
|
||||
'src/user.cpp',
|
||||
],
|
||||
include_directories : [include_directories('include')],
|
||||
dependencies: deps
|
||||
|
@ -94,10 +94,22 @@ void arch_chroot(std::string_view command, std::string_view mountpoint, bool int
|
||||
const auto& cmd_formatted = fmt::format(FMT_COMPILE("arch-chroot {} {} 2>>/tmp/cachyos-install.log 2>&1"), mountpoint, command);
|
||||
|
||||
#ifdef NDEVENV
|
||||
gucc::utils::exec(cmd_formatted, interactive);
|
||||
utils::exec(cmd_formatted, interactive);
|
||||
#else
|
||||
spdlog::info("Running with arch-chroot(interactive='{}'): '{}'", interactive, cmd_formatted);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto arch_chroot_checked(std::string_view command, std::string_view mountpoint) noexcept -> bool {
|
||||
// TODO(vnepogodin): refactor to move output into variable and print into log
|
||||
const auto& cmd_formatted = fmt::format(FMT_COMPILE("arch-chroot {} {} 2>>/tmp/cachyos-install.log 1>/dev/null"), mountpoint, command);
|
||||
|
||||
#ifdef NDEVENV
|
||||
return utils::exec(cmd_formatted, true) == "0";
|
||||
#else
|
||||
spdlog::info("Running with checked arch-chroot: '{}'", cmd_formatted);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace gucc::utils
|
||||
|
129
gucc/src/user.cpp
Normal file
129
gucc/src/user.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
#include "gucc/user.hpp"
|
||||
#include "gucc/io_utils.hpp"
|
||||
#include "gucc/string_utils.hpp"
|
||||
|
||||
#include <algorithm> // for find
|
||||
#include <filesystem>
|
||||
#include <fstream> // for ofstream
|
||||
|
||||
#include <fmt/compile.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
|
||||
#include <range/v3/algorithm/contains.hpp>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
namespace gucc::user {
|
||||
|
||||
auto create_group(std::string_view group, std::string_view mountpoint) noexcept -> bool {
|
||||
// TODO(vnepogodin):
|
||||
// 1. add parameter to check if the group was already created
|
||||
// 2. add parameter if the group should be --system group
|
||||
const auto& cmd = fmt::format(FMT_COMPILE("groupadd {}"), group);
|
||||
return utils::arch_chroot_checked(cmd, mountpoint);
|
||||
}
|
||||
|
||||
auto create_new_user(const user::UserInfo& user_info, const std::vector<std::string>& default_groups, std::string_view mountpoint) noexcept -> bool {
|
||||
if (!user_info.sudoers_group.empty() && !ranges::contains(default_groups, user_info.sudoers_group)) {
|
||||
spdlog::error("Failed to create user {}! User default groups doesn't contain sudoers group({})", user_info.username, user_info.sudoers_group);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create needed groups
|
||||
for (const auto& default_group : default_groups) {
|
||||
if (!user::create_group(default_group, mountpoint)) {
|
||||
spdlog::error("Failed to create group {}", default_group);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the user
|
||||
spdlog::info("Creating user {}", user_info.username);
|
||||
const auto& usercmd = [](auto&& username, auto&& user_shell) -> std::string {
|
||||
using namespace std::string_view_literals;
|
||||
static constexpr auto USER_BASE_CMD = "useradd -m -U"sv;
|
||||
if (!user_shell.empty()) {
|
||||
return fmt::format(FMT_COMPILE("{} -s {} {}"), USER_BASE_CMD, user_shell, username);
|
||||
}
|
||||
return fmt::format(FMT_COMPILE("{} {}"), USER_BASE_CMD, username);
|
||||
}(user_info.username, user_info.shell);
|
||||
|
||||
if (!utils::arch_chroot_checked(usercmd, mountpoint)) {
|
||||
spdlog::error("Failed to create user with {}", usercmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set user groups
|
||||
spdlog::info("Setting groups for user {}", user_info.username);
|
||||
const auto& groups_set_cmd = fmt::format(FMT_COMPILE("usermod -aG {} {}"), utils::join(default_groups, ","), user_info.username);
|
||||
if (!utils::arch_chroot_checked(groups_set_cmd, mountpoint)) {
|
||||
spdlog::error("Failed to set user groups with {}", groups_set_cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup user permissions
|
||||
spdlog::info("Setting user permissions for {}", user_info.username);
|
||||
const auto& user_group = fmt::format(FMT_COMPILE("{0}:{0}"), user_info.username);
|
||||
const auto& user_homedir = fmt::format(FMT_COMPILE("/home/{}"), user_info.username);
|
||||
const auto& setup_cmd = fmt::format(FMT_COMPILE("chown -R {} {}"), user_group, user_homedir);
|
||||
if (!utils::arch_chroot_checked(setup_cmd, mountpoint)) {
|
||||
spdlog::error("Failed to setup user permissions on {} as {}", user_homedir, user_group);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(vnepogodin): should encrypt user password properly here
|
||||
const auto& encrypted_passwd = utils::exec(fmt::format(FMT_COMPILE("openssl passwd {}"), user_info.password));
|
||||
const auto& password_set_cmd = fmt::format(FMT_COMPILE("usermod -p '{}' {}"), encrypted_passwd, user_info.username);
|
||||
if (!utils::arch_chroot_checked(password_set_cmd, mountpoint)) {
|
||||
spdlog::error("Failed to set password for user {}", user_info.username);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup sudoers
|
||||
if (user_info.sudoers_group.empty()) {
|
||||
spdlog::info("skipping sudoers group is empty");
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto& sudoers_filepath = fmt::format(FMT_COMPILE("{}/etc/sudoers.d/10-installer"), mountpoint);
|
||||
{
|
||||
const auto& sudoers_line = fmt::format(FMT_COMPILE("%{} ALL=(ALL) ALL\n"), user_info.sudoers_group);
|
||||
std::ofstream sudoers_file{sudoers_filepath, std::ios::out | std::ios::trunc};
|
||||
if (!sudoers_file.is_open()) {
|
||||
spdlog::error("Failed to open sudoers for writing {}", sudoers_filepath);
|
||||
return false;
|
||||
}
|
||||
sudoers_file << sudoers_line;
|
||||
}
|
||||
|
||||
std::error_code err{};
|
||||
fs::permissions(sudoers_filepath,
|
||||
fs::perms::owner_read | fs::perms::group_read, // 0440
|
||||
fs::perm_options::replace, err);
|
||||
if (err) {
|
||||
spdlog::error("Failed to set permissions for sudoers file: {}", err.message());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace gucc::user
|
@ -13,6 +13,7 @@
|
||||
#include "gucc/luks.hpp"
|
||||
#include "gucc/pacmanconf_repo.hpp"
|
||||
#include "gucc/string_utils.hpp"
|
||||
#include "gucc/user.hpp"
|
||||
|
||||
#include <algorithm> // for transform
|
||||
#include <array> // for array
|
||||
@ -470,29 +471,18 @@ void create_new_user(const std::string_view& user, const std::string_view& passw
|
||||
}
|
||||
}
|
||||
|
||||
// Create the user, set password, then remove temporary password file
|
||||
utils::arch_chroot("groupadd sudo", false);
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("groupadd {}"), user), false);
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("useradd {0} -m -g {0} -G sudo,storage,power,network,video,audio,lp,sys,input -s {1}"), user, shell), false);
|
||||
spdlog::info("add user to groups");
|
||||
|
||||
// check if user has been created
|
||||
const auto& user_check = gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} getent passwd {}"), mountpoint, user));
|
||||
if (user_check.empty()) {
|
||||
spdlog::error("User has not been created!");
|
||||
}
|
||||
std::error_code err{};
|
||||
gucc::utils::exec(fmt::format(FMT_COMPILE("echo -e \"{0}\\n{0}\" > /tmp/.passwd"), password));
|
||||
const auto& ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd {} < /tmp/.passwd &>/dev/null"), mountpoint, user), true);
|
||||
spdlog::info("create user pwd: {}", ret_status);
|
||||
fs::remove("/tmp/.passwd", err);
|
||||
|
||||
// Set up basic configuration files and permissions for user
|
||||
// arch_chroot "cp /etc/skel/.bashrc /home/${USER}"
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("chown -R {0}:{0} /home/{0}"), user), false);
|
||||
const auto& sudoers_file = fmt::format(FMT_COMPILE("{}/etc/sudoers"), mountpoint);
|
||||
if (fs::exists(sudoers_file)) {
|
||||
gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i '/NOPASSWD/!s/# %sudo/%sudo/g' {}"), sudoers_file));
|
||||
// Create user with sudoers and default groups
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
const gucc::user::UserInfo user_info{
|
||||
.username = user,
|
||||
.password = password,
|
||||
.shell = shell,
|
||||
.sudoers_group = "sudo"sv,
|
||||
};
|
||||
const std::vector default_user_groups{"sudo"s, "storage"s, "power"s, "network"s, "video"s, "audio"s, "lp"s, "sys"s, "input"s};
|
||||
if (!gucc::user::create_new_user(user_info, default_user_groups, mountpoint)) {
|
||||
spdlog::error("Failed to create user");
|
||||
}
|
||||
#else
|
||||
spdlog::debug("user := {}, password := {}", user, password);
|
||||
@ -1768,6 +1758,7 @@ void enable_autologin([[maybe_unused]] const std::string_view& dm, [[maybe_unuse
|
||||
gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^#autologin-user=/autologin-user={}/' /mnt/etc/lightdm/lightdm.conf"), user));
|
||||
gucc::utils::exec("sed -i 's/^#autologin-user-timeout=0/autologin-user-timeout=0/' /mnt/etc/lightdm/lightdm.conf");
|
||||
|
||||
// TODO(vnepogodin): refactor with gucc
|
||||
utils::arch_chroot("groupadd -r autologin", false);
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("gpasswd -a {} autologin"), user), false);
|
||||
} else if (dm == "sddm") {
|
||||
|
Loading…
Reference in New Issue
Block a user