{ config, lib, pkgs, ... }: with lib; let systemUserOpts = { username, ... }: { options = with types; { username = mkOption { type = str; description = "The system user's login name."; default = username; }; description = mkOption { type = str; description = "Description of this system user's purpose or role"; }; ldap-hashed-password = mkOption { type = str; description = "LDAP-formatted hashed password for this user. Generate with slappasswd."; }; }; }; userOpts = { username, ... }: { options = with types; { username = mkOption { type = str; description = "The user's login name."; default = username; }; uid = mkOption { type = int; description = "Unique UID number for the user."; }; common-name = mkOption { type = str; description = "The user's common or given name."; }; primary-group = mkOption { type = str; description = "Primary group to which the user belongs."; }; login-shell = mkOption { type = nullOr shellPackage; description = "The user's preferred shell."; }; description = mkOption { type = str; default = "Fudo Member"; description = "A description of this user's role."; }; ldap-hashed-passwd = mkOption { type = nullOr str; description = "LDAP-formatted hashed password, used for email and other services. Use slappasswd to generate the properly-formatted password."; default = null; }; login-hashed-passwd = mkOption { type = nullOr str; description = "Hashed password for shell, used for shell access to hosts. Use mkpasswd to generate the properly-formatted password."; default = null; }; ssh-authorized-keys = mkOption { type = listOf str; description = "SSH public keys this user can use to log in."; default = [ ]; }; home-manager-config = mkOption { type = nullOr attrs; description = "Home Manager configuration for the given user."; default = null; }; home-directory = mkOption { type = nullOr str; description = "Default home directory for the given user."; default = null; }; k5login = mkOption { type = listOf str; description = "List of Kerberos principals that map to this user."; default = [ ]; }; }; }; groupOpts = { group-name, ... }: { options = with types; { group-name = mkOption { type = nullOr str; default = group-name; description = "Group name."; }; description = mkOption { type = str; description = "Description of the group or it's purpose."; }; members = mkOption { type = listOf str; default = [ ]; description = "A list of users who are members of the current group."; }; gid = mkOption { type = int; description = "GID number of the group."; }; }; }; list-includes = list: el: isNull (findFirst (this: this == el) null list); filterExistingUsers = users: group-members: let user-list = attrNames users; in filter (username: list-includes user-list username) group-members; in { options.fudo = { users = mkOption { type = with types; attrsOf (submodule userOpts); description = "Users"; default = { }; }; groups = mkOption { type = with types; attrsOf (submodule groupOpts); description = "Groups"; default = { }; }; system-users = mkOption { type = with types; attrsOf (submodule systemUserOpts); description = "System users (probably not what you're looking for!)"; default = { }; }; }; imports = [ ./users-common.nix ]; config = let sys = import ../system.nix { inherit lib config; }; in { fudo.auth.ldap-server = let ldapUsers = (filterAttrs (username: userOpts: userOpts.ldap-hashed-password != null)) config.fudo.users; in { users = mapAttrs (username: userOpts: { uid = userOpts.uid; group = userOpts.primary-group; common-name = userOpts.common-name; hashed-password = userOpts.ldap-hashed-password; }) ldapUsers; groups = mapAttrs (groupname: groupOpts: { gid = groupOpts.gid-number; description = groupOpts.description; members = filterExistingUsers ldapUsers groupOpts.members; }) config.fudo.groups; system-users = mapAttrs (username: userOpts: { description = userOpts.description; hashed-password = userOpts.ldap-hashed-passwd; }) config.fudo.system-users; }; users = { users = mapAttrs (username: userOpts: { isNormalUser = true; uid = userOpts.uid; createHome = true; description = userOpts.common-name; group = userOpts.primary-group; home = if (userOpts.home-directory != null) then userOpts.home-directory else "/home/${userOpts.primary-group}/${username}"; hashedPassword = userOpts.login-hashed-passwd; openssh.authorizedKeys.keys = userOpts.ssh-authorized-keys; }) sys.local-users; groups = (mapAttrs (groupname: groupOpts: { gid = groupOpts.gid; members = filterExistingUsers sys.local-users groupOpts.members; }) sys.local-groups) // { wheel = { members = sys.local-admins; }; }; }; home-manager = { useGlobalPkgs = true; users = let home-manager-users = filterAttrs (username: userOpts: userOpts.home-manager-config != null) sys.local-users; in mapAttrs (username: userOpts: userOpts.home-manager-config) home-manager-users; # users = let # home-manager-users = # filterAttrs (username: userOpts: userOpts.home-manager-config != null) # local-users; # common-user-config = username: { # home.file.".k5login" = { # source = pkgs.writeText "${username}-k5login" '' # ${concatStringsSep "\n" config.fudo.users.${username}.k5login} # ''; # }; # }; # in mapAttrs (username: userOpts: # userOpts.home-manager-config // (common-user-config username)) # home-manager-users; }; }; }