hydra/src/script/hydra-create-user
2021-09-06 22:13:33 -04:00

122 lines
3.9 KiB
Perl
Executable file

#! /usr/bin/env perl
use strict;
use warnings;
use Hydra::Schema;
use Hydra::Helper::Nix;
use Hydra::Model::DB;
use Getopt::Long qw(:config gnu_getopt);
sub showHelp {
print q%
Usage: hydra-create-user NAME
[--rename-from NAME]
[--type hydra|google|github]
[--full-name FULLNAME]
[--email-address EMAIL-ADDRESS]
[--password PASSWORD]
[--password-hash HASH]
[--wipe-roles]
[--role ROLE]...
Create a new Hydra user account, or update or an existing one. The
--role flag can be given multiple times. If the account already
exists, roles are added to the existing roles unless --wipe-roles is
specified. If --rename-from is given, the specified account is
renamed.
* PASSWORD HASH
The password hash should be an Argon2id hash, which can be generated
via:
$ nix-shell -p libargon2
[nix-shell]$ argon2 "$(LC_ALL=C tr -dc '[:alnum:]' < /dev/urandom | head -c16)" -id -t 3 -k 262144 -p 1 -l 16 -e
foobar
Ctrl^D
$argon2id$v=19$m=262144,t=3,p=1$NFU1QXJRNnc4V1BhQ0NJQg$6GHqjqv5cNDDwZqrqUD0zQ
SHA1 is also accepted, but SHA1 support is deprecated and the user's
password will be upgraded to Argon2id on first login.
Examples:
Create a user with an argon2 password:
$ hydra-create-user alice --password-hash '$argon2id$v=19$m=262144,t=3,p=1$NFU1QXJRNnc4V1BhQ0NJQg$6GHqjqv5cNDDwZqrqUD0zQ' --role admin
Create a user with a password insecurely provided on the commandline:
$ hydra-create-user alice --password foobar --role admin
%;
exit 0;
}
my ($renameFrom, $type, $fullName, $emailAddress, $password, $passwordHash);
my $wipeRoles = 0;
my @roles;
GetOptions("rename-from=s" => \$renameFrom,
"type=s" => \$type,
"full-name=s" => \$fullName,
"email-address=s" => \$emailAddress,
"password=s" => \$password,
"password-hash=s" => \$passwordHash,
"wipe-roles" => \$wipeRoles,
"role=s" => \@roles,
"help" => sub { showHelp() }
) or exit 1;
die "$0: one user name required\n" if scalar @ARGV != 1;
my $userName = $ARGV[0];
die "$0: type must be `hydra', `google' or `github'\n"
if defined $type && $type ne "hydra" && $type ne "google" && $type ne "github";
my $db = Hydra::Model::DB->new();
$db->txn_do(sub {
my $user = $db->resultset('Users')->find({ username => $renameFrom // $userName });
if ($renameFrom) {
die "$0: user `$renameFrom' does not exist\n" unless $user;
$user->update({ username => $userName });
} elsif ($user) {
print STDERR "updating existing user `$userName'\n";
} else {
print STDERR "creating new user `$userName'\n";
$user = $db->resultset('Users')->create(
{ username => $userName, type => "hydra", emailaddress => "", password => "!" });
}
die "$0: Google or GitHub user names must be email addresses\n"
if ($user->type eq "google" || $user->type eq "github") && $userName !~ /\@/;
$user->update({ type => $type }) if defined $type;
$user->update({ fullname => $fullName eq "" ? undef : $fullName }) if defined $fullName;
if ($user->type eq "google" || $user->type eq "github") {
die "$0: Google and GitHub accounts do not have an explicitly set email address.\n"
if defined $emailAddress;
die "$0: Google and GitHub accounts do not have a password.\n"
if defined $password;
die "$0: Google and GitHub accounts do not have a password.\n"
if defined $passwordHash;
$user->update({ emailaddress => $userName, password => "!" });
} else {
$user->update({ emailaddress => $emailAddress }) if defined $emailAddress;
if (defined $password && !(defined $passwordHash)) {
$user->setPassword($password);
}
if (defined $passwordHash) {
$user->setPasswordHash($passwordHash);
}
}
$user->userroles->delete if $wipeRoles;
$user->userroles->update_or_create({ role => $_ }) foreach @roles;
});