#! /usr/bin/env perl
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;

use File::Basename;
use lib dirname(__FILE__) . '/../../../lib/perl';
use OVH::Result;
use OVH::Bastion;
use OVH::Bastion::Plugin qw( :DEFAULT help );

my $remainingOptions = OVH::Bastion::Plugin::begin(
    argv    => \@ARGV,
    header  => "create a new bastion account",
    options => {
        'force-key-from=s'    => \my $forceKeyFrom,      # only to be used under root by the install script
        'uid=i'               => \my $uid,
        'account=s'           => \my $account,
        'always-active'       => \my $alwaysActive,
        'pubKey|public-key=s' => \my $pubKey,
        'comment=s'           => \my $comment,
        'uid-auto'            => \my $uidAuto,
        'osh-only'            => \my $oshOnly,
        'max-inactive-days=i' => \my $maxInactiveDays,
        'immutable-key'       => \my $immutableKey,
        'no-key'              => \my $noKey,
        'ttl=s'               => \my $ttl,
    },
    helptext => <<'EOF',
Create a new bastion account

Usage: --osh SCRIPT_NAME --account ACCOUNT <--uid UID|--uid-auto> [OPTIONS]

  --account NAME            Account name to create, NAME must contain only valid UNIX account name characters
  --uid UID                 Account system UID, also see --uid-auto
  --uid-auto                Auto-select an UID from the allowed range (the upper available one will be used)
  --always-active           This account's activation won't be challenged on connection, even if the bastion is globally
                              configured to check for account activation
  --osh-only                This account will only be able to use ``--osh`` commands, and can't connect anywhere through the bastion
  --max-inactive-days DAYS  Set account expiration policy, overriding the global bastion configuration 'accountMaxInactiveDays',
                              setting this option to zero disables account expiration.
  --immutable-key           Deny any subsequent modification of the account key (selfAddKey and selfDelKey are denied)
  --comment '"STRING"'      An optional comment when creating the account. Quote it twice as shown if you're under a shell.
  --public-key '"KEY"'      Account public SSH key to deposit on the bastion, if not present,
                              you'll be prompted interactively for it. Quote it twice as shown if your're under a shell.
  --no-key                  Don't prompt for an SSH key, no ingress public key will be installed
  --ttl SECONDS|DURATION    Time after which the account will be deactivated (amount of seconds, or duration string such as "4d12h15m")
EOF
);

# ugly hack for space-enabled parameter
# XXX should be removed, double quoting fixes the problem, but keep it for compatibility
if (ref $remainingOptions eq 'ARRAY' and @$remainingOptions) {
    $pubKey .= " " . join(" ", @$remainingOptions);
}

#
# code
#
my $fnret;

#
# params check
#

if (!$account) {
    help();
    osh_exit 'ERR_MISSING_PARAMETER', "Missing mandatory parameter 'account'";
}

if (!defined $uid && !$uidAuto) {
    help();
    osh_exit 'ERR_MISSING_PARAMETER', "Missing mandatory parameter --uid or --uid-auto";
}

# quickly ensure these params are not pure bullshit (real check is done by helper script)
if ($account !~ /^[a-z0-9._-]+$/i) {
    osh_exit 'ERR_INVALID_PARAMETER', "Parameter 'account' seems invalid";
}

if (defined $ttl) {
    $fnret = OVH::Bastion::is_valid_ttl(ttl => $ttl);
    $fnret or osh_exit $fnret;
    $ttl = $fnret->value->{'seconds'};
}

if (defined $uid && $uid == 0) {
    osh_exit 'ERR_IN_YOUR_DREAMS', "Tu l'as vu ?";
}

if (defined $uid && $uidAuto) {
    help();
    osh_exit 'ERR_INCOMPATIBLE_PARAMETERS', "Can't use --uid and --uid-auto at the same time";
}

if (defined $pubKey && $noKey) {
    help();
    osh_exit 'ERR_INCOMPATIBLE_PARAMETERS', "Can't use --public-key and --no-key at the same time";
}

if (defined $maxInactiveDays && $maxInactiveDays < 0) {
    help();
    osh_exit 'ERR_INVALID_PARAMETER', "Expected a >= 0 amount of days for --max-inactive-days";
}

if (!$pubKey && !$noKey) {
    osh_info "Please paste the SSH key you want to add.";
    OVH::Bastion::print_accepted_key_algorithms(way => "ingress");
    osh_info "\nPlease ensure your private key is encrypted using a proper passphrase (your paste won't be echoed).";
    $pubKey = <STDIN>;
}

if (!$noKey) {
    $fnret = OVH::Bastion::is_valid_public_key(pubKey => $pubKey, way => 'ingress');
    $fnret or osh_exit $fnret;
}

#
# Now create it
#
my @command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountCreate';
push @command, "--type",    "normal";
push @command, "--account", $account;
push @command, "--pubKey",  $pubKey if !$noKey;
push @command, "--always-active" if $alwaysActive;
push @command, "--comment", $comment if $comment;
push @command, "--uid",     $uid     if defined $uid;
push @command, "--osh-only", if $oshOnly;
push @command, "--max-inactive-days", $maxInactiveDays if defined $maxInactiveDays;
push @command, "--uid-auto"      if $uidAuto;
push @command, "--immutable-key" if $immutableKey;
push @command, '--ttl',            $ttl          if $ttl;
push @command, '--force-key-from', $forceKeyFrom if ($forceKeyFrom && $< == 0 && $> == 0);    # only to be used under root by the install script

osh_exit OVH::Bastion::helper(cmd => \@command);
