#!/usr/bin/perl -w
#
# pgpw:
# Construct the Postgres password for a given user.
#
# The idea here is that passwords are computed from hash(secret, username).
# This means that we don't have to manage passwords explicitly, but can still
# give out limited access to people safely and don't have to rely on identd
# between multiple machines.
# 
# Use "create user 'foo' with password '...';" within psql to actually make the
# user with the password generated by this script.
#
# Copyright (c) 2005 UK Citizens Online Democracy. All rights reserved.
# Email: chris@mysociety.org; WWW: http://www.mysociety.org/
#

use strict;

use Digest::SHA;
use Errno;
use IO::File;
use Getopt::Long;

my $secret = undef;
my $new_pgpw;

sub pgpw ($) {
    my $user = shift;
    # Although there is currently no difference here, we can use this conditional
    # to update the digest method and length of the string returned if needed.
    if ($new_pgpw) {
        return substr(Digest::SHA::sha512_base64("$secret$user"), 0, 32);
    } else {
        return substr(Digest::SHA::sha512_base64("$secret$user"), 0, 32);
    }
}


GetOptions(
    'new|n' => \$new_pgpw,
);

my $secret_file_suffix = '';
$secret_file_suffix = '.new' if ($new_pgpw);

foreach my $file ($ENV{PGSECRET}, "/etc/mysociety/postgres_secret$secret_file_suffix", "/usr/local/etc/mysociety/postgres_secret$secret_file_suffix") {
    next if (!defined($file));
    my $h = new IO::File($file, O_RDONLY);
    if (!$h) {
        if ($!{ENOENT}) {
            next;
        } else {
            print STDERR "pgpw: opening $file as euid $>: $!\n";
            exit(1);
        }
    }
    $secret = join('', $h->getlines());
    if ($h->error()) {
        print STDERR "pgpw: reading $file as euid $>: $!\n";
        exit(1);
    }
    $h->close();
}

if (!defined($secret)) {
    print STDERR "pgpw: no secret file found e.g. /etc/mysociety/postgres_secret$secret_file_suffix\n";
    exit(1);
}

if (@ARGV == 1) {
    print pgpw($ARGV[0]), "\n";
} else {
    foreach (@ARGV) {
        print "$_: ", pgpw($_), "\n";
    }
}

exit(0);
