From 3db35e87f01175252cb5fb19b0eaa3d0ced1bb05 Mon Sep 17 00:00:00 2001 From: Daiderd Jordan Date: Sat, 13 Jan 2018 13:41:08 +0100 Subject: [PATCH] users: move submodules to separate files --- default.nix | 3 +- modules/users/default.nix | 116 ++++++++++++++++++++++++++++++++ modules/users/group.nix | 35 ++++++++++ modules/users/groups.nix | 95 -------------------------- modules/users/user.nix | 73 ++++++++++++++++++++ modules/users/users.nix | 137 -------------------------------------- 6 files changed, 225 insertions(+), 234 deletions(-) create mode 100644 modules/users/default.nix create mode 100644 modules/users/group.nix delete mode 100644 modules/users/groups.nix create mode 100644 modules/users/user.nix delete mode 100644 modules/users/users.nix diff --git a/default.nix b/default.nix index 930631f..e3648d4 100644 --- a/default.nix +++ b/default.nix @@ -62,8 +62,7 @@ let ./modules/programs/tmux.nix ./modules/programs/vim.nix ./modules/programs/zsh - ./modules/users/users.nix - ./modules/users/groups.nix + ./modules/users ]; }; diff --git a/modules/users/default.nix b/modules/users/default.nix new file mode 100644 index 0000000..fb43265 --- /dev/null +++ b/modules/users/default.nix @@ -0,0 +1,116 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.users; + + group = import ./group.nix; + user = import ./user.nix; + + isCreated = list: name: elem name list; + isDeleted = attrs: name: ! elem name (mapAttrsToList (n: v: v.name) attrs); + + createdGroups = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreated cfg.knownGroups v.name) cfg.groups); + createdUsers = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreated cfg.knownUsers v.name) cfg.users); + deletedGroups = filter (n: isDeleted cfg.groups n) cfg.knownGroups; + deletedUsers = filter (n: isDeleted cfg.users n) cfg.knownUsers; +in + +{ + options = { + users.knownGroups = mkOption { + type = types.listOf types.str; + default = []; + description = "List of groups that should be created and configured."; + }; + + users.knownUsers = mkOption { + type = types.listOf types.str; + default = []; + description = "List of users that should be created and configured."; + }; + + users.groups = mkOption { + type = types.loaOf (types.submodule group); + default = {}; + description = "Configuration for groups."; + }; + + users.users = mkOption { + type = types.loaOf (types.submodule user); + default = {}; + description = "Configuration for users."; + }; + }; + + config = { + + system.activationScripts.groups.text = mkIf (cfg.knownGroups != []) '' + echo "setting up groups..." >&2 + + ${concatMapStringsSep "\n" (v: '' + g=$(dscl . -read '/Groups/${v.name}' PrimaryGroupID 2> /dev/null) || true + g=''${g#PrimaryGroupID: } + if [ -z "$g" ]; then + echo "creating group ${v.name}..." >&2 + dscl . -create '/Groups/${v.name}' PrimaryGroupID ${toString v.gid} + dscl . -create '/Groups/${v.name}' RealName '${v.description}' + else + if [ "$g" -ne ${toString v.gid} ]; then + echo "warning: existing group '${v.name}' has unexpected gid $g, skipping..." >&2 + fi + fi + '') createdGroups} + + ${concatMapStringsSep "\n" (name: '' + g=$(dscl . -read '/Groups/${name}' PrimaryGroupID 2> /dev/null) || true + g=''${g#PrimaryGroupID: } + if [ -n "$g" ]; then + if [ "$g" -gt 501 ]; then + echo "deleting group ${name}..." >&2 + dscl . -delete '/Groups/${name}' 2> /dev/null + else + echo "warning: existing group '${name}' has unexpected gid $g, skipping..." >&2 + fi + fi + '') deletedGroups} + ''; + + system.activationScripts.users.text = mkIf (cfg.knownUsers != []) '' + echo "setting up users..." >&2 + + ${concatMapStringsSep "\n" (v: '' + u=$(dscl . -read '/Users/${v.name}' UniqueID 2> /dev/null) || true + u=''${u#UniqueID: } + if [ -z "$u" ]; then + echo "creating user ${v.name}..." >&2 + dscl . -create '/Users/${v.name}' UniqueID ${toString v.uid} + dscl . -create '/Users/${v.name}' PrimaryGroupID ${toString v.gid} + dscl . -create '/Users/${v.name}' IsHidden ${if v.isHidden then "1" else "0"} + dscl . -create '/Users/${v.name}' RealName '${v.description}' + dscl . -create '/Users/${v.name}' NFSHomeDirectory '${v.home}' + dscl . -create '/Users/${v.name}' UserShell '${v.shell}' + else + if [ "$u" -ne ${toString v.uid} ]; then + echo "warning: existing user '${v.name}' has unexpected uid $u, skipping..." >&2 + fi + fi + '') createdUsers} + + ${concatMapStringsSep "\n" (name: '' + u=$(dscl . -read '/Users/${name}' UniqueID 2> /dev/null) || true + u=''${u#UniqueID: } + if [ -n "$u" ]; then + if [ "$u" -gt 501 ]; then + echo "deleting user ${name}..." >&2 + dscl . -delete '/Users/${name}' 2> /dev/null + else + echo "warning: existing user '${name}' has unexpected uid $u, skipping..." >&2 + fi + fi + '') deletedUsers} + ''; + + }; +} diff --git a/modules/users/group.nix b/modules/users/group.nix new file mode 100644 index 0000000..2f38c9f --- /dev/null +++ b/modules/users/group.nix @@ -0,0 +1,35 @@ +{ name, lib, ... }: + +with lib; + +{ + options = { + gid = mkOption { + type = mkOptionType { + name = "gid"; + check = t: isInt t && t > 501; + }; + description = "The group's GID."; + }; + + name = mkOption { + type = types.str; + description = '' + The group's name. If undefined, the name of the attribute set + will be used. + ''; + }; + + description = mkOption { + type = types.str; + default = ""; + description = "The group's description."; + }; + }; + + config = { + + name = mkDefault name; + + }; +} diff --git a/modules/users/groups.nix b/modules/users/groups.nix deleted file mode 100644 index 58c90da..0000000 --- a/modules/users/groups.nix +++ /dev/null @@ -1,95 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.users; - - isCreatedGroup = name: elem name cfg.knownGroups; - isDeletedGroup = name: ! elem name (mapAttrsToList (n: v: v.name) cfg.groups); - - createdGroups = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreatedGroup v.name) cfg.groups); - deletedGroups = filter (n: isDeletedGroup n) cfg.knownGroups; - - group = - { name, ... }: - { - options = { - gid = mkOption { - type = mkOptionType { - name = "gid"; - check = t: isInt t && t > 501; - }; - description = "The group's GID."; - }; - - name = mkOption { - type = types.str; - description = '' - The group's name. If undefined, the name of the attribute set - will be used. - ''; - }; - - description = mkOption { - type = types.str; - default = ""; - description = "The group's description."; - }; - }; - config = { - name = mkDefault name; - }; - }; -in - -{ - options = { - users.knownGroups = mkOption { - type = types.listOf types.str; - default = []; - description = "List of groups that should be created and configured."; - }; - - users.groups = mkOption { - type = types.loaOf (types.submodule group); - default = {}; - description = "Configuration for groups."; - }; - }; - - config = { - - system.activationScripts.groups.text = mkIf (cfg.knownGroups != []) '' - echo "setting up groups..." >&2 - - ${concatMapStringsSep "\n" (v: '' - g=$(dscl . -read '/Groups/${v.name}' PrimaryGroupID 2> /dev/null) || true - g=''${g#PrimaryGroupID: } - if [ -z "$g" ]; then - echo "creating group ${v.name}..." >&2 - dscl . -create '/Groups/${v.name}' PrimaryGroupID ${toString v.gid} - dscl . -create '/Groups/${v.name}' RealName '${v.description}' - else - if [ "$g" -ne ${toString v.gid} ]; then - echo "warning: existing group '${v.name}' has unexpected gid $g, skipping..." >&2 - fi - fi - '') createdGroups} - - ${concatMapStringsSep "\n" (name: '' - g=$(dscl . -read '/Groups/${name}' PrimaryGroupID 2> /dev/null) || true - g=''${g#PrimaryGroupID: } - if [ -n "$g" ]; then - if [ "$g" -gt 501 ]; then - echo "deleting group ${name}..." >&2 - dscl . -delete '/Groups/${name}' 2> /dev/null - else - echo "warning: existing group '${name}' has unexpected gid $g, skipping..." >&2 - fi - fi - '') deletedGroups} - ''; - - }; -} diff --git a/modules/users/user.nix b/modules/users/user.nix new file mode 100644 index 0000000..8b70225 --- /dev/null +++ b/modules/users/user.nix @@ -0,0 +1,73 @@ +{ name, lib, ... }: + +with lib; + +{ + options = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether this user should be created."; + }; + + name = mkOption { + type = types.str; + description = '' + The name of the user account. If undefined, the name of the + attribute set will be used. + ''; + }; + + description = mkOption { + type = types.str; + default = ""; + example = "Alice Q. User"; + description = '' + A short description of the user account, typically the + user's full name. + ''; + }; + + uid = mkOption { + type = types.int; + description = "The user's UID."; + }; + + gid = mkOption { + type = types.int; + default = 20; + description = "The user's primary group."; + }; + + isHidden = mkOption { + type = types.bool; + default = false; + description = "Whether to make the user account hidden."; + }; + + # extraGroups = mkOption { + # type = types.listOf types.str; + # default = []; + # description = "The user's auxiliary groups."; + # }; + + home = mkOption { + type = types.path; + default = "/var/empty"; + description = "The user's home directory."; + }; + + shell = mkOption { + type = types.either types.shellPackage types.path; + default = "/sbin/nologin"; + example = literalExample "pkgs.bashInteractive"; + description = "The user's shell."; + }; + }; + + config = { + + name = mkDefault name; + + }; +} diff --git a/modules/users/users.nix b/modules/users/users.nix deleted file mode 100644 index f023f10..0000000 --- a/modules/users/users.nix +++ /dev/null @@ -1,137 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.users; - - isCreatedUser = name: elem name cfg.knownUsers; - isDeletedUser = name: ! elem name (mapAttrsToList (n: v: v.name) cfg.users); - - createdUsers = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreatedUser v.name) cfg.users); - deletedUsers = filter (n: isDeletedUser n) cfg.knownUsers; - - user = - { name, ... }: - { - options = { - enable = mkOption { - type = types.bool; - default = true; - description = "Whether this user should be created."; - }; - - name = mkOption { - type = types.str; - description = '' - The name of the user account. If undefined, the name of the - attribute set will be used. - ''; - }; - - description = mkOption { - type = types.str; - default = ""; - example = "Alice Q. User"; - description = '' - A short description of the user account, typically the - user's full name. - ''; - }; - - uid = mkOption { - type = types.int; - description = "The user's UID."; - }; - - gid = mkOption { - type = types.int; - default = 20; - description = "The user's primary group."; - }; - - isHidden = mkOption { - type = types.bool; - default = false; - description = "Whether to make the user account hidden."; - }; - - # extraGroups = mkOption { - # type = types.listOf types.str; - # default = []; - # description = "The user's auxiliary groups."; - # }; - - home = mkOption { - type = types.path; - default = "/var/empty"; - description = "The user's home directory."; - }; - - shell = mkOption { - type = types.either types.shellPackage types.path; - default = "/sbin/nologin"; - example = literalExample "pkgs.bashInteractive"; - description = "The user's shell."; - }; - }; - config = { - name = mkDefault name; - }; - }; -in - -{ - options = { - users.knownUsers = mkOption { - type = types.listOf types.str; - default = []; - description = "List of users that should be created and configured."; - }; - - users.users = mkOption { - type = types.loaOf (types.submodule user); - default = {}; - description = "Configuration for users."; - }; - }; - - config = { - - system.activationScripts.users.text = mkIf (cfg.knownUsers != []) '' - echo "setting up users..." >&2 - - ${concatMapStringsSep "\n" (v: '' - u=$(dscl . -read '/Users/${v.name}' UniqueID 2> /dev/null) || true - u=''${u#UniqueID: } - if [ -z "$u" ]; then - echo "creating user ${v.name}..." >&2 - dscl . -create '/Users/${v.name}' UniqueID ${toString v.uid} - dscl . -create '/Users/${v.name}' PrimaryGroupID ${toString v.gid} - dscl . -create '/Users/${v.name}' IsHidden ${if v.isHidden then "1" else "0"} - dscl . -create '/Users/${v.name}' RealName '${v.description}' - dscl . -create '/Users/${v.name}' NFSHomeDirectory '${v.home}' - dscl . -create '/Users/${v.name}' UserShell '${v.shell}' - else - if [ "$u" -ne ${toString v.uid} ]; then - echo "warning: existing user '${v.name}' has unexpected uid $u, skipping..." >&2 - fi - fi - '') createdUsers} - - ${concatMapStringsSep "\n" (name: '' - u=$(dscl . -read '/Users/${name}' UniqueID 2> /dev/null) || true - u=''${u#UniqueID: } - if [ -n "$u" ]; then - if [ "$u" -gt 501 ]; then - echo "deleting user ${name}..." >&2 - dscl . -delete '/Users/${name}' 2> /dev/null - else - echo "warning: existing user '${name}' has unexpected uid $u, skipping..." >&2 - fi - fi - '') deletedUsers} - ''; - - }; -}