root/branches/release-41/lib/MT/Author.pm @ 2675

Revision 2675, 24.9 kB (checked in by auno, 17 months ago)

Fixed to get off the IE cache problem for userpic. BugzID:80354

  • 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(50)',
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    if ( MT->config->SingleCommunity ) {
148        $blog_id = 0;
149    }
150
151    require MT::Permission;
152    my %perm_spec = (
153        author_id => $this->id(),
154        blog_id => $blog_id
155    );
156    my $perm = MT::Permission->load(\%perm_spec);
157    if (!$perm) {
158        $perm = MT::Permission->new();
159        $perm->set_values(\%perm_spec);
160    }
161    if ($action eq 'approve') {
162        $perm->remove_restrictions('comment');
163        $perm->can_comment(1) if COMMENTER eq $this->type;
164    } elsif (($action eq 'ban') || ($action eq 'block')) {
165        $perm->set_these_restrictions('comment');
166        $perm->can_comment(0) if COMMENTER eq $this->type;
167    } elsif ($action eq 'pending') {
168        $perm->remove_restrictions('comment');
169        $perm->can_comment(0) if COMMENTER eq $this->type;
170    }
171    $perm->save()
172        or return $this->error(MT->translate("The approval could not be committed: [_1]", $perm->errstr));
173
174    return 1;
175}
176
177sub commenter_status {
178    my $this = shift;
179    return APPROVED if $this->is_superuser;
180    my ($blog_id) = @_;
181
182    if ( MT->config->SingleCommunity ) {
183        $blog_id = 0;
184    }
185
186    require MT::Permission;
187    my $perm = MT::Permission->load(
188        { author_id => $this->id, blog_id => $blog_id } );
189    return PENDING if !$perm;
190    return BANNED if $perm->is_restricted('comment');
191    return APPROVED if $perm->can_comment() || $perm->can_manage_feedback();
192    return PENDING;
193}
194
195sub is_active { shift->status() == ACTIVE; }
196sub is_trusted { shift->commenter_status(@_) == APPROVED; }
197sub is_banned { shift->commenter_status(@_) == BANNED; }
198*is_blocked = \&is_banned;
199sub is_not_trusted { shift->commenter_status(@_) == PENDING; }
200*is_untrusted = \&is_not_trusted;
201
202sub approve {
203    my $this = shift;
204    my ($blog_id) = @_;
205    $this->set_commenter_perm($blog_id, 'approve');
206}
207
208*trust = \&approve;
209
210sub pending {
211    $_[0]->set_commenter_perm($_[1], 'pending');
212}
213
214sub ban {
215    my $this = shift;
216    my ($blog_id) = @_;
217    $this->set_commenter_perm($blog_id, 'ban');
218}
219*block = \&ban;
220
221sub save {
222    my $auth = shift;
223
224    if ($auth->type == AUTHOR) {
225        if (!$auth->id) {
226            # New author, undefined API password. Generate one.
227            if (!defined $auth->api_password) {
228                my @pool = ('a'..'z', 0..9);
229                my $pass = '';
230                for (1..8) { $pass .= $pool[ rand @pool ] }
231                $auth->api_password($pass);
232            }
233        }
234        # Generate basename
235        my $basename = MT::Util::make_unique_author_basename($auth);
236        $auth->basename($basename);
237    }
238
239    my $privs;
240    if (exists $auth->permissions(0)->{changed_cols}->{permissions}) {
241         $privs = $auth->permissions(0)->permissions;
242    }
243    # delete new user's privilege from cache
244    delete MT::Request->instance->{__stash}->{'__perm_author_'} unless $auth->id;
245    $auth->SUPER::save(@_) or return $auth->error($auth->errstr);
246    if (defined $privs) {
247        my $perm = $auth->permissions(0);
248        $perm->permissions($privs);
249        $perm->save or return $auth->error("Error saving permission: " . $perm->errstr);
250    }
251    1;
252}
253
254sub remove {
255    my $auth = shift;
256    $auth->remove_sessions if ref $auth;
257    $auth->remove_children({ key => 'author_id' }) or return;
258    $auth->SUPER::remove(@_);
259}
260
261sub can_edit_entry {
262    my $author = shift;
263    die unless $author->isa('MT::Author');
264    return 1 if $author->is_superuser();
265    my($entry) = @_;
266    unless (ref $entry) {
267        require MT::Entry;
268        $entry = MT::Entry->load($entry);
269    }
270    die if !$entry || !$entry->isa('MT::Entry');
271    my $perms = $author->permissions($entry->blog_id);
272    die unless $perms->isa('MT::Permission');
273    $perms->can_edit_all_posts ||
274        ($perms->can_create_post && $entry->author_id == $author->id);
275}
276
277sub is_superuser {
278    my $author = shift;
279    if (@_) {
280        $author->permissions(0)->can_administer(@_);
281        if ($_[0]) {
282            $author->permissions(0)->can_create_blog(@_);
283            $author->permissions(0)->can_view_log(@_);
284            $author->permissions(0)->can_manage_plugins(@_);
285            $author->permissions(0)->can_edit_templates(@_);
286        }
287    } else {
288        $author->permissions(0)->can_administer() ||
289            $author->SUPER::is_superuser();
290    }
291}
292
293sub can_create_blog {
294    my $author = shift;
295    if (@_) {
296        $author->permissions(0)->can_create_blog(@_);
297    } else {
298        $author->is_superuser() ||
299            $author->permissions(0)->can_create_blog(@_);
300    }
301}
302
303sub can_view_log {
304    my $author = shift;
305    if (@_) {
306        $author->permissions(0)->can_view_log(@_);
307    } else {
308        $author->is_superuser() ||
309            $author->permissions(0)->can_view_log(@_);
310    }
311}
312
313sub can_manage_plugins {
314    my $author = shift;
315    if (@_) {
316        $author->permissions(0)->can_manage_plugins(@_);
317    } else {
318        $author->is_superuser() ||
319            $author->permissions(0)->can_manage_plugins(@_);
320    }
321}
322
323sub can_edit_templates {
324    my $author = shift;
325    if (@_) {
326        $author->permissions(0)->can_edit_templates(@_);
327    } else {
328        $author->is_superuser() ||
329            $author->permissions(0)->can_edit_templates(@_);
330    }
331}
332
333sub blog_perm {
334    my $author = shift;
335    my ($blog_id) = @_;
336    $author->permissions($blog_id);
337}
338
339sub permissions {
340    my $author = shift;
341    my ($obj) = @_;
342    my $blog_id = $obj;
343
344    my $terms = { author_id => $author->id };
345    my $cache_key = "__perm_author_" . (defined($author->id) ? $author->id : q());
346    if ($obj) {
347        if ((ref $obj) && $obj->isa('MT::Blog')) {
348            $blog_id = $obj->id;
349        } elsif ($obj) {
350            $blog_id = $obj;
351            require MT::Blog;
352            $obj = MT::Blog->load($blog_id);
353        }
354        $cache_key .= "_blog_$blog_id";
355        $terms->{blog_id} = [ 0, $blog_id ];
356    } else {
357        $terms->{blog_id} = 0;
358    }
359
360    require MT::Request;
361    my $r = MT::Request->instance;
362    my $p = $r->stash($cache_key);
363    return $p if $p;
364
365    require MT::Permission;
366    my @perm = MT::Permission->load($terms);
367    my $perm;
368    if ($obj) {
369        if (@perm == 2) {
370            if (!$perm[0]->blog_id) {
371                @perm = reverse @perm;
372            }
373            ($perm, my $sys_perm) = @perm;
374            $perm->add_permissions($sys_perm);
375        } elsif (@perm == 1) {
376            $perm = $perm[0];
377            if (!$perm->blog_id) {
378                $perm->blog_id($obj->id);
379                delete $perm->{column_values}{blog_id};
380                delete $perm->{changed_cols}{blog_id};
381            }
382        } elsif (@perm > 2) {
383            # Condition sometimes caused by saving preferences. BugId:79501
384            # Handle by merging permissions and removing all but one
385            # Not ideal, but better than dying...
386            my ($sys_perm) = grep { ! $_->blog_id } @perm;
387            my @blog_perms = grep { $_->blog_id } sort { $b->modified_on cmp $a->modified_on } @perm;
388
389            my $new_perm = shift @blog_perms; # take last one saved
390            if (@blog_perms) {
391                foreach my $more_perms (@blog_perms) {
392                    $new_perm->add_permissions($more_perms);
393                    $new_perm->add_restrictions($more_perms);
394                    $more_perms->remove;
395                }
396                # save merged permission record
397                $new_perm->save;
398            }
399            $new_perm->add_permissions($sys_perm);
400            $new_perm->add_restrictions($sys_perm);
401            $perm = $new_perm;
402            @perm = ($perm);
403        }
404    } else {
405        $perm = $perm[0] if @perm;
406    }
407    unless (@perm) {
408        if ($blog_id || !@_) {
409            if ($author->is_superuser()) {
410                $perm = new MT::Permission;
411                $perm->author_id($author->id);
412                $perm->set_full_permissions;
413            }
414        }
415    }
416    unless ($perm) {
417        $perm = new MT::Permission;
418        $perm->author_id($author->id);
419        $perm->clear_full_permissions;
420    }
421    $r->stash($cache_key, $perm);
422    $perm;
423}
424
425sub common_blogs { # returns the blogs in the form of permission records of $this
426    die "This was removed";        # FIXME: this is to catch mistakes
427}
428sub can_administer {
429    die "This was removed";        # FIXME: this is to catch mistakes
430}
431
432sub entry_prefs {
433    my $author = shift;
434    my @prefs = split /,/, ($author->column('entry_prefs') || '');
435    my %prefs;
436    foreach (@prefs) {
437        my ($name, $value) = split /=/, $_, 2;
438        $prefs{$name} = $value;
439    }
440    if (@_) {
441        %prefs = (%prefs, @_);
442        my $pref = '';
443        foreach (keys %prefs) {
444            $pref .= ',' if $pref ne '';
445            $pref .= $_ . '=' . $prefs{$_};
446        }
447        $author->column('entry_prefs', $pref);
448    }
449
450    # default assignments for author entry preferences
451    $prefs{tag_delim} ||= MT->config->DefaultUserTagDelimiter;
452
453    \%prefs;
454}
455
456sub role_iter {
457    my $author = shift;
458    my ($terms, $args) = @_;
459    require MT::Association;
460    require MT::Role;
461    my $blog_id = delete $terms->{blog_id};
462    my $type;
463    if ($blog_id) {
464        $type = MT::Association::USER_BLOG_ROLE();
465    } else {
466        $type = MT::Association::USER_ROLE();
467    }
468    $args->{join} = MT::Association->join_on('role_id', {
469        type => $type,
470        author_id => $author->id,
471        $blog_id ? (blog_id => $blog_id) : (blog_id => 0),
472    });
473    MT::Role->load_iter($terms, $args);
474}
475
476sub blog_iter {
477    my $author = shift;
478    my ($terms, $args) = @_;
479    my $perm = $author->permissions;
480    if (!$author->is_superuser) {
481        require MT::Permission;
482        $args->{join} = MT::Permission->join_on('blog_id', {
483            author_id => $author->id,
484        });
485    }
486    require MT::Blog;
487    my $i = MT::Blog->load_iter($terms, $args);
488}
489
490sub group_iter {
491    my $author = shift;
492    my ($terms, $args) = @_;
493    my $grp_class = MT->model('group') or return undef;
494    require MT::Association;
495    $args->{join} = MT::Association->join_on('group_id', {
496        type => MT::Association::USER_GROUP(),
497        author_id => $author->id,
498    });
499    return $grp_class->load_iter($terms, $args);
500}
501
502sub group_role_iter {
503    my $author = shift;
504    my ($terms, $args) = @_;
505
506    my $grp_class = MT->model('group')
507        or return undef;
508    my @iters;
509    require MT::Association;
510    require MT::Role;
511    my $blog_id = delete $terms->{blog_id};
512    $args->{join} = MT::Association->join_on('role_id', {
513        type => $blog_id ? MT::Association::USER_BLOG_ROLE() : MT::Association::USER_ROLE(),
514        author_id => $author->id,
515        $blog_id ? (blog_id => $blog_id) : (),
516    });
517    my $user_iter = MT::Role->load_iter($terms, $args);
518    push @iters, $user_iter if $user_iter;
519
520    my @groups;
521    if (my $group_iter = $author->group_iter({ status => MT::Group::ACTIVE() })) {
522        while (my $g = $group_iter->()) {
523            push @groups, $g->id;
524        }
525    }
526    if (@groups) {
527        $args->{join} = MT::Association->join_on('role_id', {
528            type => $blog_id ? MT::Association::GROUP_BLOG_ROLE() : MT::Association::GROUP_ROLE(),
529            group_id => \@groups,
530            $blog_id ? (blog_id => $blog_id) : (),
531        });
532        my $group_iter = MT::Role->load_iter($terms, $args);
533        push @iters, $group_iter if $group_iter;
534    }
535    MT::Util::multi_iter(\@iters);
536}
537
538sub add_role {
539    my $author = shift;
540    my ($role, $blog) = @_;
541    $author->save unless $author->id;
542    $role->save unless $role->id;
543    $blog->save if $blog && !$blog->id;
544    require MT::Association;
545    MT::Association->link($author, @_);
546}
547
548sub add_group {
549    my $author = shift;
550    my ($group) = @_;
551    $author->save unless $author->id;
552    $group->save unless $group->id;
553    require MT::Association;
554    MT::Association->link($author, @_);
555}
556
557sub remove_role {
558    my $author = shift;
559    require MT::Association;
560    MT::Association->unlink($author, @_);
561}
562
563sub remove_group {
564    my $author = shift;
565    require MT::Association;
566    MT::Association->unlink($author, @_);
567}
568
569sub add_default_roles {
570    my $author = shift;
571    my $def = MT->config->DefaultAssignments;
572    return unless $def;
573
574    my $blog_class = MT->model('blog');
575    my $role_class = MT->model('role');
576
577    require MT::Association;
578    my @def = split ',', $def;
579    while (my $role_id = shift @def) {
580        my $blog_id = shift @def;
581        next unless $role_id && $blog_id;
582        my $blog = $blog_class->load($blog_id);
583        my $role = $role_class->load($role_id);
584        next unless ref $blog && ref $role;
585        MT::Association->link($author => $role => $blog);
586    }
587}
588
589sub to_hash {
590    my $author = shift;
591    my $hash = $author->SUPER::to_hash(@_);
592    my $app = MT->instance;
593    my $blog = $app->blog if $app->can('blog');
594    if ($blog) {
595        require MT::Permission;
596        if (my $perms = MT::Permission->load({ author_id => $author->id, blog_id => $blog->id })) {
597            my $perms_hash = $perms->to_hash;
598            $hash->{"author.$_"} = $perms_hash->{$_} foreach keys %$perms_hash;
599        }
600    }
601    $hash;
602}
603
604sub group_count {
605    my $author = shift;
606    require MT::Association;
607    MT::Association->count({
608        type => MT::Association::USER_GROUP(),
609        author_id => $author->id,
610    });
611}
612
613sub external_id {
614    my $author = shift;
615    if (@_) {
616        return $author->SUPER::external_id($author->unpack_external_id(@_));
617    }
618    my $value = $author->SUPER::external_id;
619    $value = $author->pack_external_id($value) if $value;
620}
621
622sub load {
623    my $author = shift;
624    my ($terms, $args) = @_;
625    if ((ref($terms) eq 'HASH') && exists($terms->{external_id})) {
626        $terms->{external_id} = $author->unpack_external_id($terms->{external_id});
627    }
628    $author->SUPER::load($terms, $args);
629}
630
631sub load_iter {
632    my $author = shift;
633    my ($terms, $args) = @_;
634    if ((ref($terms) eq 'HASH') && exists($terms->{external_id})) {
635        $terms->{external_id} = $author->unpack_external_id($terms->{external_id});
636    }
637    $author->SUPER::load_iter($terms, $args);
638}
639
640sub pack_external_id { return pack('H*', $_[1]); }
641sub unpack_external_id { return unpack('H*', $_[1]); }
642
643sub auth_icon_url {
644    my $author = shift;
645    my ($size) = @_;
646    $size ||= 'logo_small';
647
648    my $app = MT->instance;
649    my $static_path = $app->static_path;
650
651    my $auth_type = $author->auth_type;
652    return q() unless $auth_type;
653
654    if ( $author->type == MT::Author::AUTHOR() ) {
655        return $static_path . 'images/comment/mt_logo.png' ;
656    }
657   
658    my $authenticator = MT->commenter_authenticator( $auth_type );
659    return q() unless $authenticator;
660    return q() unless exists $authenticator->{$size};
661
662    my $logo = $authenticator->{$size};
663    if ( ( $logo !~ m!^https?://! ) || ( $logo !~ m!^/! ) ) {
664        $logo = $static_path . $logo;
665    }
666    return $logo;
667}
668
669sub userpic {
670    my $author = shift;
671
672    my $asset_id = $author->userpic_asset_id or return;
673    require MT::Asset;
674    my $asset = MT->model('asset.image')->load($asset_id) or return;
675
676    $asset;
677}
678
679sub userpic_thumbnail_options {
680    my $author = shift;
681
682    # Specify these to put an author's userpic thumbnail in a consistent
683    # place whenever userpic_url is called as an instance method on a
684    # particular author.
685    my %real_userpic_options = (
686        Path   => File::Spec->catdir( MT->config->AssetCacheDir, 'userpics' ),
687        Format => MT->translate('userpic-[_1]-%wx%h%x', $author->id),
688    ) if ref $author;
689
690    my $cfg = MT->config;
691    my $max_dim = $cfg->UserpicThumbnailSize;
692    my $square  = $cfg->UserpicAllowRect ? 0 : 1;
693    return (
694        Width  => $max_dim,
695        Height => $max_dim,
696        Square => $square,
697        Type   => 'png',
698        %real_userpic_options,
699    );
700}
701
702sub userpic_file {
703    my $author = shift;
704
705    my $asset = $author->userpic;
706    if (!$asset) {
707        $asset = MT->model('asset.image')->new;
708        $asset->file_name('userpic');
709    }
710
711    my %thumb_param = $author->userpic_thumbnail_options();
712    my $thumb_file = File::Spec->catfile(
713        $asset->thumbnail_path(%thumb_param),
714        $asset->thumbnail_filename(%thumb_param),
715    );
716
717    return $thumb_file;
718}
719
720sub userpic_url {
721    my $author = shift;
722    my (%param) = @_;
723
724    my $asset = delete $param{Asset};
725    if (!$asset && ref $author) {
726        $asset = $author->userpic;
727    }
728    return if !$asset;
729
730    my @info = $asset->thumbnail_url(
731        $author->userpic_thumbnail_options(),
732        %param,
733    );
734    if ($info[0] !~ m!^https?://!) {
735        my $static_host = MT->instance->static_path;
736        if ($static_host =~ m!^https?://!) {
737            $static_host =~ s!^(https?://[^/]+?)!$1!;
738            $info[0] = $static_host . $info[0];
739        }
740    }
741    return wantarray ? @info : $info[0];
742}
743
744sub userpic_html {
745    my $author = shift;
746    my ($thumb_url, $w, $h) = $author->userpic_url(@_) or return;
747    return unless $thumb_url;
748    sprintf q{<img src="%s?%d" width="%d" height="%d" alt="" />},
749      MT::Util::encode_html($thumb_url), $author->userpic->id, $w, $h;
750}
751
7521;
753
754__END__
755
756=head1 NAME
757
758MT::Author - Movable Type author record
759
760=head1 SYNOPSIS
761
762    use MT::Author;
763    my $author = MT::Author->new;
764    $author->name('Foo Bar');
765    $author->set_password('secret');
766    $author->save
767        or die $author->errstr;
768
769    my $author = MT::Author->load($author_id);
770
771=head1 DESCRIPTION
772
773An I<MT::Author> object represents a user in the Movable Type system. It
774contains profile information (name, nickname, email address, etc.), global
775permissions settings (blog creation, activity log viewing), and authentication
776information (password, public key). It does not contain any per-blog
777permissions settings--for those, look at the I<MT::Permission> object.
778
779=head1 USAGE
780
781As a subclass of I<MT::Object>, I<MT::Author> inherits all of the
782data-management and -storage methods from that class; thus you should look
783at the I<MT::Object> documentation for details about creating a new object,
784loading an existing object, saving an object, etc.
785
786The following methods are unique to the I<MT::Author> interface:
787
788=head2 $author->set_password($pass)
789
790One-way encrypts I<$pass> with a randomly-generated salt, using the Unix
791I<crypt> function, and sets the I<password> data field in the I<MT::Author>
792object I<$author>.
793
794Because the password is one-way encrypted, there is B<no way> of recovering
795the initial password.
796
797=head2 $author->is_valid_password($check_pass)
798
799Tests whether I<$check_pass> is a valid password for the I<MT::Author> object
800I<$author> (ie, whether it matches the password originally set using
801I<set_password>). This check is done by one-way encrypting I<$check_pass>,
802using the same salt used to encrypt the original password, then comparing the
803two encrypted strings for equality.
804
805=head1 DATA ACCESS METHODS
806
807The I<MT::Author> object holds the following pieces of data. These fields can
808be accessed and set using the standard data access methods described in the
809I<MT::Object> documentation.
810
811=over 4
812
813=item * id
814
815The numeric ID of the author.
816
817=item * name
818
819The username of the author. This is the username used to log in to the system.
820
821=item * nickname
822
823The author nickname (or "display" name). This is the preferred name used for publishing the author's name.
824
825=item * password
826
827The author's password, one-way encrypted. If you wish to check the validity of
828a password, you should use the I<is_valid_password> method, above.
829
830=item * type
831
832The 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).
833
834=item * status
835
836A column that defines whether the records of an AUTHOR type are ACTIVE, INACTIVE or PENDING (constants declared in this package).
837
838=item * commenter_status
839
840This 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.
841
842=item * email
843
844The author's email address.
845
846=item * url
847
848The author's homepage URL.
849
850=item * hint
851
852The answer to the question used when recovering the user's password.
853
854=item * external_id
855
856A column for holding a value used to synchronize the MT author record with an external record.
857
858=item * can_create_blog
859
860A boolean flag specifying whether the author has permission to create a new
861blog in the system.
862
863=item * can_view_log
864
865A boolean flag specifying whether the author has permission to view the global
866system activity log.
867
868=item * created_by
869
870The 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.
871
872=item * public_key
873
874The author's ASCII-armoured public key, to be used in the future for verifying
875incoming email messages.
876
877=back
878
879=head1 DATA LOOKUP
880
881In addition to numeric ID lookup, you can look up or sort records by any
882combination of the following fields. See the I<load> documentation in
883I<MT::Object> for more information.
884
885=over 4
886
887=item * name
888
889=item * email
890
891=back
892
893=head1 NOTES
894
895=over 4
896
897=item *
898
899When you remove an author using I<MT::Author::remove>, in addition to removing
900the author record, all of the author's permissions (I<MT::Permission> objects)
901will be removed, as well.
902
903=back
904
905=head1 AUTHOR & COPYRIGHTS
906
907Please see the I<MT> manpage for author, copyright, and license information.
908
909=cut
Note: See TracBrowser for help on using the browser.