# Copyright © 2010 Julian Blake Kongslie # Licensed under the BSD 3-clause license. use strict; use warnings; package Piny::Group; use Moose; use MooseX::StrictConstructor; use Piny::User; # Attributes has 'gid' => ( is => 'ro' , isa => 'Int' , lazy_build => 1 ); has 'name' => ( is => 'ro' , isa => 'Str' , lazy_build => 1 ); has 'grent' => ( is => 'ro' , isa => 'ArrayRef' , lazy_build => 1 , init_arg => undef ); has 'members' => ( is => 'ro' , isa => 'ArrayRef[Piny::User]' , lazy_build => 1 , init_arg => undef ); # Public methods sub add_member { my ( $s, @users ) = @_; foreach my $user ( @users ) { system( "/usr/sbin/adduser", $user->name( ), $s->name( ) ); $user->clear_groups( ); }; $s->clear_members( ); }; sub remove_member { my ( $s, @users ) = @_; foreach my $user ( @users ) { system( "/usr/sbin/deluser", $user->name( ), $s->name( ) ); $user->clear_groups( ); }; $s->clear_members( ); }; # Builder methods # If constructed with just one argument, then # * If that argument is numeric, treat it as a GID. # * Otherwise, treat it as a name. around BUILDARGS => sub { my ( $orig, $class ) = ( shift, shift ); if ( @_ == 1 && ! ref $_[0] ) { if ( $_[0] =~ m/^\d+$/ ) { return $class->$orig( gid => $_[0] ); } else { return $class->$orig( name => $_[0] ); }; } else { return $class->$orig( @_ ); }; }; sub BUILD { my ( $s ) = @_; if ( not ( $s->has_gid( ) or $s->has_name( ) ) ) { die "You must provide either GID or name!"; }; if ( $s->has_gid( ) and $s->has_name( ) ) { die "You must not provide both GID and name!"; }; }; sub _build_gid { my ( $s ) = @_; return $s->grent( )->[2]; }; sub _build_name { my ( $s ) = @_; return $s->grent( )->[0]; }; sub _build_grent { my ( $s ) = @_; if ( $s->has_gid( ) ) { my @res = getgrgid( $s->gid( ) ); die "getgrgid( " . $s->gid( ) . " ) failed: $!" unless @res; return \@res; } elsif ( $s->has_name( ) ) { my @res = getgrnam( $s->name( ) ); die "getgrnam( " . $s->name( ) . " ) failed: $!" unless @res; return \@res; } else { die "Not enough information provided to lookup group!"; }; }; sub _build_members { my ( $s ) = @_; return [ ] if ( $s->grent( )->[3] eq "" ); return [ map { Piny::User->new( name => $_ ) } split( /:/, $s->grent( )->[3] ) ]; }; # Moose boilerplate __PACKAGE__->meta->make_immutable; 1;