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

Revision 2690, 25.0 kB (checked in by takayama, 17 months ago)

Fixed BugId:80476
* Applied an patch

  • 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    my (%param) = @_;
672
673    my $asset = $param{Asset};
674    return $asset if $asset;
675
676    my $asset_id = $author->userpic_asset_id or return;
677    require MT::Asset;
678    my $asset = MT->model('asset.image')->load($asset_id) or return;
679
680    $asset;
681}
682
683sub userpic_thumbnail_options {
684    my $author = shift;
685
686    # Specify these to put an author's userpic thumbnail in a consistent
687    # place whenever userpic_url is called as an instance method on a
688    # particular author.
689    my %real_userpic_options = (
690        Path   => File::Spec->catdir( MT->config->AssetCacheDir, 'userpics' ),
691        Format => MT->translate('userpic-[_1]-%wx%h%x', $author->id),
692    ) if ref $author;
693
694    my $cfg = MT->config;
695    my $max_dim = $cfg->UserpicThumbnailSize;
696    my $square  = $cfg->UserpicAllowRect ? 0 : 1;
697    return (
698        Width  => $max_dim,
699        Height => $max_dim,
700        Square => $square,
701        Type   => 'png',
702        %real_userpic_options,
703    );
704}
705
706sub userpic_file {
707    my $author = shift;
708
709    my $asset = $author->userpic;
710    if (!$asset) {
711        $asset = MT->model('asset.image')->new;
712        $asset->file_name('userpic');
713    }
714
715    my %thumb_param = $author->userpic_thumbnail_options();
716    my $thumb_file = File::Spec->catfile(
717        $asset->thumbnail_path(%thumb_param),
718        $asset->thumbnail_filename(%thumb_param),
719    );
720
721    return $thumb_file;
722}
723
724sub userpic_url {
725    my $author = shift;
726    my (%param) = @_;
727
728    my $asset = delete $param{Asset};
729    if (!$asset && ref $author) {
730        $asset = $author->userpic;
731    }
732    return if !$asset;
733
734    my @info = $asset->thumbnail_url(
735        $author->userpic_thumbnail_options(),
736        %param,
737    );
738    if ($info[0] !~ m!^https?://!) {
739        my $static_host = MT->instance->static_path;
740        if ($static_host =~ m!^https?://!) {
741            $static_host =~ s!^(https?://[^/]+?)!$1!;
742            $info[0] = $static_host . $info[0];
743        }
744    }
745    return wantarray ? @info : $info[0];
746}
747
748sub userpic_html {
749    my $author = shift;
750    my ($thumb_url, $w, $h) = $author->userpic_url(@_) or return;
751    return unless $thumb_url;
752    sprintf q{<img src="%s?%d" width="%d" height="%d" alt="" />},
753      MT::Util::encode_html($thumb_url), $author->userpic(@_)->id, $w, $h;
754}
755
7561;
757
758__END__
759
760=head1 NAME
761
762MT::Author - Movable Type author record
763
764=head1 SYNOPSIS
765
766    use MT::Author;
767    my $author = MT::Author->new;
768    $author->name('Foo Bar');
769    $author->set_password('secret');
770    $author->save
771        or die $author->errstr;
772
773    my $author = MT::Author->load($author_id);
774
775=head1 DESCRIPTION
776
777An I<MT::Author> object represents a user in the Movable Type system. It
778contains profile information (name, nickname, email address, etc.), global
779permissions settings (blog creation, activity log viewing), and authentication
780information (password, public key). It does not contain any per-blog
781permissions settings--for those, look at the I<MT::Permission> object.
782
783=head1 USAGE
784
785As a subclass of I<MT::Object>, I<MT::Author> inherits all of the
786data-management and -storage methods from that class; thus you should look
787at the I<MT::Object> documentation for details about creating a new object,
788loading an existing object, saving an object, etc.
789
790The following methods are unique to the I<MT::Author> interface:
791
792=head2 $author->set_password($pass)
793
794One-way encrypts I<$pass> with a randomly-generated salt, using the Unix
795I<crypt> function, and sets the I<password> data field in the I<MT::Author>
796object I<$author>.
797
798Because the password is one-way encrypted, there is B<no way> of recovering
799the initial password.
800
801=head2 $author->is_valid_password($check_pass)
802
803Tests whether I<$check_pass> is a valid password for the I<MT::Author> object
804I<$author> (ie, whether it matches the password originally set using
805I<set_password>). This check is done by one-way encrypting I<$check_pass>,
806using the same salt used to encrypt the original password, then comparing the
807two encrypted strings for equality.
808
809=head1 DATA ACCESS METHODS
810
811The I<MT::Author> object holds the following pieces of data. These fields can
812be accessed and set using the standard data access methods described in the
813I<MT::Object> documentation.
814
815=over 4
816
817=item * id
818
819The numeric ID of the author.
820
821=item * name
822
823The username of the author. This is the username used to log in to the system.
824
825=item * nickname
826
827The author nickname (or "display" name). This is the preferred name used for publishing the author's name.
828
829=item * password
830
831The author's password, one-way encrypted. If you wish to check the validity of
832a password, you should use the I<is_valid_password> method, above.
833
834=item * type
835
836The 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).
837
838=item * status
839
840A column that defines whether the records of an AUTHOR type are ACTIVE, INACTIVE or PENDING (constants declared in this package).
841
842=item * commenter_status
843
844This 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.
845
846=item * email
847
848The author's email address.
849
850=item * url
851
852The author's homepage URL.
853
854=item * hint
855
856The answer to the question used when recovering the user's password.
857
858=item * external_id
859
860A column for holding a value used to synchronize the MT author record with an external record.
861
862=item * can_create_blog
863
864A boolean flag specifying whether the author has permission to create a new
865blog in the system.
866
867=item * can_view_log
868
869A boolean flag specifying whether the author has permission to view the global
870system activity log.
871
872=item * created_by
873
874The 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.
875
876=item * public_key
877
878The author's ASCII-armoured public key, to be used in the future for verifying
879incoming email messages.
880
881=back
882
883=head1 DATA LOOKUP
884
885In addition to numeric ID lookup, you can look up or sort records by any
886combination of the following fields. See the I<load> documentation in
887I<MT::Object> for more information.
888
889=over 4
890
891=item * name
892
893=item * email
894
895=back
896
897=head1 NOTES
898
899=over 4
900
901=item *
902
903When you remove an author using I<MT::Author::remove>, in addition to removing
904the author record, all of the author's permissions (I<MT::Permission> objects)
905will be removed, as well.
906
907=back
908
909=head1 AUTHOR & COPYRIGHTS
910
911Please see the I<MT> manpage for author, copyright, and license information.
912
913=cut
Note: See TracBrowser for help on using the browser.