root/branches/release-34/lib/MT/Author.pm @ 1823

Revision 1823, 23.6 kB (checked in by takayama, 20 months ago)

Fixed BugId:67959
* Added check for result of object loading

  • Property svn:keywords set to Author Date Id Revision
Line 
1# Movable Type (r) Open Source (C) 2001-2008 Six Apart, Ltd.
2# This program is distributed under the terms of the
3# GNU General Public License, version 2.
4#
5# $Id$
6
7package MT::Author;
8
9use strict;
10use base qw( MT::Object MT::Scorable );
11
12__PACKAGE__->install_properties({
13    column_defs => {
14        'id' => 'integer not null auto_increment',
15        'name' => 'string(255) not null',
16        'nickname' => 'string(255)',
17        'password' => 'string(60) not null',
18        'type' => 'smallint not null',
19        'email' => 'string(75)',
20        'url' => 'string(255)',
21        'hint' => 'string(75)',
22        'public_key' => 'text',
23        'preferred_language' => 'string(50)',
24        'api_password' => 'string(60)',
25        'remote_auth_username' => 'string(50)',
26        'remote_auth_token' => 'string(50)',
27        'entry_prefs' => 'string(255)',
28        'text_format' => 'string(30)',
29        'status' => 'integer',
30        'external_id' => 'string(255)',
31#        'last_login' => 'datetime',
32        # deprecated; permissions are in MT::Permission only now
33        'can_create_blog' => 'boolean',
34        'is_superuser' => 'boolean',
35        'can_view_log' => 'boolean',
36        'auth_type' => 'string(255)',
37        'userpic_asset_id' => 'integer',
38        'basename' => 'string(255)',
39    },
40    defaults => {
41        type => 1,
42        status => 1,
43    },
44    indexes => {
45        created_on => 1,
46        name => 1,
47        email => 1,
48        type => 1,
49        status => 1,
50        external_id => 1,
51        auth_type => 1,
52        basename => 1,
53        # is_superuser => 1,
54    },
55    meta => 1,
56    child_classes => ['MT::Permission', 'MT::Association'],
57    datasource => 'author',
58    primary_key => 'id',
59    audit => 1,
60});
61__PACKAGE__->install_meta({
62    columns => [
63        'favorite_blogs',
64        'widgets',
65    ],
66});
67
68sub class_label {
69    MT->translate("User");
70}
71
72sub class_label_plural {
73    MT->translate("Users");
74}
75
76# Valid "type" codes:
77sub AUTHOR ()    { 1 }
78sub COMMENTER () { 2 }
79
80# Commenter statuses
81sub APPROVED () { 1 }
82sub BANNED ()   { 2 }
83sub BLOCKED ()  { 2 }  # alias for BANNED for backward compatibility
84sub PENDING ()  { 3 }
85
86# Author statuses
87sub ACTIVE ()   { 1 }
88sub INACTIVE () { 2 }
89#use constant PENDING => 3; # there *is* PENDING status for authors but it's the same name and value.
90
91use Exporter;
92*import = \&Exporter::import;
93use vars qw(@EXPORT_OK %EXPORT_TAGS);
94@EXPORT_OK = qw(AUTHOR COMMENTER ACTIVE INACTIVE APPROVED BANNED PENDING);
95%EXPORT_TAGS = (constants => [qw(AUTHOR COMMENTER ACTIVE INACTIVE APPROVED BANNED PENDING)]);
96
97sub set_defaults {
98    my $auth = shift;
99    my $cfg = MT->config;
100    $auth->SUPER::set_defaults(@_);
101    $auth->preferred_language($cfg->DefaultUserLanguage || $cfg->DefaultLanguage);
102}
103
104sub remove_sessions {
105    my $auth = shift;
106    require MT::Session;
107    my $sess_iter = MT::Session->load_iter({ kind => 'US' });
108    my @sess;
109    while (my $sess = $sess_iter->()) {
110        my $id = $sess->get('author_id');
111        next unless $id == $auth->id;
112        push @sess, $sess;
113    }
114    $_->remove foreach @sess;
115}
116
117sub set_password {
118    my $auth = shift;
119    my($pass) = @_;
120    my @alpha = ('a'..'z', 'A'..'Z', 0..9);
121    my $salt = join '', map $alpha[rand @alpha], 1..2;
122    # FIXME: use something besides 'crypt'
123    $auth->column('password', crypt $pass, $salt);
124}
125
126sub is_valid_password {
127    my $author = shift;
128    my($pass, $crypted, $error_ref) = @_;
129    $pass ||= '';
130    require MT::Auth;
131    return MT::Auth->is_valid_password($author, $pass, $crypted, $error_ref);
132}
133
134sub is_email_hidden {
135    my $auth = shift;
136    return 1 unless $auth->email =~ m/@/;
137    return ($auth->email =~ /^[0-9a-f]{40}$/i) ? 1 : 0;
138}
139
140# Existing comments of a user are made visible only if the
141# user is coming from "pending" status.
142
143sub set_commenter_perm {
144    my $this = shift;
145    my ($blog_id, $action) = @_;
146
147    require MT::Permission;
148    my %perm_spec = (
149        author_id => $this->id(),
150        blog_id => $blog_id
151    );
152    my $perm = MT::Permission->load(\%perm_spec);
153    if (!$perm) {
154        $perm = MT::Permission->new();
155        $perm->set_values(\%perm_spec);
156    }
157    if ($action eq 'approve') {
158        $perm->remove_restrictions('comment');
159        $perm->can_comment(1) if COMMENTER eq $this->type;
160    } elsif (($action eq 'ban') || ($action eq 'block')) {
161        $perm->set_these_restrictions('comment');
162        $perm->can_comment(0) if COMMENTER eq $this->type;
163    } elsif ($action eq 'pending') {
164        $perm->remove_restrictions('comment');
165        $perm->can_comment(0) if COMMENTER eq $this->type;
166    }
167    $perm->save()
168        or return $this->error(MT->translate("The approval could not be committed: [_1]", $perm->errstr));
169
170    return 1;
171}
172
173sub commenter_status {
174    my $this = shift;
175    return APPROVED if $this->is_superuser;
176    my ($blog_id) = @_;
177    require MT::Permission;
178    my $perm = MT::Permission->load(
179        { author_id=>$this->id, blog_id => $blog_id } );
180    return PENDING if !$perm;
181    return BANNED if $perm->is_restricted('comment');
182    return APPROVED if $perm->can_comment() || $perm->can_manage_feedback();
183    return PENDING;
184}
185
186sub is_active { shift->status() == ACTIVE; }
187sub is_trusted { shift->commenter_status(@_) == APPROVED; }
188sub is_banned { shift->commenter_status(@_) == BANNED; }
189*is_blocked = \&is_banned;
190sub is_not_trusted { shift->commenter_status(@_) == PENDING; }
191*is_untrusted = \&is_not_trusted;
192
193sub approve {
194    my $this = shift;
195    my ($blog_id) = @_;
196    $this->set_commenter_perm($blog_id, 'approve');
197}
198
199*trust = \&approve;
200
201sub pending {
202    $_[0]->set_commenter_perm($_[1], 'pending');
203}
204
205sub ban {
206    my $this = shift;
207    my ($blog_id) = @_;
208    $this->set_commenter_perm($blog_id, 'ban');
209}
210*block = \&ban;
211
212sub save {
213    my $auth = shift;
214
215    if ($auth->type == AUTHOR) {
216        if (!$auth->id) {
217            # New author, undefined API password. Generate one.
218            if (!defined $auth->api_password) {
219                my @pool = ('a'..'z', 0..9);
220                my $pass = '';
221                for (1..8) { $pass .= $pool[ rand @pool ] }
222                $auth->api_password($pass);
223            }
224        }
225        # Generate basename
226        my $basename = MT::Util::make_unique_author_basename($auth);
227        $auth->basename($basename);
228    }
229
230    my $privs;
231    if (exists $auth->permissions(0)->{changed_cols}->{permissions}) {
232         $privs = $auth->permissions(0)->permissions;
233    }
234    # delete new user's privilege from cache
235    delete MT::Request->instance->{__stash}->{'__perm_author_'} unless $auth->id;
236    $auth->SUPER::save(@_) or return $auth->error($auth->errstr);
237    if (defined $privs) {
238        my $perm = $auth->permissions(0);
239        $perm->permissions($privs);
240        $perm->save or return $auth->error("Error saving permission: " . $perm->errstr);
241    }
242    1;
243}
244
245sub remove {
246    my $auth = shift;
247    $auth->remove_sessions if ref $auth;
248    $auth->remove_children({ key => 'author_id' }) or return;
249    $auth->SUPER::remove(@_);
250}
251
252sub can_edit_entry {
253    my $author = shift;
254    die unless $author->isa('MT::Author');
255    return 1 if $author->is_superuser();
256    my($entry) = @_;
257    unless (ref $entry) {
258        require MT::Entry;
259        $entry = MT::Entry->load($entry);
260    }
261    die if !$entry || $entry->isa('MT::Entry');
262    my $perms = $author->permissions($entry->blog_id);
263    die unless $perms->isa('MT::Permission');
264    $perms->can_edit_all_posts ||
265    ($perms->can_create_post && $entry->author_id == $author->id);
266}
267
268sub is_superuser {
269    my $author = shift;
270    if (@_) {
271        $author->permissions(0)->can_administer(@_);
272        if ($_[0]) {
273            $author->permissions(0)->can_create_blog(@_);
274            $author->permissions(0)->can_view_log(@_);
275            $author->permissions(0)->can_manage_plugins(@_);
276            $author->permissions(0)->can_edit_templates(@_);
277        }
278    } else {
279        $author->permissions(0)->can_administer() ||
280            $author->SUPER::is_superuser();
281    }
282}
283
284sub can_create_blog {
285    my $author = shift;
286    if (@_) {
287        $author->permissions(0)->can_create_blog(@_);
288    } else {
289        $author->is_superuser() ||
290            $author->permissions(0)->can_create_blog(@_);
291    }
292}
293
294sub can_view_log {
295    my $author = shift;
296    if (@_) {
297        $author->permissions(0)->can_view_log(@_);
298    } else {
299        $author->is_superuser() ||
300            $author->permissions(0)->can_view_log(@_);
301    }
302}
303
304sub can_manage_plugins {
305    my $author = shift;
306    if (@_) {
307        $author->permissions(0)->can_manage_plugins(@_);
308    } else {
309        $author->is_superuser() ||
310            $author->permissions(0)->can_manage_plugins(@_);
311    }
312}
313
314sub can_edit_templates {
315    my $author = shift;
316    if (@_) {
317        $author->permissions(0)->can_edit_templates(@_);
318    } else {
319        $author->is_superuser() ||
320            $author->permissions(0)->can_edit_templates(@_);
321    }
322}
323
324sub blog_perm {
325    my $author = shift;
326    my ($blog_id) = @_;
327    $author->permissions($blog_id);
328}
329
330sub permissions {
331    my $author = shift;
332    my ($obj) = @_;
333    my $blog_id = $obj;
334
335    my $terms = { author_id => $author->id };
336    my $cache_key = "__perm_author_" . (defined($author->id) ? $author->id : q());
337    if ($obj) {
338        if ((ref $obj) && $obj->isa('MT::Blog')) {
339            $blog_id = $obj->id;
340        } elsif ($obj) {
341            $blog_id = $obj;
342            require MT::Blog;
343            $obj = MT::Blog->load($blog_id);
344        }
345        $cache_key .= "_blog_$blog_id";
346        $terms->{blog_id} = [ 0, $blog_id ];
347    } else {
348        $terms->{blog_id} = 0;
349    }
350
351    require MT::Request;
352    my $r = MT::Request->instance;
353    my $p = $r->stash($cache_key);
354    return $p if $p;
355
356    require MT::Permission;
357    my @perm = MT::Permission->load($terms);
358    my $perm;
359    if ($obj) {
360        if (@perm == 2) {
361            if (!$perm[0]->blog_id) {
362                @perm = reverse @perm;
363            }
364            ($perm, my $sys_perm) = @perm;
365            $perm->add_permission($sys_perm);
366        } elsif (@perm == 1) {
367            $perm = $perm[0];
368            if (!$perm->blog_id) {
369                $perm->blog_id($obj->id);
370                delete $perm->{column_values}->{id};
371                delete $perm->{changed_cols}->{id};
372            }
373        } elsif (@perm) {
374            die "invalid permissions for author " . $author->id;
375        }
376    } else {
377        $perm = $perm[0] if @perm;
378    }
379    unless (@perm) {
380        if ($blog_id || !@_) {
381            if ($author->is_superuser()) {
382                $perm = new MT::Permission;
383                $perm->author_id($author->id);
384                $perm->set_full_permissions;
385            }
386        }
387    }
388    unless ($perm) {
389        $perm = new MT::Permission;
390        $perm->author_id($author->id);
391        $perm->clear_full_permissions;
392    }
393    $r->stash($cache_key, $perm);
394    $perm;
395}
396
397sub common_blogs { # returns the blogs in the form of permission records of $this
398    die "This was removed";        # FIXME: this is to catch mistakes
399}
400sub can_administer {
401    die "This was removed";        # FIXME: this is to catch mistakes
402}
403
404sub entry_prefs {
405    my $author = shift;
406    my @prefs = split /,/, ($author->column('entry_prefs') || '');
407    my %prefs;
408    foreach (@prefs) {
409        my ($name, $value) = split /=/, $_, 2;
410        $prefs{$name} = $value;
411    }
412    if (@_) {
413        %prefs = (%prefs, @_);
414        my $pref = '';
415        foreach (keys %prefs) {
416            $pref .= ',' if $pref ne '';
417            $pref .= $_ . '=' . $prefs{$_};
418        }
419        $author->column('entry_prefs', $pref);
420    }
421
422    # default assignments for author entry preferences
423    $prefs{tag_delim} ||= MT->config->DefaultUserTagDelimiter;
424
425    \%prefs;
426}
427
428sub role_iter {
429    my $author = shift;
430    my ($terms, $args) = @_;
431    require MT::Association;
432    require MT::Role;
433    my $blog_id = delete $terms->{blog_id};
434    my $type;
435    if ($blog_id) {
436        $type = MT::Association::USER_BLOG_ROLE();
437    } else {
438        $type = MT::Association::USER_ROLE();
439    }
440    $args->{join} = MT::Association->join_on('role_id', {
441        type => $type,
442        author_id => $author->id,
443        $blog_id ? (blog_id => $blog_id) : (blog_id => 0),
444    });
445    MT::Role->load_iter($terms, $args);
446}
447
448sub blog_iter {
449    my $author = shift;
450    my ($terms, $args) = @_;
451    my $perm = $author->permissions;
452    if (!$author->is_superuser) {
453        require MT::Permission;
454        $args->{join} = MT::Permission->join_on('blog_id', {
455            author_id => $author->id,
456        });
457    }
458    require MT::Blog;
459    my $i = MT::Blog->load_iter($terms, $args);
460}
461
462sub group_iter {
463    my $author = shift;
464    my ($terms, $args) = @_;
465    my $grp_class = MT->model('group') or return undef;
466    require MT::Association;
467    $args->{join} = MT::Association->join_on('group_id', {
468        type => MT::Association::USER_GROUP(),
469        author_id => $author->id,
470    });
471    return $grp_class->load_iter($terms, $args);
472}
473
474sub group_role_iter {
475    my $author = shift;
476    my ($terms, $args) = @_;
477
478    my $grp_class = MT->model('group')
479        or return undef;
480    my @iters;
481    require MT::Association;
482    require MT::Role;
483    my $blog_id = delete $terms->{blog_id};
484    $args->{join} = MT::Association->join_on('role_id', {
485        type => $blog_id ? MT::Association::USER_BLOG_ROLE() : MT::Association::USER_ROLE(),
486        author_id => $author->id,
487        $blog_id ? (blog_id => $blog_id) : (),
488    });
489    my $user_iter = MT::Role->load_iter($terms, $args);
490    push @iters, $user_iter if $user_iter;
491
492    my @groups;
493    if (my $group_iter = $author->group_iter({ status => MT::Group::ACTIVE() })) {
494        while (my $g = $group_iter->()) {
495            push @groups, $g->id;
496        }
497    }
498    if (@groups) {
499        $args->{join} = MT::Association->join_on('role_id', {
500            type => $blog_id ? MT::Association::GROUP_BLOG_ROLE() : MT::Association::GROUP_ROLE(),
501            group_id => \@groups,
502            $blog_id ? (blog_id => $blog_id) : (),
503        });
504        my $group_iter = MT::Role->load_iter($terms, $args);
505        push @iters, $group_iter if $group_iter;
506    }
507    MT::Util::multi_iter(\@iters);
508}
509
510sub add_role {
511    my $author = shift;
512    my ($role, $blog) = @_;
513    $author->save unless $author->id;
514    $role->save unless $role->id;
515    $blog->save if $blog && !$blog->id;
516    require MT::Association;
517    MT::Association->link($author, @_);
518}
519
520sub add_group {
521    my $author = shift;
522    my ($group) = @_;
523    $author->save unless $author->id;
524    $group->save unless $group->id;
525    require MT::Association;
526    MT::Association->link($author, @_);
527}
528
529sub remove_role {
530    my $author = shift;
531    require MT::Association;
532    MT::Association->unlink($author, @_);
533}
534
535sub remove_group {
536    my $author = shift;
537    require MT::Association;
538    MT::Association->unlink($author, @_);
539}
540
541sub add_default_roles {
542    my $author = shift;
543    my $def = MT->config->DefaultAssignments;
544    return unless $def;
545
546    my $blog_class = MT->model('blog');
547    my $role_class = MT->model('role');
548
549    require MT::Association;
550    my @def = split ',', $def;
551    while (my $role_id = shift @def) {
552        my $blog_id = shift @def;
553        next unless $role_id && $blog_id;
554        my $blog = $blog_class->load($blog_id);
555        my $role = $role_class->load($role_id);
556        next unless ref $blog && ref $role;
557        MT::Association->link($author => $role => $blog);
558    }
559}
560
561sub to_hash {
562    my $author = shift;
563    my $hash = $author->SUPER::to_hash(@_);
564    my $app = MT->instance;
565    my $blog = $app->blog if $app->can('blog');
566    if ($blog) {
567        require MT::Permission;
568        if (my $perms = MT::Permission->load({ author_id => $author->id, blog_id => $blog->id })) {
569            my $perms_hash = $perms->to_hash;
570            $hash->{"author.$_"} = $perms_hash->{$_} foreach keys %$perms_hash;
571        }
572    }
573    $hash;
574}
575
576sub group_count {
577    my $author = shift;
578    require MT::Association;
579    MT::Association->count({
580        type => MT::Association::USER_GROUP(),
581        author_id => $author->id,
582    });
583}
584
585sub external_id {
586    my $author = shift;
587    if (@_) {
588        return $author->SUPER::external_id($author->unpack_external_id(@_));
589    }
590    my $value = $author->SUPER::external_id;
591    $value = $author->pack_external_id($value) if $value;
592}
593
594sub load {
595    my $author = shift;
596    my ($terms, $args) = @_;
597    if ((ref($terms) eq 'HASH') && exists($terms->{external_id})) {
598        $terms->{external_id} = $author->unpack_external_id($terms->{external_id});
599    }
600    $author->SUPER::load($terms, $args);
601}
602
603sub load_iter {
604    my $author = shift;
605    my ($terms, $args) = @_;
606    if ((ref($terms) eq 'HASH') && exists($terms->{external_id})) {
607        $terms->{external_id} = $author->unpack_external_id($terms->{external_id});
608    }
609    $author->SUPER::load_iter($terms, $args);
610}
611
612sub pack_external_id { return pack('H*', $_[1]); }
613sub unpack_external_id { return unpack('H*', $_[1]); }
614
615sub auth_icon_url {
616    my $author = shift;
617    my ($size) = @_;
618    $size ||= 'logo_small';
619
620    my $app = MT->instance;
621    my $static_path = $app->static_path;
622
623    my $auth_type = $author->auth_type;
624    return q() unless $auth_type;
625
626    if ( $author->type == MT::Author::AUTHOR() ) {
627        return $static_path . 'images/comment/mt_logo.png' ;
628    }
629   
630    my $authenticator = MT->commenter_authenticator( $auth_type );
631    return q() unless $authenticator;
632    return q() unless exists $authenticator->{$size};
633
634    my $logo = $authenticator->{$size};
635    if ( ( $logo !~ m!^https?://! ) || ( $logo !~ m!^/! ) ) {
636        $logo = $static_path . $logo;
637    }
638    return $logo;
639}
640
641sub userpic {
642    my $author = shift;
643
644    my $asset_id = $author->userpic_asset_id or return;
645    require MT::Asset;
646    my $asset = MT->model('asset.image')->load($asset_id) or return;
647
648    $asset;
649}
650
651sub userpic_thumbnail_options {
652    my $author = shift;
653
654    # Specify these to put an author's userpic thumbnail in a consistent
655    # place whenever userpic_url is called as an instance method on a
656    # particular author.
657    my %real_userpic_options = (
658        Path   => File::Spec->catdir( MT->config->AssetCacheDir, 'userpics' ),
659        Format => MT->translate('userpic-[_1]-%wx%h%x', $author->id),
660    ) if ref $author;
661
662    my $cfg = MT->config;
663    my $max_dim = $cfg->UserpicThumbnailSize;
664    my $square  = $cfg->UserpicAllowRect ? 0 : 1;
665    return (
666        Width  => $max_dim,
667        Height => $max_dim,
668        Square => $square,
669        Type   => 'png',
670        %real_userpic_options,
671    );
672}
673
674sub userpic_file {
675    my $author = shift;
676
677    my $asset = $author->userpic;
678    if (!$asset) {
679        $asset = MT->model('asset.image')->new;
680        $asset->file_name('userpic');
681    }
682
683    my %thumb_param = $author->userpic_thumbnail_options();
684    my $thumb_file = File::Spec->catfile(
685        $asset->thumbnail_path(%thumb_param),
686        $asset->thumbnail_filename(%thumb_param),
687    );
688
689    return $thumb_file;
690}
691
692sub userpic_url {
693    my $author = shift;
694    my (%param) = @_;
695
696    my $asset = delete $param{Asset};
697    if (!$asset && ref $author) {
698        $asset = $author->userpic;
699    }
700    return if !$asset;
701
702    my @info = $asset->thumbnail_url(
703        $author->userpic_thumbnail_options(),
704        %param,
705    );
706    return wantarray ? @info : $info[0];
707}
708
709sub userpic_html {
710    my $author = shift;
711    my ($thumb_url, $w, $h) = $author->userpic_url(@_) or return;
712    return unless $thumb_url;
713    sprintf q{<img src="%s" width="%d" height="%d" alt="" />},
714        MT::Util::encode_html($thumb_url), $w, $h;
715}
716
7171;
718
719__END__
720
721=head1 NAME
722
723MT::Author - Movable Type author record
724
725=head1 SYNOPSIS
726
727    use MT::Author;
728    my $author = MT::Author->new;
729    $author->name('Foo Bar');
730    $author->set_password('secret');
731    $author->save
732        or die $author->errstr;
733
734    my $author = MT::Author->load($author_id);
735
736=head1 DESCRIPTION
737
738An I<MT::Author> object represents a user in the Movable Type system. It
739contains profile information (name, nickname, email address, etc.), global
740permissions settings (blog creation, activity log viewing), and authentication
741information (password, public key). It does not contain any per-blog
742permissions settings--for those, look at the I<MT::Permission> object.
743
744=head1 USAGE
745
746As a subclass of I<MT::Object>, I<MT::Author> inherits all of the
747data-management and -storage methods from that class; thus you should look
748at the I<MT::Object> documentation for details about creating a new object,
749loading an existing object, saving an object, etc.
750
751The following methods are unique to the I<MT::Author> interface:
752
753=head2 $author->set_password($pass)
754
755One-way encrypts I<$pass> with a randomly-generated salt, using the Unix
756I<crypt> function, and sets the I<password> data field in the I<MT::Author>
757object I<$author>.
758
759Because the password is one-way encrypted, there is B<no way> of recovering
760the initial password.
761
762=head2 $author->is_valid_password($check_pass)
763
764Tests whether I<$check_pass> is a valid password for the I<MT::Author> object
765I<$author> (ie, whether it matches the password originally set using
766I<set_password>). This check is done by one-way encrypting I<$check_pass>,
767using the same salt used to encrypt the original password, then comparing the
768two encrypted strings for equality.
769
770=head1 DATA ACCESS METHODS
771
772The I<MT::Author> object holds the following pieces of data. These fields can
773be accessed and set using the standard data access methods described in the
774I<MT::Object> documentation.
775
776=over 4
777
778=item * id
779
780The numeric ID of the author.
781
782=item * name
783
784The username of the author. This is the username used to log in to the system.
785
786=item * nickname
787
788The author nickname (or "display" name). This is the preferred name used for publishing the author's name.
789
790=item * password
791
792The author's password, one-way encrypted. If you wish to check the validity of
793a password, you should use the I<is_valid_password> method, above.
794
795=item * type
796
797The type of author record. Currently, MT stores authenticated commenters in the author table. The type column can be one of AUTHOR or COMMENTER (constants defined in this package).
798
799=item * status
800
801A column that defines whether the records of an AUTHOR type are ACTIVE, INACTIVE or PENDING (constants declared in this package).
802
803=item * commenter_status
804
805This method requires a blog id to be passed as the argument and a value of APPROVED, BANNED or PENDING (constants declared in this package) is returned.
806
807=item * email
808
809The author's email address.
810
811=item * url
812
813The author's homepage URL.
814
815=item * hint
816
817The answer to the question used when recovering the user's password.
818
819=item * external_id
820
821A column for holding a value used to synchronize the MT author record with an external record.
822
823=item * can_create_blog
824
825A boolean flag specifying whether the author has permission to create a new
826blog in the system.
827
828=item * can_view_log
829
830A boolean flag specifying whether the author has permission to view the global
831system activity log.
832
833=item * created_by
834
835The author ID of the author who created this author. If the author was created by a process where no user was logged in to Movable Type, the created_by column will be empty.
836
837=item * public_key
838
839The author's ASCII-armoured public key, to be used in the future for verifying
840incoming email messages.
841
842=back
843
844=head1 DATA LOOKUP
845
846In addition to numeric ID lookup, you can look up or sort records by any
847combination of the following fields. See the I<load> documentation in
848I<MT::Object> for more information.
849
850=over 4
851
852=item * name
853
854=item * email
855
856=back
857
858=head1 NOTES
859
860=over 4
861
862=item *
863
864When you remove an author using I<MT::Author::remove>, in addition to removing
865the author record, all of the author's permissions (I<MT::Permission> objects)
866will be removed, as well.
867
868=back
869
870=head1 AUTHOR & COPYRIGHTS
871
872Please see the I<MT> manpage for author, copyright, and license information.
873
874=cut
Note: See TracBrowser for help on using the browser.