Skip to content

Commit

Permalink
Merge pull request #329 from yast/edit-y2users
Browse files Browse the repository at this point in the history
Edit users
  • Loading branch information
joseivanlopez authored Sep 28, 2021
2 parents 4d5f402 + 77c938e commit ea1c5e7
Show file tree
Hide file tree
Showing 29 changed files with 2,121 additions and 501 deletions.
112 changes: 76 additions & 36 deletions doc/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,57 @@ This document describes the attributes that can be indicated for users and group

The YaST UI for creating and editing a user offers the following attributes:

| UI Field | Y2Users attr | Only when adding | Only when editing | Description |
| :--- | :--- | :--- | :--- | :--- |
| full name | gecos | | | |
| name | name | | | |
| password | password | | | |
| system mail | | | | |
| disable login | * password starting by `!` | | | |
| uid | uid | | | |
| home dir | home | | | | |
| home dir permission | | | | |
| empty home | | yes | | |
| Move to new location | | | yes | |
| Btrfs subvolume | btrfs_subvolume_home | | | |
| Additional info | gecos | | | |
| login shell | shell | | | |
| group | primary_group | | | |
| additional groups | groups | | | |
| ssh public keys | authorized_keys | | | |

### Home management

### Creating a user
| UI Field | Y2Users attr | Usage | Description |
| :--- | :--- | :--- | :--- |
| full name | `#gecos` | add && edit | |
| name | `#name` | add && edit | |
| password | `#password` | add && edit |
| system mail | `#receive_system_mail` | add && edit | See `MailAliases` module |
| disable login | * password starting by `!` | add && edit | |
| uid | `#uid` | add && edit | |
| home dir | `Home#path` | add && edit | |
| home dir permission | `Home#permissions` | add | | `useradd -K HOME_MODE=0755` |
| empty home | `CommitConfig#home_without_skel` | add | | `rm -rf` after creating. No way to ignore `/usr/etc/skel` |
| Move to new location | `CommitConfig#move_home` | edit | |
| Btrfs subvolume | `Home#btrfs_subvol` | add && edit | |
| Additional info | `#gecos` | add && edit | |
| login shell | `#shell` | add && edit | |
| group | `#primary_group` | add && edit | |
| additional groups | `#groups` | add && edit | |
| ssh public keys | `#authorized_keys` | add && edit | |


## Password

The YaST UI for creating and editing a user offers the following attributes for the password:

| UI Field | Y2Users attr | Usage | Description |
| :--- | :--- | :--- | :--- |
| force change | aging == 0 | add && edit | |
| days to warning | warning_period | add && edit | |
| days usable after expiration | inactivity_period | add && edit | |
| max days same password | maximum_age | add && edit | |
| min days same password | minimum_age | add && edit | |
| expiration date | account_expiration | add && edit | |


## Home management

This section describes how the YaST users client behaves when dealing with the user home.

#### Creating a user

* A user can be created with or without home.
* To create a user without home, the *home dir* path should be set to empty.
* The home can be created with or without default content (*empty home* checkbox).
* The home can be created as Btrfs subvolume (*Btrfs subvol* checkbox).
* The home can be created with custom permissions (*Home permissions* field).
* If the home already exists, it asks for adapting ownership.

### Editing a user
#### Editing a user

* If the home path is changed, then a new home is created with the default content.
* If the home already exists, it asks for adapting ownership.
* There is no way to create a new home without content (*empty home* checkbox is not available).
* If the *Move to new location* checkbox is marked, then the content of the old home is moved to the new one and the old home is removed.
* If the *Move to new location* checkbox is not marked, then the old home is kept.
Expand All @@ -47,20 +67,40 @@ The YaST UI for creating and editing a user offers the following attributes:
* If the home path is removed, then the home is removed from the user but the home itself (directory or subvolume) is kept.
* There is no way to remove the home directory/subvolume.

### Deleting a user
#### Deleting a user

* The home is removed too.
* The user is asked whether to keep or remove home.

#### Home representation in `Y2Users`

## Password

The YaST UI for creating and editing a user offers the following attributes for the password:
~~~
Y2Users::Home
#path
#permissions
#btrfs_subvol
~~~

| UI Field | Y2Users attr | Only when adding | Only when editing | Description |
| :--- | :--- | :--- | :--- | :--- |
| force change | aging == 0 | | | |
| days to warning | warning_period | | | |
| days usable after expiration | inactivity_period | | | |
| max days same password | maximum_age | | | |
| min days same password | minimum_age | | | |
| expiration date | account_expiration | | | |
* Use cases
* create a new user with a home (`Home#path` is not empty)
* if the path already exists:
* re-use existing home
* adapt ownership (`CommitConfig#adapt_home_ownership`)
* if the path does not exist:
* create new home as dir/subvolume (`Home#btrfs_subvol`)
* create with/without content (`CommitConfig#home_without_skel`)
* create with custom permissions (`Home#permissions`)
* create a new user without a home (`Home#path` is empty)
* do not create a home on disk
* edit a user and change the home (`Home#path` changes)
* if the path already exists:
* re-use existing home
* adapt ownership (`CommitConfig#adapt_home_ownership`)
* if the path does not exist:
* if the home should be moved (`CommitConfig#move_home`)
* move home
* if the home should not be moved:
* create a home (TODO: Not supported by shadow tools)
* do not remove old home from disk
* edit a user and remove the home (`Home#path` is empty)
* do not remove old home from disk
* delete a user (TODO)
5 changes: 3 additions & 2 deletions src/lib/y2users/autoinst/reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
require "y2users/parsers/shadow"
require "y2users/collision_checker"
require "y2users/user"
require "y2users/home"
require "y2users/group"
require "y2users/password"
require "y2users/useradd_config"
Expand Down Expand Up @@ -154,10 +155,10 @@ def read_users(issues)
res.gecos = [user_section.fullname]
# TODO: handle forename/lastname
res.gid = user_section.gid
res.home = user_section.home
res.home = Home.new(user_section.home)
res.home.btrfs_subvol = user_section.home_btrfs_subvolume
res.shell = user_section.shell
res.uid = user_section.uid
res.btrfs_subvolume_home = user_section.home_btrfs_subvolume
res.password = create_password(user_section)
res.authorized_keys = user_section.authorized_keys
users << res
Expand Down
102 changes: 102 additions & 0 deletions src/lib/y2users/collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Copyright (c) [2021] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "forwardable"

module Y2Users
# Base class for collections
#
# A collection is similar to a ruby Array class, but the collection is intended to provide query
# methods to make easier to work with the collected elements.
#
# @example
# # Collection of named elements (respond to #name method)
# class ExampleCollection < Collection
# def by_name(value)
# selection = elements.select { |e| e.name == value }
#
# self.class.new(selection)
# end
# end
#
# obj1 = NamedObject.new("foo")
# obj2 = NamedObject.new("bar")
# obj3 = NamedObject.new("foo")
#
# collection = ExampleCollection.new([obj1, obj2, obj3])
# collection.by_name("foo") #=> ExampleCollection<obj1, obj3>
# collection.empty? #=> false
class Collection
extend Forwardable

def_delegators :@elements, :each, :select, :find, :reject, :map, :any?, :size, :empty?, :first

# Constructor
#
# @param elements [Array<Object>]
def initialize(elements = [])
@elements = elements
end

# Adds an element to the collection
#
# @raise [FrozenError] see {#check_editable}
#
# @param element [Object]
# @return [self]
def add(element)
check_editable

@elements << element

self
end

# List with all the elements
#
# @return [Array<Object>]
def all
@elements.dup
end

alias_method :to_a, :all

# Generates a new collection with the sum of elements
#
# @param other [Collection]
# @return [Collection]
def +(other)
self.class.new(all + other.all)
end

private

# Checks whether the collection can be modified
#
# Modifications in the list of elements should be prevented when the collection is frozen.
#
# @raise [FrozenError] if the collection is frozen
# @return [Boolean]
def check_editable
return true unless frozen?

raise FrozenError, "can't modify frozen #{self.class}: #{inspect}"
end
end
end
63 changes: 63 additions & 0 deletions src/lib/y2users/commit_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright (c) [2021] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

module Y2Users
# Class for configuring the commit action for a user
#
# Writers can receive a collection of objects of this class (see {CommitConfigCollection}) in
# order to decide what actions to perform over the user. For example, a writer can use the commit
# config to check whether the content of the home directory should be moved or not.
class CommitConfig
# Name of the user this commit config applies to
#
# @return [String]
attr_accessor :username

# Whether the home should be empty after the creation (i.e., do not use skels)
#
# @return [Boolean]
attr_writer :home_without_skel

# Whether to move the content of the current home directory to the new location
#
# @return [Boolean]
attr_writer :move_home

# Whether this user should own the home. This is useful when changing the home to reuse an
# existing directory/subvolume.
#
# @return [Boolean]
attr_writer :adapt_home_ownership

# @return [Boolean]
def home_without_skel?
!!@home_without_skel
end

# @return [Boolean]
def move_home?
!!@move_home
end

# @return [Boolean]
def adapt_home_ownership?
!!@adapt_home_ownership
end
end
end
43 changes: 43 additions & 0 deletions src/lib/y2users/commit_config_collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright (c) [2021] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "y2users/collection"

module Y2Users
# Collection of commit configs
#
# @see CommitConfig
class CommitConfigCollection < Collection
# Constructor
#
# @param commit_configs [Array<CommitConfig>]
def initialize(commit_configs = [])
super
end

# Commit config for the given user
#
# @param value [String] username
# @return [CommitConfig, nil] nil if the collection does not include a commit config for the
# given username
def by_username(value)
find { |c| c.username == value }
end
end
end
Loading

0 comments on commit ea1c5e7

Please sign in to comment.