refactor: simplify host composition and shared feature config
This commit is contained in:
+54
-19
@@ -1,5 +1,7 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
nonEmptyStrType = lib.types.addCheck lib.types.str (value: lib.stringLength value > 0);
|
||||
|
||||
mkNullableOption =
|
||||
type:
|
||||
lib.mkOption {
|
||||
@@ -10,9 +12,26 @@ let
|
||||
hasSinglePrimaryEmail =
|
||||
user: builtins.length (lib.filter (email: email.primary) (builtins.attrValues user.emails)) == 1;
|
||||
|
||||
scopeEmailCount =
|
||||
scope: user:
|
||||
builtins.length (lib.filter (email: email.scope == scope) (builtins.attrValues user.emails));
|
||||
|
||||
hasAtMostOneScopedEmail = scope: user: scopeEmailCount scope user <= 1;
|
||||
|
||||
requiredSourceControlScopes =
|
||||
user:
|
||||
lib.unique [
|
||||
"personal"
|
||||
user.sourceControl.projectScope
|
||||
];
|
||||
|
||||
hasRequiredScopedEmail =
|
||||
scope: user: scopeEmailCount scope user == 1;
|
||||
|
||||
primaryEmailFallback = {
|
||||
address = "";
|
||||
primary = false;
|
||||
scope = null;
|
||||
type = "";
|
||||
};
|
||||
|
||||
@@ -53,6 +72,8 @@ let
|
||||
type = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
scope = mkNullableOption sourceControlScopeType;
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -62,13 +83,11 @@ let
|
||||
{
|
||||
options = {
|
||||
publicKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
privateKeyPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
type = lib.types.nullOr nonEmptyStrType;
|
||||
default = null;
|
||||
};
|
||||
|
||||
privateKeyPath = mkNullableOption nonEmptyStrType;
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -93,22 +112,10 @@ let
|
||||
}
|
||||
);
|
||||
|
||||
sourceControlProfileType = lib.types.submodule (
|
||||
{ ... }:
|
||||
{
|
||||
options = { };
|
||||
}
|
||||
);
|
||||
|
||||
sourceControlType = lib.types.submodule (
|
||||
{ ... }:
|
||||
{
|
||||
options = {
|
||||
profiles = lib.mkOption {
|
||||
type = lib.types.attrsOf sourceControlProfileType;
|
||||
default = { };
|
||||
};
|
||||
|
||||
projectScope = lib.mkOption {
|
||||
type = sourceControlScopeType;
|
||||
default = "personal";
|
||||
@@ -305,7 +312,22 @@ in
|
||||
config.assertions = lib.mapAttrsToList (userName: user: {
|
||||
assertion = hasSinglePrimaryEmail user;
|
||||
message = "User `${userName}` must define exactly one primary email entry.";
|
||||
}) config.meta.host.users;
|
||||
}) config.meta.host.users
|
||||
++ lib.flatten (
|
||||
lib.mapAttrsToList (userName: user:
|
||||
(map (scope: {
|
||||
assertion = hasAtMostOneScopedEmail scope user;
|
||||
message = "User `${userName}` may define at most one `${scope}` scoped email entry.";
|
||||
}) [
|
||||
"personal"
|
||||
"work"
|
||||
])
|
||||
++ map (scope: {
|
||||
assertion = hasRequiredScopedEmail scope user;
|
||||
message = "User `${userName}` must define exactly one `${scope}` scoped email entry.";
|
||||
}) (requiredSourceControlScopes user)
|
||||
) config.meta.host.users
|
||||
);
|
||||
};
|
||||
|
||||
flake.modules.homeManager.meta =
|
||||
@@ -326,6 +348,19 @@ in
|
||||
config.assertions = lib.optional (config.meta.user != null) {
|
||||
assertion = hasSinglePrimaryEmail config.meta.user;
|
||||
message = "User `${config.meta.user.name}` must define exactly one primary email entry.";
|
||||
};
|
||||
}
|
||||
++ lib.optionals (config.meta.user != null) (
|
||||
(map (scope: {
|
||||
assertion = hasAtMostOneScopedEmail scope config.meta.user;
|
||||
message = "User `${config.meta.user.name}` may define at most one `${scope}` scoped email entry.";
|
||||
}) [
|
||||
"personal"
|
||||
"work"
|
||||
])
|
||||
++ map (scope: {
|
||||
assertion = hasRequiredScopedEmail scope config.meta.user;
|
||||
message = "User `${config.meta.user.name}` must define exactly one `${scope}` scoped email entry.";
|
||||
}) (requiredSourceControlScopes config.meta.user)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user