Revision 305

Date:
2013/04/22 16:42:50
Author:
ahitrov
Revision Log:
Credentials
Files:

Legend:

 
Added
 
Removed
 
Modified
  • utf8/plugins/users/config.proto

     
    18 18 PROFILE_AUTH_METHOD = RPC
    19 19 REWRITE += PROFILE_AUTH_METHOD
    20 20
    21
    21 PROFILE_USE_CREDENTIALS = <YES/NO>
    22 REWRITE += PROFILE_USE_CREDENTIALS
    22 23 ########################################################################
    23 24 #
    24 25 # PROFILE_DOCUMENT_CLASS
  • utf8/plugins/users/lib/users/Email.pm

     
    1 package users::Email;
    2
    3 use base "Contenido::Document";
    4 use Contenido::Globals;
    5
    6 use overload (
    7 '""' => '_stringify',
    8 );
    9
    10 sub extra_properties
    11 {
    12 return (
    13 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'E-mail' },
    14 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус e-mail-адреса',
    15 'cases' => [
    16 [0, 'Не активен'],
    17 [1, 'Подтвержден'],
    18 [2, 'Основной'],
    19 [3, 'Потерян / заблокирован'],
    20 ],
    21 },
    22 { 'attr' => 'name_orig', 'type' => 'string', 'rusname' => 'E-mail без приведения к нижнему регистру' },
    23 # { 'attr' => 'login', 'type' => 'string', 'rusname' => 'Login' },
    24 # { 'attr' => 'passwd', 'type' => 'string', 'rusname' => 'Password' },
    25 )
    26 }
    27
    28 sub _stringify {
    29 my $self = shift;
    30
    31 return $self->name;
    32 }
    33
    34
    35 sub class_name
    36 {
    37 return 'E-mail адрес';
    38 }
    39
    40 sub class_description
    41 {
    42 return 'E-mail адрес';
    43 }
    44
    45 sub search_fields
    46 {
    47 return ('name');
    48 }
    49
    50 sub class_table
    51 {
    52 return 'users::SQL::CredentialsTable';
    53 }
    54
    55 sub contenido_status_style
    56 {
    57 my $self = shift;
    58 if ( $self->status == 2 ) {
    59 return 'color:green;';
    60 } elsif ( $self->status == 3 ) {
    61 return 'color:red;';
    62 }
    63 }
    64
    65 sub pre_store
    66 {
    67 my $self = shift;
    68
    69 my $default_section = $project->s_alias->{user_emails} if ref $project->s_alias eq 'HASH' && exists $project->s_alias->{user_emails};
    70 if ( $default_section && !$self->{sections} ) {
    71 $self->{sections} = $default_section;
    72 }
    73
    74 return 1;
    75 }
    76 1;
  • utf8/plugins/users/lib/users/Init.pm

     
    13 13 # users::SomeClass
    14 14 Contenido::Init::load_classes(qw(
    15 15 users::SQL::UserProfile
    16 users::SQL::CredentialsTable
    16 17
    17 18 users::UserProfile
    19 users::Email
    20 users::Phone
    18 21 users::Section
    22
    23 users::OA::VK
    24 users::OA::FaceBook
    25 users::OA::Google
    26 users::OA::Mailru
    19 27 ));
    20 28
    21 29 sub init {
    22 30 push @{ $state->{'available_documents'} }, 'users::UserProfile' if $state->{users}->profile_document_class eq 'users::UserProfile';
    23 31 push @{ $state->{'available_sections'} }, 'users::Section';
    32 if ( $state->{users}->use_credentials ) {
    33 push @{ $state->{'available_documents'} },
    34 qw( users::Email users::Phone users::OA::VK users::OA::FaceBook users::OA::Google users::OA::Mailru );
    35 }
    24 36 0;
    25 37 }
    26 38
  • utf8/plugins/users/lib/users/Keeper.pm

     
    39 39 #
    40 40 # login => login пользователя
    41 41 # email => e-mail пользователя
    42 # phone => телефон пользователя
    42 43 # passwd => пароль пользователя
    43 44 # ----------------------------------------------------------------------------
    44 45 sub login {
    45 46
    46 my $self = shift;
    47 my %opts = @_;
    47 my $self = shift;
    48 my (%opts) = @_;
    48 49
    49 return if !($opts{login} || $opts{email}) && !$opts{passwd};
    50 my $passmd5 = Digest::MD5::md5_hex($opts{passwd});
    51 my $class = $self->state->profile_document_class;
    52 my $res = $keeper->get_documents (
    53 class => $class,
    54 $opts{login} ? (login => $opts{login}) : (),
    55 $opts{email} ? (email => lc($opts{email})) : (),
    56 status => [1,2,3,4,5],
    57 return_mode => 'array_ref',
    58 );
    59 $res = ref $res eq 'ARRAY' ? $res->[0] : undef;
    60 return unless ref $res;
    61 # warn "Password = ".$opts{passwd}."; Pass MD5 = $passmd5; user MD5 = ".$res->passwd."\n" if $DEBUG;
    62 if ($res->passwd eq $passmd5 ) {
    63 my $lastlogin = Contenido::DateTime->new ( postgres => $res->lastlogin );
    64 my $now = Contenido::DateTime->new;
    65 my $then = $now->clone;
    66 $then->subtract( hours => 2 );
    67 if ( DateTime->compare($then, $lastlogin) == 1 ) {
    68 $res->lastlogin( $now->ymd('-').' '.$now->hms );
    69 $res->passwd(undef);
    70 $res->store;
    71 $res->lastlogin( $lastlogin->ymd('-').' '.$lastlogin->hms );
    50 return if !($opts{login} || $opts{email} || $opts{phone}) && !$opts{passwd};
    51
    52 my $password = delete $opts{passwd};
    53 my $passmd5 = Digest::MD5::md5_hex( $password );
    54 my $class = $self->state->profile_document_class;
    55 my $profile = $self->get_profile( %opts, status => [qw(1 2 3 4 5)] );
    56 return unless ref $profile;
    57
    58 my $result;
    59 # warn "Password = ".$opts{passwd}."; Pass MD5 = $passmd5; user MD5 = ".$res->passwd."\n" if $DEBUG;
    60 if ($profile->passwd eq $passmd5 ) {
    61 my ($prop) = grep { $_->{attr} eq 'lastlogin' } $profile->structure;
    62 if ( ref $prop ) {
    63 my $now = Contenido::DateTime->new;
    64 $profile->lastlogin( $now->ymd('-').' '.$now->hms );
    65 $profile->store;
    72 66 }
    73 return $res;
    74 }else{
    75 return;
    76 }
    77
    67 return $profile;
    68 } else {
    69 return undef;
    70 }
    78 71 }
    79 72
    80 73
     
    125 118 # email => по e-mail
    126 119 # nickname=> по никнейму
    127 120 # status => фильтр по статусу
    121 # При включенных credentials:
    122 # phone => по телефону
    123 # vkontakte => по логину ВК
    124 # facebook => по логину Facebook
    125 # google => по логину Google
    126 # mailru => по логину Mail.ru
    128 127 # ----------------------------------------------------------------------------
    129 128 sub get_profile {
    130 129
    131 my $self = shift;
    132 my %opts = @_;
    130 my $self = shift;
    131 my (%opts) = @_;
    133 132
    134 return if !$opts{login} && !$opts{id} && !$opts{email} && !$opts{nickname};
    135 my $class = $self->state->profile_document_class;
    136 my $res = $keeper->get_documents (
    133 my $profile;
    134 if ( $self->state->use_credentials && !$opts{login} && !$opts{id} ) {
    135 $profile = $self->get_profile_by_credential ( %opts );
    136 } else {
    137 return if !$opts{login} && !$opts{id} && !$opts{email} && !$opts{nickname};
    138 my $class = $self->state->profile_document_class;
    139 ($profile) = $keeper->get_documents (
    140 class => $class,
    141 %opts,
    142 limit => 1,
    143 );
    144 }
    145 return $profile;
    146 }
    147
    148
    149 sub get_profile_by_credential {
    150
    151 my $self = shift;
    152 my (%opts) = @_;
    153
    154 my $credential;
    155 if ( $opts{email} && $self->_email_format($opts{email}) ) {
    156 ($credential) = $keeper->get_documents (
    157 class => 'users::Email',
    158 name => $self->_email_reduction( delete $opts{email} ),
    159 limit => 1,
    160 );
    161 } elsif ( $opts{phone} && $self->_phone_reduction($opts{phone}) ) {
    162 ($credential) = $keeper->get_documents (
    163 class => 'users::Phone',
    164 name => $self->_phone_reduction( delete $opts{phone} ),
    165 limit => 1,
    166 );
    167 } elsif ( $opts{vkontake} ) {
    168 ($credential) = $keeper->get_documents (
    169 class => 'users::OA::VK',
    170 ext_id => delete $opts{vkontakte},
    171 limit => 1,
    172 );
    173 } elsif ( $opts{facebook} ) {
    174 ($credential) = $keeper->get_documents (
    175 class => 'users::OA::FaceBook',
    176 ext_id => delete $opts{facebook},
    177 limit => 1,
    178 );
    179 } elsif ( $opts{mailru} ) {
    180 ($credential) = $keeper->get_documents (
    181 class => 'users::OA::Mailru',
    182 ext_id => delete $opts{mailru},
    183 limit => 1,
    184 );
    185 } elsif ( $opts{google} ) {
    186 ($credential) = $keeper->get_documents (
    187 class => 'users::OA::Google',
    188 ext_id => delete $opts{google},
    189 limit => 1,
    190 );
    191 }
    192 return unless ref $credential;
    193
    194 my $class = $self->state->profile_document_class;
    195 my $profile = $keeper->get_document_by_id ( $credential->uid,
    137 196 class => $class,
    138 197 %opts,
    139 return_mode => 'array_ref',
    140 198 );
    141 $res = ref $res eq 'ARRAY' && scalar @$res ? $res->[0] : undef;
    142 return $res;
    199 return $profile;
    143 200 }
    144 201
    202
    203 ###### Additional subs
    204 ###################################################
    205 sub _email_format {
    206 my $self = shift;
    207 my $email = shift;
    208 for ( $email ) {
    209 s/^\s+//;
    210 s/\s+$//;
    211 }
    212 if ( $email =~ /^[\-\.\w\d]+\@[a-z\d\-\.]+\.[a-z\d]+$/i ) {
    213 return $email;
    214 }
    215 return undef;
    216 }
    217
    218 sub _email_reduction {
    219 my $self = shift;
    220 my $email = shift;
    221 for ( $email ) {
    222 s/^\s+//;
    223 s/\s+$//;
    224 }
    225 if ( $email =~ /^[\-\.\w\d]+\@[a-z\d\-\.]+\.[a-z\d]+$/i ) {
    226 return lc( $email );
    227 }
    228 return undef;
    229 }
    230
    231 sub _phone_format {
    232 my $self = shift;
    233 my $phone = shift;
    234 if ( $phone ) {
    235 for ( $phone ) {
    236 s/-//g;
    237 s/\[/\(/g;
    238 s/\]/\)/g;
    239 s/^\s+//;
    240 s/\s+$//;
    241 }
    242 if ( $phone =~ /^\+?(\d)+[\(\ ]+(\d+)[\)\ ]+([\d+\ ])$/ ) {
    243 my $cc = $1;
    244 my $code = $2;
    245 my $number = $3; $number =~ s/\D//g;
    246 $phone = $cc.'('.$code.')'.$phone;
    247 } elsif ( $phone =~ /^[\(]+(\d+)[\)\ ]+([\d+\ ])$/ ) {
    248 my $cc = '7';
    249 my $code = $1;
    250 my $number = $2; $number =~ s/\D//g;
    251 $phone = $cc.'('.$code.')'.$phone;
    252 } else {
    253 $phone =~ s/\D//g;
    254 }
    255 return $phone;
    256 }
    257 }
    258
    259 sub _phone_reduction {
    260 my $self = shift;
    261 my $phone = shift;
    262 if ( $phone ) {
    263 $phone =~ s/\D//g;
    264 return $phone || undef;
    265 }
    266 }
    267
    145 268 1;
  • utf8/plugins/users/lib/users/OA/Credential.pm

     
    1 package users::OA::Credential;
    2
    3 use base "Contenido::Document";
    4 use Contenido::Globals;
    5
    6 sub extra_properties
    7 {
    8 return (
    9 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'Имя в системе' },
    10 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус',
    11 'cases' => [
    12 [0, 'Не активен'],
    13 [1, 'Подтвержден'],
    14 [3, 'Потерян / заблокирован'],
    15 ],
    16 },
    17 { 'attr' => 'ava_url', 'type' => 'url', 'rusname' => 'Аватар (url)' },
    18 { 'attr' => 'avatar', 'type' => 'image', 'rusname' => 'Аватар' },
    19 # { 'attr' => 'login', 'type' => 'string', 'rusname' => 'Login' },
    20 # { 'attr' => 'passwd', 'type' => 'string', 'rusname' => 'Password' },
    21 )
    22 }
    23
    24 sub class_name
    25 {
    26 return 'OpenAuth Proto';
    27 }
    28
    29 sub class_description
    30 {
    31 return 'OpenAuth Proto class';
    32 }
    33
    34 sub search_fields
    35 {
    36 return ('ext_id', 'name', 'uid');
    37 }
    38
    39 sub class_table
    40 {
    41 return 'users::SQL::CredentialsTable';
    42 }
    43
    44 sub contenido_status_style
    45 {
    46 my $self = shift;
    47 if ( $self->status == 3 ) {
    48 return 'color:red;';
    49 }
    50 }
    51
    52 sub pre_store
    53 {
    54 my $self = shift;
    55
    56 my $default_section = $project->s_alias->{user_externals} if ref $project->s_alias eq 'HASH' && exists $project->s_alias->{user_externals};
    57 if ( $default_section && !$self->{sections} ) {
    58 $self->{sections} = $default_section;
    59 }
    60
    61 return 1;
    62 }
    63 1;
  • utf8/plugins/users/lib/users/OA/FaceBook.pm

     
    1 package users::OA::FaceBook;
    2
    3 use base "users::OA::Credential";
    4 use Contenido::Globals;
    5
    6 sub extra_properties
    7 {
    8 return (
    9 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'Имя в системе' },
    10 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус',
    11 'cases' => [
    12 [0, 'Не активен'],
    13 [1, 'Подтвержден'],
    14 [3, 'Потерян / заблокирован'],
    15 ],
    16 },
    17 )
    18 }
    19
    20 sub class_name
    21 {
    22 return 'OpenAuth FaceBook';
    23 }
    24
    25 sub class_description
    26 {
    27 return 'OpenAuth FaceBook';
    28 }
    29
    30 1;
  • utf8/plugins/users/lib/users/OA/Google.pm

     
    1 package users::OA::Google;
    2
    3 use base "users::OA::Credential";
    4 use Contenido::Globals;
    5
    6 sub extra_properties
    7 {
    8 return (
    9 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'Имя в системе' },
    10 { 'attr' => 'email', 'type' => 'string', 'rusname' => 'E-mail' },
    11 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус',
    12 'cases' => [
    13 [0, 'Не активен'],
    14 [1, 'Подтвержден'],
    15 [3, 'Потерян / заблокирован'],
    16 ],
    17 },
    18 )
    19 }
    20
    21 sub class_name
    22 {
    23 return 'OpenAuth Google';
    24 }
    25
    26 sub class_description
    27 {
    28 return 'OpenAuth Google';
    29 }
    30
    31 1;
  • utf8/plugins/users/lib/users/OA/Mailru.pm

     
    1 package users::OA::Mailru;
    2
    3 use base "users::OA::Credential";
    4 use Contenido::Globals;
    5
    6 sub extra_properties
    7 {
    8 return (
    9 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'Имя в системе' },
    10 { 'attr' => 'email', 'type' => 'string', 'rusname' => 'E-mail' },
    11 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус',
    12 'cases' => [
    13 [0, 'Не активен'],
    14 [1, 'Подтвержден'],
    15 [3, 'Потерян / заблокирован'],
    16 ],
    17 },
    18 )
    19 }
    20
    21 sub class_name
    22 {
    23 return 'OpenAuth Mail.ru';
    24 }
    25
    26 sub class_description
    27 {
    28 return 'OpenAuth Mail.ru';
    29 }
    30
    31 1;
  • utf8/plugins/users/lib/users/OA/VK.pm

     
    1 package users::OA::VK;
    2
    3 use base "users::OA::Credential";
    4 use Contenido::Globals;
    5
    6 sub extra_properties
    7 {
    8 return (
    9 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'Имя в системе' },
    10 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус',
    11 'cases' => [
    12 [0, 'Не активен'],
    13 [1, 'Подтвержден'],
    14 [3, 'Потерян / заблокирован'],
    15 ],
    16 },
    17 )
    18 }
    19
    20 sub class_name
    21 {
    22 return 'OpenAuth ВКонтакте';
    23 }
    24
    25 sub class_description
    26 {
    27 return 'OpenAuth ВКонтакте';
    28 }
    29
    30 1;
  • utf8/plugins/users/lib/users/Phone.pm

     
    1 package users::Phone;
    2
    3 use base "Contenido::Document";
    4 use Contenido::Globals;
    5
    6 sub extra_properties
    7 {
    8 return (
    9 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'Телефон (только номер)' },
    10 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус e-mail-адреса',
    11 'cases' => [
    12 [0, 'Не активен'],
    13 [1, 'Подтвержден'],
    14 [2, 'Основной'],
    15 [3, 'Потерян / заблокирован'],
    16 ],
    17 },
    18 { 'attr' => 'name_format', 'type' => 'string', 'rusname' => 'Телефон отформатированный' },
    19 { 'attr' => 'name_orig', 'type' => 'string', 'rusname' => 'Телефон (ввод пользователя)' },
    20 # { 'attr' => 'login', 'type' => 'string', 'rusname' => 'Login' },
    21 # { 'attr' => 'passwd', 'type' => 'string', 'rusname' => 'Password' },
    22 )
    23 }
    24
    25 sub class_name
    26 {
    27 return 'Телефон';
    28 }
    29
    30 sub class_description
    31 {
    32 return 'Телефон';
    33 }
    34
    35 sub search_fields
    36 {
    37 return ('name');
    38 }
    39
    40 sub class_table
    41 {
    42 return 'users::SQL::CredentialsTable';
    43 }
    44
    45 sub contenido_status_style
    46 {
    47 my $self = shift;
    48 if ( $self->status == 2 ) {
    49 return 'color:green;';
    50 } elsif ( $self->status == 3 ) {
    51 return 'color:red;';
    52 }
    53 }
    54
    55 sub pre_store
    56 {
    57 my $self = shift;
    58
    59 my $default_section = $project->s_alias->{user_phones} if ref $project->s_alias eq 'HASH' && exists $project->s_alias->{user_phones};
    60 if ( $default_section && !$self->{sections} ) {
    61 $self->{sections} = $default_section;
    62 }
    63
    64 return 1;
    65 }
    66 1;
  • utf8/plugins/users/lib/users/SQL/CredentialsTable.pm

     
    1 package users::SQL::CredentialsTable;
    2
    3 use strict;
    4 use base 'SQL::DocumentTable';
    5
    6 sub db_table
    7 {
    8 return 'profile_credentials';
    9 }
    10
    11 sub available_filters {
    12 my @available_filters = qw(
    13 _class_filter
    14 _status_filter
    15 _in_id_filter
    16 _id_filter
    17 _name_filter
    18 _class_excludes_filter
    19 _sfilter_filter
    20 _datetime_filter
    21 _date_equal_filter
    22 _date_filter
    23 _previous_days_filter
    24 _s_filter
    25
    26 _excludes_filter
    27 _link_filter
    28 _uid_filter
    29 _ext_id_filter
    30 _main_filter
    31 );
    32 return \@available_filters;
    33 }
    34
    35 # ----------------------------------------------------------------------------
    36 # Свойства храним в массивах, потому что порядок важен!
    37 # Это общие свойства - одинаковые для всех документов.
    38 #
    39 # attr - обязательный параметр, название атрибута;
    40 # type - тип аттрибута, требуется для отображдения;
    41 # rusname - русское название, опять же требуется для отображения;
    42 # hidden - равен 1, когда
    43 # readonly - инициализации при записи только без изменения в дальнейшем
    44 # db_field - поле в таблице
    45 # default - значение по умолчанию (поле всегда имеет это значение)
    46 # ----------------------------------------------------------------------------
    47 sub required_properties
    48 {
    49 my $self = shift;
    50
    51 my @parent_properties = grep { $_->{attr} ne 'sections' && $_->{attr} ne 'dtime' } $self->SUPER::required_properties;
    52 return (
    53 @parent_properties,
    54 {
    55 'attr' => 'uid',
    56 'type' => 'pickup',
    57 'rusname' => 'Идентификатор пользователя',
    58 'lookup_opts' => {
    59 'class' => 'mynotes::UserProfile',
    60 'search_by' => 'name',
    61 },
    62 'db_field' => 'uid',
    63 'db_type' => 'integer',
    64 'db_opts' => "not null default 0",
    65 },
    66 {
    67 'attr' => 'ext_id',
    68 'type' => 'integer',
    69 'rusname' => 'External ID',
    70 'db_field' => 'ext_id',
    71 'db_type' => 'integer',
    72 'db_opts' => "not null default 0",
    73 'default' => 0,
    74 },
    75 {
    76 'attr' => 'opaque',
    77 'type' => 'status',
    78 'rusname' => 'Видимость',
    79 'cases' => [
    80 [0, 'не видно никому'],
    81 [1, 'видно близким людям'],
    82 [2, 'видно всем друзьям'],
    83 [3, 'видно всем пользователям'],
    84 [10, 'видно всем'],
    85 ],
    86 'db_field' => 'opaque',
    87 'db_type' => 'integer',
    88 },
    89 {
    90 'attr' => 'confirm',
    91 'type' => 'string',
    92 'rusname' => 'Confirmation string',
    93 'db_field' => 'confirm',
    94 'db_type' => 'varchar(32)',
    95 },
    96 {
    97 'attr' => 'main',
    98 'type' => 'checkbox',
    99 'rusname' => 'Main credential',
    100 'db_field' => 'main',
    101 'db_type' => 'integer',
    102 },
    103 {
    104 'attr' => 'sections',
    105 'type' => 'sections_list',
    106 'rusname' => 'Секция',
    107 'hidden' => 1,
    108 'db_field' => 'sections',
    109 'db_type' => 'integer',
    110 },
    111
    112 );
    113 }
    114
    115
    116 sub _s_filter {
    117 my ($self,%opts)=@_;
    118 return undef unless ( exists $opts{s} );
    119 return &SQL::Common::_generic_int_filter('d.sections', $opts{s});
    120 }
    121
    122 sub _uid_filter {
    123 my ($self,%opts)=@_;
    124 return undef unless ( exists $opts{uid} );
    125 return &SQL::Common::_generic_int_filter('d.uid', $opts{uid});
    126 }
    127
    128 sub _main_filter {
    129 my ($self,%opts)=@_;
    130 return undef unless ( exists $opts{main} );
    131 return &SQL::Common::_generic_int_filter('d.main', $opts{main});
    132 }
    133
    134 sub _ext_id_filter {
    135 my ($self,%opts)=@_;
    136 return undef unless ( exists $opts{ext_id} );
    137 return &SQL::Common::_generic_int_filter('d.ext_id', $opts{ext_id});
    138 }
    139
    140 sub _name_filter {
    141 my ($self,%opts)=@_;
    142 return undef unless ( exists $opts{name} );
    143 if ( exists $opts{ext_id} ) {
    144 return &SQL::Common::_generic_text_filter('d.name', $opts{name});
    145 } else {
    146 my ($w1, $v1) = &SQL::Common::_generic_text_filter('d.name', $opts{name});
    147 my ($w2, $v2) = &SQL::Common::_generic_int_filter('d.ext_id', 0);
    148 return " ($w1) AND ($w2) ", [@$v1, @$v2];
    149 }
    150 }
    151
    152 1;
  • utf8/plugins/users/lib/users/SQL/UserProfile.pm

     
    1 1 package users::SQL::UserProfile;
    2 2
    3 3 use base 'SQL::DocumentTable';
    4 use Contenido::Globals;
    4 5
    5 6 sub db_table
    6 7 {
     
    152 153 'attr' => 'email',
    153 154 'type' => 'string',
    154 155 'rusname' => 'E-mail (primary)',
    156 'hidden' => $state->{users}->use_credentials ? 1 : undef,
    157 'readonly' => $state->{users}->use_credentials ? 1 : undef,
    155 158 'db_field' => 'email',
    156 159 'db_type' => 'text',
    157 160 },
  • utf8/plugins/users/lib/users/State.pm.proto

     
    20 20 $self->{db_password} = '';
    21 21 $self->{db_port} = '';
    22 22 $self->{profile_document_class} = '@PROFILE_DOCUMENT_CLASS@' || 'users::UserProfile';
    23 $self->{use_credentials} = uc('@PROFILE_USE_CREDENTIALS@') eq 'YES' ? 1 : 0;
    23 24
    24 25 $self->{data_directory} = '';
    25 26 $self->{images_directory} = '';
     
    51 52 $self->{attributes}->{$_} = 'SCALAR' for qw(
    52 53 db_type
    53 54 profile_document_class
    55 use_credentials
    54 56 db_keepalive
    55 57 db_host
    56 58 db_port
  • utf8/plugins/users/lib/users/UserProfile.pm

     
    4 4 use Digest::MD5;
    5 5 use Contenido::Globals;
    6 6
    7 my %CREDENTIAL_FIELDS = (
    8 'users::Email' => 'email',
    9 'users::Phone' => 'phone',
    10 'users::OA::VK' => 'vkontakte',
    11 'users::OA::FaceBook' => 'facebook',
    12 'users::OA::Google' => 'google',
    13 'users::OA::Mailru' => 'mailru',
    14 );
    15
    7 16 sub extra_properties
    8 17 {
    9 18 return (
     
    11 20 'cases' => [
    12 21 [0, 'Блокированный'],
    13 22 [1, 'Активный'],
    14 [2, 'Платный'],
    15 [3, 'Свой/сотрудник'],
    16 [4, 'VIP'],
    17 23 [5, 'Временная активация'],
    18 24 ],
    19 25 },
     
    48 54 )
    49 55 }
    50 56
    57
    58 sub post_init {
    59 my $self = shift;
    60 my $opts = shift;
    61
    62 $self->{passwd_prev} = $self->passwd;
    63
    64 return if exists $opts->{ids} || exists $opts{names} || exists $opts{light};
    65 if ( $self->id && $state->{users}->use_credentials ) {
    66 my $creds = $keeper->get_documents(
    67 uid => $self->id,
    68 table => 'users::SQL::CredentialsTable',
    69 return_mode => 'array_ref',
    70 );
    71 if ( @$creds ) {
    72 my %creds;
    73 foreach my $cred ( @$creds ) {
    74 $cred->{keeper} = undef;
    75 my $main_field = $CREDENTIAL_FIELDS{$cred->class} if exists $CREDENTIAL_FIELDS{$cred->class};
    76 if ( $main_field ) {
    77 my $multi_field = $main_field.'s';
    78 $self->{$multi_field} = [] unless exists $self->{$multi_field};
    79 push @{$self->{$multi_field}}, $cred;
    80 $self->{$main_field} = $cred if $cred->main;
    81 }
    82 }
    83 }
    84 }
    85 return;
    86 }
    87
    88
    51 89 sub name_full
    52 90 {
    53 91 my $self = shift;
     
    112 150 }
    113 151 }
    114 152
    153
    154 sub confirm_credential {
    155 my ($self, %opts) = @_;
    156 my $object;
    157 if ( exists $opts{confirm} && $opts{name} && $opts{class} ) {
    158 ($object) = $self->keeper->get_documents(
    159 class => $opts{class},
    160 uid => $self->id,
    161 name => lc($opts{name}),
    162 limit => 1,
    163 );
    164 if ( ref $object && $object->confirm eq $opts{confirm} ) {
    165 $object->status(1);
    166 $object->store;
    167 }
    168 } elsif ( $opts{name} && $opts{class} ) {
    169 ($object) = $self->keeper->get_documents(
    170 class => $opts{class},
    171 uid => $self->id,
    172 name => lc($opts{name}),
    173 limit => 1,
    174 );
    175 if ( ref $object ) {
    176 $object->status(1);
    177 $object->store;
    178 }
    179 }
    180 return $object;
    181 }
    182
    183
    184 sub create_credential {
    185 my ($self, %opts) = @_;
    186 my $object;
    187 if ( $opts{vkontakte} ) {
    188 ($object) = $self->keeper->get_documents(
    189 class => users::OA::VK,
    190 uid => $self->id,
    191 ext_id => $opts{vkontakte},
    192 limit => 1,
    193 );
    194 unless ( ref $object ) {
    195 $object = users::OA::VK->new ($keeper);
    196 $object->name( $opts{name} );
    197 $object->status( 1 );
    198 $object->opaque( $opts{opaque} || 0 );
    199 $object->uid( $self->id );
    200 $object->ava_url( $opts{avatar} );
    201 $object->store;
    202 }
    203 } elsif ( $opts{facebook} ) {
    204 ($object) = $self->keeper->get_documents(
    205 class => users::OA::FaceBook,
    206 uid => $self->id,
    207 ext_id => $opts{facebook},
    208 limit => 1,
    209 );
    210 unless ( ref $object ) {
    211 $object = users::OA::FaceBook->new ($keeper);
    212 $object->name( $opts{name} );
    213 $object->status( 1 );
    214 $object->opaque( $opts{opaque} || 0 );
    215 $object->uid( $self->id );
    216 $object->ava_url( $opts{avatar} );
    217 $object->store;
    218 }
    219 } elsif ( $opts{google} ) {
    220 ($object) = $self->keeper->get_documents(
    221 class => users::OA::Google,
    222 uid => $self->id,
    223 ext_id => $opts{google},
    224 limit => 1,
    225 );
    226 unless ( ref $object ) {
    227 $object = users::OA::Google->new ($keeper);
    228 $object->name( $opts{name} );
    229 if ( $opts{email} ) {
    230 $object->email( $opts{email} );
    231 $self->create_credential( email => $opts{email}, status => 1 );
    232 }
    233 $object->status( 1 );
    234 $object->opaque( $opts{opaque} || 0 );
    235 $object->uid( $self->id );
    236 $object->ava_url( $opts{avatar} );
    237 $object->store;
    238 }
    239 } elsif ( $opts{mailru} ) {
    240 ($object) = $self->keeper->get_documents(
    241 class => users::OA::Mailru,
    242 uid => $self->id,
    243 ext_id => $opts{mailru},
    244 limit => 1,
    245 );
    246 unless ( ref $object ) {
    247 $object = users::OA::Mailru->new ($keeper);
    248 $object->name( $opts{name} );
    249 if ( $opts{email} ) {
    250 $object->email( $opts{email} );
    251 $self->create_credential( email => $opts{email}, status => 1 );
    252 }
    253 $object->status( 1 );
    254 $object->opaque( $opts{opaque} || 0 );
    255 $object->uid( $self->id );
    256 $object->ava_url( $opts{avatar} );
    257 $object->store;
    258 }
    259 } elsif ( $opts{email} ) {
    260 ($object) = $self->keeper->get_documents(
    261 class => users::Email,
    262 uid => $self->id,
    263 name => lc($opts{email}),
    264 limit => 1,
    265 );
    266 unless ( ref $object ) {
    267 $object = users::Email->new ($keeper);
    268 $object->name( lc($opts{email}) );
    269 $object->name_orig( $opts{email} );
    270 $object->main( $opts{main} || 0 );
    271 $object->status( $opts{status} || 0 );
    272 $object->opaque( $opts{opaque} || 0 );
    273 $object->uid( $self->id );
    274 $object->confirm( Digest::MD5::md5_hex(int(rand(1000000)), $self->id, $opts{email}) );
    275 $object->store;
    276 }
    277 } elsif ( $opts{phone} ) {
    278 ($object) = $self->keeper->get_documents(
    279 class => users::Phone,
    280 uid => $self->id,
    281 name => $keeper->{users}->_phone_reduction( $opts{phone} ),
    282 limit => 1,
    283 );
    284 unless ( ref $object ) {
    285 $object = users::Phone->new ($keeper);
    286 $object->name( $keeper->{users}->_phone_reduction($opts{phone}) );
    287 $object->name_format( $keeper->{users}->_phone_format($opts{phone}) );
    288 $object->name_orig( $opts{phone} );
    289 $object->main( $opts{main} || 0 );
    290 $object->status( $opts{status} || 0 );
    291 $object->opaque( $opts{opaque} || 0 );
    292 $object->uid( $self->id );
    293 $object->confirm( Digest::MD5::md5_hex(int(rand(1000000)), $self->id, $opts{email}) );
    294 $object->store;
    295 }
    296 }
    297 return $object;
    298 }
    299
    300
    115 301 sub pre_store
    116 302 {
    117 303 my $self = shift;
     
    119 305 my $up = $self->{keeper}->get_document_by_id ( $self->id,
    120 306 class => $self->class,
    121 307 );
    122 if ( (ref $up && $self->passwd && $self->passwd ne $up->passwd) || (!ref $up && $self->passwd) ) {
    308 my $passwd_prev = $self->{passwd_prev} || '';
    309 if ( $self->passwd && $self->passwd ne $passwd_prev ) {
    123 310 warn "Pass = ".$self->passwd."\n" if $DEBUG;
    124 311 my $pass = Digest::MD5::md5_hex($self->passwd);
    125 312 warn "Pass_hex = $pass\n" if $DEBUG;
    126 313 $self->passwd($pass);
    127 } elsif ( ref $up && (!$self->passwd || $self->passwd eq $up->passwd ) ) {
    128 $self->passwd($up->passwd);
    314 } else {
    315 $self->passwd($passwd_prev);
    129 316 }
    130 $self->email(lc($self->email));
    131 $self->login(lc($self->login));
    317 $self->login( lc($self->login) );
    132 318
    319 if ( $state->{users}->use_credentials ) {
    320 foreach my $prop ( $self->structure ) {
    321 my $name = $prop->{attr};
    322 if ( ref $self->$name =~ /^users::OA::/ ) {
    323 my $obj = $self->$name;
    324 $self->$name( $obj->ext_id );
    325 } elsif ( ref $self->$name =~ /^users::/ ) {
    326 my $obj = $self->$name;
    327 $self->$name( $obj->name );
    328 }
    329 }
    330 } else {
    331 $self->email( $keeper->{users}->_email_reduction($self->email) );
    332 }
    333
    133 334 my $default_section = $project->s_alias->{users} if ref $project->s_alias eq 'HASH' && exists $project->s_alias->{users};
    134 335 if ( $default_section ) {
    135 336 my $sections = $self->{sections};

Небольшая справка по веткам

cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.

koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.

utf8 – актуальная ветка, заточенная под UTF-8.

Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.