root/branches/release-36/lib/MT/Author.pm @ 2060

Revision 2060, 23.8 kB (checked in by bchoate, 19 months ago)

Added new auth_type_name index.

  • 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
33        # deprecated; permissions are in MT::Permission only now
34        'can_create_blog' => 'boolean',
35        'is_superuser' => 'boolean',
36        'can_view_log' => 'boolean',
37        'auth_type' => 'string(255)',
38        'userpic_asset_id' => 'integer',
39        'basename' => 'string(255)',
40
41        # meta properties
42        'widgets' => 'hash meta',
43        'favorite_blogs' => 'array meta',
44    },
45    defaults => {
46        type => 1,
47        status => 1,
48    },
49    indexes => {
50        created_on => 1,
51        name => 1,
52        email => 1,
53        type => 1,
54        status => 1,
55        external_id => 1,
56        auth_type_name => {
57            columns => ['auth_type', 'name', 'type'],
58        },
59        basename => 1,
60    },
61    meta => 1,
62    child_classes => ['MT::Permission', 'MT::Association'],
63    datasource => 'author',
64    primary_key => 'id',
65    audit => 1,
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    if ($info[0] !~ m!^https?://!) {
707        my $static_host = MT->instance->static_path;
708        if ($static_host =~ m!^https?://!) {
709            $static_host =~ s!^(https?://[^/]+?)!$1!;
710            $info[0] = $static_host . $info[0];
711        }
712    }
713    return wantarray ? @info : $info[0];
714}
715
716sub userpic_html {
717    my $author = shift;
718    my ($thumb_url, $w, $h) = $author->userpic_url(@_) or return;
719    return unless $thumb_url;
720    sprintf q{<img src="%s" width="%d" height="%d" alt="" />},
721        MT::Util::encode_html($thumb_url), $w, $h;
722}
723
7241;
725
726__END__
727
728=head1 NAME
729
730MT::Author - Movable Type author record
731
732=head1 SYNOPSIS
733
734    use MT::Author;
735    my $author = MT::Author->new;
736    $author->name('Foo Bar');
737    $author->set_password('secret');
738    $author->save
739        or die $author->errstr;
740
741    my $author = MT::Author->load($author_id);
742
743=head1 DESCRIPTION
744
745An I<MT::Author> object represents a user in the Movable Type system. It
746contains profile information (name, nickname, email address, etc.), global
747permissions settings (blog creation, activity log viewing), and authentication
748information (password, public key). It does not contain any per-blog
749permissions settings--for those, look at the I<MT::Permission> object.
750
751=head1 USAGE
752
753As a subclass of I<MT::Object>, I<MT::Author> inherits all of the
754data-management and -storage methods from that class; thus you should look
755at the I<MT::Object> documentation for details about creating a new object,
756loading an existing object, saving an object, etc.
757
758The following methods are unique to the I<MT::Author> interface:
759
760=head2 $author->set_password($pass)
761
762One-way encrypts I<$pass> with a randomly-generated salt, using the Unix
763I<crypt> function, and sets the I<password> data field in the I<MT::Author>
764object I<$author>.
765
766Because the password is one-way encrypted, there is B<no way> of recovering
767the initial password.
768
769=head2 $author->is_valid_password($check_pass)
770
771Tests whether I<$check_pass> is a valid password for the I<MT::Author> object
772I<$author> (ie, whether it matches the password originally set using
773I<set_password>). This check is done by one-way encrypting I<$check_pass>,
774using the same salt used to encrypt the original password, then comparing the
775two encrypted strings for equality.
776
777=head1 DATA ACCESS METHODS
778
779The I<MT::Author> object holds the following pieces of data. These fields can
780be accessed and set using the standard data access methods described in the
781I<MT::Object> documentation.
782
783=over 4
784
785=item * id
786
787The numeric ID of the author.
788
789=item * name
790
791The username of the author. This is the username used to log in to the system.
792
793=item * nickname
794
795The author nickname (or "display" name). This is the preferred name used for publishing the author's name.
796
797=item * password
798
799The author's password, one-way encrypted. If you wish to check the validity of
800a password, you should use the I<is_valid_password> method, above.
801
802=item * type
803
804The 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).
805
806=item * status
807
808A column that defines whether the records of an AUTHOR type are ACTIVE, INACTIVE or PENDING (constants declared in this package).
809
810=item * commenter_status
811
812This 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.
813
814=item * email
815
816The author's email address.
817
818=item * url
819
820The author's homepage URL.
821
822=item * hint
823
824The answer to the question used when recovering the user's password.
825
826=item * external_id
827
828A column for holding a value used to synchronize the MT author record with an external record.
829
830=item * can_create_blog
831
832A boolean flag specifying whether the author has permission to create a new
833blog in the system.
834
835=item * can_view_log
836
837A boolean flag specifying whether the author has permission to view the global
838system activity log.
839
840=item * created_by
841
842The 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.
843
844=item * public_key
845
846The author's ASCII-armoured public key, to be used in the future for verifying
847incoming email messages.
848
849=back
850
851=head1 DATA LOOKUP
852
853In addition to numeric ID lookup, you can look up or sort records by any
854combination of the following fields. See the I<load> documentation in
855I<MT::Object> for more information.
856
857=over 4
858
859=item * name
860
861=item * email
862
863=back
864
865=head1 NOTES
866
867=over 4
868
869=item *
870
871When you remove an author using I<MT::Author::remove>, in addition to removing
872the author record, all of the author's permissions (I<MT::Permission> objects)
873will be removed, as well.
874
875=back
876
877=head1 AUTHOR & COPYRIGHTS
878
879Please see the I<MT> manpage for author, copyright, and license information.
880
881=cut
Note: See TracBrowser for help on using the browser.