# ================================================================== # Gossamer Mail - enhanced email management system # # Website : http://gossamer-threads.com/ # Support : http://gossamer-threads.com/scripts/support/ # Revision : $Id: User.pm,v 1.49 2002/06/05 21:56:48 brewt Exp $ # # Copyright (c) 2001 Gossamer Threads Inc. All Rights Reserved. # Redistribution in part or in whole strictly prohibited. Please # see LICENSE file for full details. # ================================================================== # # Description: User module for Gossamer Mail. # package GMail::User; # ================================================================== # Pragmas use strict; use vars qw/$DEBUG @ISA $ERRORS/; # Internal modules use GMail qw{:folders :objects ADMIN}; use GMail::Auth; # Globals @ISA = qw(GMail); $ERRORS = { BADUSERNAME => 'Users name is not formated correctly. The name must be a full email address: (%s)' }; sub PREFS_VERSION () { '2.0.0' } sub load_user { # ------------------------------------------------------------------------------------ # This method should be called to load a user. The first argument is the user name. # If the user does not exist they will be created unless you specify a true second # argument, then it will just return false. # my ($self, $user, $no_check) = @_; my ($tb, $sth, $rec, $uid); $tb = $DB->table('users'); $sth = $tb->select({ email => $user }); my $init; if (!$user) { die "No user!"; } if (!$sth->rows and $no_check) { return } if (!$sth->rows) { $init = 1; $uid = $self->default_create($user); $sth = $tb->select({ userid => $uid }); } $rec = $sth->fetchrow_hashref; for (keys %{$rec}) { $self->{$_} = $rec->{$_} } $rec = $self->load_dgraph($self->{userid}); for (keys %{$rec}) { $self->{$_} = $rec->{$_} } ($self->{username}, $self->{domain}) = split(/\@/ => $self->{email}); $self->{dir} = $self->get_user_directory ($self->{email}); if (!-d $self->{dir}) { $self->create_directories; } # Get the users options. if (-e "$self->{dir}/.prefs") { $self->{opts} = do "$self->{dir}/.prefs"; } if ($init) { $self->create_files; $self->insert_welcome; } elsif (!$self->{opts}->{version} or $self->{opts}->{version} ne PREFS_VERSION) { $self->create_files; } # Set display defaults my $t = $self->template_set; for (keys %{$CFG->{display}}) { $self->{opts}->{display}->{$t}->{$_} = $CFG->{display}->{$_} unless exists $self->{opts}->{display}->{$t}->{$_}; } return $self; } sub load_dgraph { # ------------------------------------------------------------------------------------ # This method called to load the users demographics information out of the dgraph # database into self. Takes an argument of the users ID to look up. Returns a # hash of the key value pairs from the database. # my ($self, $uid) = @_; my ($tb, $sth); # Get the user out of the dgraph table. $tb = $DB->table('dgraph'); return $tb->get($uid); } sub default_create { # ------------------------------------------------------------------------------------ # Creates a user with all default settings. The only argument is the the user name of # the user to create. This assumes the user is already in the main auth systems. # my ($self, $user) = @_; # Insert the user in the user table my $uid = $PLG->dispatch('GMail::User::insert_user', sub { $self->insert_user(@_) }, $user); # Insert user into the demographics table $PLG->dispatch('GMail::User::insert_dgraph', sub { $self->insert_dgraph(@_) }, $uid); # Create folder $PLG->dispatch('GMail::User::insert_folders', sub { $self->insert_folders(@_) }, $uid); return $uid; } sub insert_dgraph { my ($self, $uid) = @_; my $tb = $DB->table('dgraph'); $tb->insert({ dgraph_userid => $uid }); } sub insert_user { my ($self, $user) = @_; my $tb = $DB->table('users'); my $insert = { map { 'users_' . $_ => $CFG->{defaults}->{$_} } keys %{$CFG->{defaults}} }; $insert->{password} = $PLG->dispatch('GMail::Auth::get_pass', sub { GMail::Auth->get_pass(@_) }, $user); if (!$insert->{password}) { delete $insert->{password} } $insert->{users_join_time} = time; $insert->{email} = $user; $insert->{users_default_template} = GMail->template_set; my $sth = $tb->insert($insert); return $sth->insert_id; } sub insert_folders { my ($self, $uid) = @_; my $tb = $DB->table('folders'); $tb->insert ({ folders_userid => $uid, folders_name => $CFG->{language}->{FOLD_INBOX} || 'Inbox', folders_fid => INBOX }); $tb->insert ({ folders_userid => $uid, folders_name => $CFG->{language}->{FOLD_SENTBOX} || 'Sent', folders_fid => SENT, folders_display_sent_to => 1, folders_display_sent_from => 0, }); $tb->insert ({ folders_userid => $uid, folders_name => $CFG->{language}->{FOLD_TRASH} || 'Trash', folders_fid => TRASH }); } sub update_template { my ($self, $t) = @_; $DB->table('users')->update({ users_default_template => $t }, { userid => $self->{userid} }); } sub check_create { # ------------------------------------------------------------------------------------ # The method checks all the user tables to see if the user has the proper entries in # them. If any of the tables are missing entries they are added. This method is called # each time a user loggs in. An addition argument can be passed in. If it is # a welcome message will not be inserted for this user. # my ($self, $wel) = @_; my ($tb, $sth, $uid); # Insert user into the demographics table $tb = $DB->table('dgraph'); if (!$tb->count({ dgraph_userid => $self->{userid} })) { $PLG->dispatch('GMail::User::insert_dgraph', sub { $self->insert_dgraph(@_) }, $self->{userid}); } # Get the users directory and create it. if (!-e $self->{dir}) { $self->create_directories; $self->create_files; $self->{opts} = do "$self->{dir}/.prefs"; } else { $self->{opts} = do "$self->{dir}/.prefs"; } # Create folder $tb = $DB->table('folders'); if ($tb->count({ folders_userid => $self->{userid} }) < 3) { $PLG->dispatch('GMail::User::insert_folders', sub { $self->insert_folders(@_) }, $self->{userid}); # Here we assume this is the users first login. $self->insert_welcome if !$wel; } } sub vars { my ($self, @hshs) = @_; $self->{storage} ||= []; push(@{$self->{storage}}, @hshs) if @hshs; return $self->{storage}; } sub info { # ------------------------------------------------------------------- # This method sumrizes a users info into a single hash and returns it # This method is called each time a page in the Auth state is printed # my $self = shift; my $ret = {}; # User defined options if ($self->{opts}) { for my $opt (keys %{$self->{opts}}) { if (ref $self->{opts}->{$opt} eq 'HASH') { for (keys %{$self->{opts}->{$opt}}) { $ret->{'options_' . $opt .'_' . $_} = $self->{opts}->{$opt}->{$_}; } } else { $ret->{'options_' . $opt} = $self->{opts}->{$opt}; } } } for (keys %{$self}) { next unless /^(?:(?:users_)|(?:dgraph_))/; if (/space/) { $ret->{$_} = $self->format_size($self->{$_}); } else { $ret->{$_} = $self->{$_}; } } if (!defined($self->{users_space_allowed}) or !int($self->{users_space_allowed})) { $self->{users_space_allowed} = 1; } $self->{users_space_used} ||= 0; $ret->{users_percent_used} = sprintf("%.1f", $self->{users_space_used}/$self->{users_space_allowed} * 100); $ret->{users_space_left} = $self->format_size($self->{users_space_allowed} - $self->{users_space_used}); $ret->{username} = $self->{username}; $ret->{email} = $self->{email}; $ret->{user} = $self->{email}; $ret->{userid} = $self->{userid}; $ret->{domain} = $self->{domain}; return wantarray ? %{$ret} : $ret; } sub create_directories { # ------------------------------------------------------------------- # This method creates all the directories for the user currently in # self. This method is called when a user is created. # my $self = shift; my $base_dir = $self->{dir}; my ($domain, $uid, $p); if ($self->{email} ne ADMIN) { $p = lc substr ($self->{username}, 0, 1) } else { $uid = ADMIN; $self->{domain} = 'ADMIN'; } my $ddir = $CFG->{location}->{path}->{data} . '/users/'. $self->{domain}; (-d $ddir) or $self->mkdir($ddir); (-d "$ddir/$p") or $self->mkdir("$ddir/$p") unless ($self->{email} eq ADMIN); (-d $base_dir) or $self->mkdir($base_dir); return 1; } sub delete_directories { # ------------------------------------------------------------------- # This method deletes all the users files and directories. Called # when a user is deleted from the GMail system. # my ($self) = @_; my $base_dir = GMail::User->get_user_directory($self->{email}); (-e $base_dir and -d _) and $self->rmdir ($base_dir); return 1; } sub create_files { # ------------------------------------------------------------------- # This method creates all the files for a user. Should be called when # creating a user after create directories is called. # my $self = shift; my $base_dir = GMail::User->get_user_directory($self->{email}); require GT::Dumper; my $t = GMail->template_set; require GT::Template::Inheritance; my $file = GT::Template::Inheritance->get_path( file => 'prefs.cfg', path => "$CFG->{location}->{path}->{data}/templates/$t", use_local => 1, use_inheritance => 1 ); my $admin = do $file; $admin->{version} = PREFS_VERSION; my $wr = $self->touch("$base_dir/.prefs"); print {$wr} GT::Dumper->dump( var => '', data => $admin ); close $wr; return 1; } ############################################### ## Utility functions ## ############################################### sub get_user_directory { # ------------------------------------------------------------------- # Given a user returns the users directory. Class or instance method. # my ($class, $user) = @_; if ($user ne ADMIN) { my ($uid, $domain) = split(/\@/ => $user); (!$uid) and $uid = $domain; my $p = lc substr ($uid, 0, 1); return $CFG->{location}->{path}->{data} . '/users/'. $domain . '/' . $p . '/' . $uid; } else { return $CFG->{location}->{path}->{data} . '/users/ADMIN/' . ADMIN; } } sub insert_welcome { # ------------------------------------------------------------------- # Inserts a welcome message for this user. This method assumes the # user is already loaded into the system. This method is called from # check_create and load_user if the user is not in the auth system. # my ($self) = @_; my $t = GMail->template_set; require GT::Template::Inheritance; my $file = GT::Template::Inheritance->get_path( file => 'welcome.eml', path => "$CFG->{location}->{path}->{data}/templates/$t", use_local => 1, use_inheritance => 1 ); if ($CFG->{email}->{welcome_message} and $file) { require GMail::NoAuth; require GMail::Messages; require GMail::Folders; ($self->{username}, $self->{domain}) = split(/\@/ => $self->{email}); $self->{username} ||= ''; my @tags = GMail::NoAuth->get_tags; # Make a copy of Self for tags my $cp = {}; for (keys %$self) { $cp->{$_} = $self->{$_}; } push @tags, $cp; my $mail = GMail::NoAuth->parse_message($file, @tags); $mail->top_part->set(to => $self->{email}); my ($size, $id) = $PLG->dispatch('GMail::Messages::insert_data', sub { GMail::Messages->insert_data(@_) }, $mail); $self->{opts} ||= {}; $PLG->dispatch('GMail::Messages::insert_user', sub { GMail::Messages->insert_user(@_) }, { msgtrack_fid => INBOX, msgtrack_userid => $self->{userid}, msgtrack_status => 'New', msgtrack_mid => $id, msgtrack_look => ($self->{opts}->{default_look} || 'clear'), msgtrack_account => 0, }, 0); $PLG->dispatch('GMail::Folders::update', sub { GMail::Folders->update(@_) }, INBOX); } } 1;