summaryrefslogtreecommitdiff
path: root/lib/ACME/AutoRedact.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ACME/AutoRedact.pm')
-rw-r--r--lib/ACME/AutoRedact.pm115
1 files changed, 94 insertions, 21 deletions
diff --git a/lib/ACME/AutoRedact.pm b/lib/ACME/AutoRedact.pm
index 0b85712..69d80df 100644
--- a/lib/ACME/AutoRedact.pm
+++ b/lib/ACME/AutoRedact.pm
@@ -7,17 +7,62 @@ use Scalar::Util qw(blessed);
# ABSTRACT: string-like object that can redact its value out of derived strings
+=head1 SYNOPSIS
+
+ my $password_redacted = ACME::AutoRedact->new($password);
+
+ my $complicated_string = "some text with $password_redacted";
+
+ # this gets the password
+ do_thing_with($complicated_string);
+
+ # this gets asterisks
+ { ACME::AutoRedact->redact; log($complicated_string) }
+
+=cut
+
use overload
q{""} => \&stringify,
q{.} => \&concat,
fallback => 1,
;
-sub _build__redacted {
+sub _build_redacted {
my ($self) = @_;
- return '*' x length($self->{value});
+ return q{*} x length($self->{value});
}
+=attr C<value>
+
+The "revealed" string value of this object.
+
+=attr C<redacted>
+
+The "redacted" string value of this object. Defaults to a sequence of
+C<*> as long as the L</value>.
+
+=attr C<default_behaviour>
+
+Either C<redact> or C<reveal> (the default). What the object should do
+when stringifying, absent any specific directive (see L<< /C<redact>
+>> and L<< /C<reveal> >>).
+
+=method C<new>
+
+ ACME::AutoRedact->new($string);
+ ACME::AutoRedact->new({ value => $string });
+ ACME::AutoRedact->new({
+ value => $string,
+ redacted => $other_string,
+ default_behaviour => 'redact',
+ });
+
+Constructs a new object; the L</redacted> version defaults to a
+sequence of C<*> as long as the L</value>, the L<default
+bahviour|/default_behaviour> is "reveal".
+
+=cut
+
sub new {
my ($class,@args) = @_;
@@ -32,20 +77,46 @@ sub new {
$self = { @args };
}
bless $self,$class;
- $self->{_redacted} //= $self->_build__redacted;
+ $self->{redacted} //= $self->_build_redacted;
return $self;
}
-our $requested_behaviour;
+our $requested_behaviour; ## no critic(ProhibitPackageVars)
+
+=method C<redact>
+
+ ACME::AutoRedact->redact;
+
+This sets (locally to the scope in which it's called) the
+L</default_behaviour> to be "redact".
+
+=cut
sub redact {
localize *requested_behaviour, \'redact', UP;
}
+=method C<reveal>
+
+ ACME::AutoRedact->reveal;
+
+This sets (locally to the scope in which it's called) the
+L</default_behaviour> to be "reveal".
+
+=cut
+
sub reveal {
localize *requested_behaviour, \'reveal', UP;
}
+=method C<stringify>
+
+Overloaded stringification method. Returns either the normal
+L</value>, or the L</redacted> one, depending on the current
+behaviour.
+
+=cut
+
sub stringify {
my ($self) = @_;
@@ -55,33 +126,35 @@ sub stringify {
return $self->{value};
}
else {
- return $self->{_redacted};
+ return $self->{redacted};
}
}
+=method C<concat>
+
+Overloaded concatenation method. Returns a new object with both normal
+L</value> and L</redacted> value being the (appropriate) concatenation
+of the arguments.
+
+=cut
+
sub concat {
my ($self,$other,$swap) = @_;
my %new;
if ((blessed($other)//'') eq __PACKAGE__) {
- $new{value} = $swap
- ? $other->{value} . $self->{value}
- : $self->{value} . $other->{value};
- $new{_redacted} = $swap
- ? $other->{_redacted} . $self->{_redacted}
- : $self->{_redacted} . $other->{_redacted};
-
- $new{default_behaviour} = $swap
- ? $other->{default_behaviour}
- : $self->{default_behaviour};
+ ($self,$other) = ($other,$self) if $swap;
+ $new{value} = $self->{value} . $other->{value};
+ $new{redacted} = $self->{redacted} . $other->{redacted};
+
+ $new{default_behaviour} = $self->{default_behaviour};
}
else {
- $new{value} = $swap
- ? "$other" . $self->{value}
- : $self->{value} . "$other";
- $new{_redacted} = $swap
- ? "$other" . $self->{_redacted}
- : $self->{_redacted} . "$other";
+ for my $k (qw(value redacted)) {
+ $new{$k} = $swap
+ ? "$other" . $self->{$k}
+ : $self->{$k} . "$other";
+ }
$new{default_behaviour} = $self->{default_behaviour};
}