Revision 379

Date:
2013/08/21 12:49:37
Author:
ahitrov
Revision Log:
Emails control for credentials
Files:

Legend:

 
Added
 
Removed
 
Modified
  • utf8/plugins/users/comps/contenido/ajax/credential_email_valid.html

     
    1 <% $json %>
    2 <%once>
    3
    4 use JSON::XS;
    5
    6 </%once>
    7 <%args>
    8
    9 $id => undef
    10 $email => undef
    11
    12 </%args>
    13 <%init>
    14
    15 my %result;
    16 if ( $email ) {
    17 if ( $keeper->{users}->_email_format( $email ) ) {
    18 my $email_r = $keeper->{users}->_email_reduction( $email );
    19 if ( $id && $id =~ /^\d+$/) {
    20 my $object = $keeper->{users}->get_profile( id => $id );
    21 if ( ref $object ) {
    22 my ($cred) = $keeper->get_documents(
    23 name => $email_r,
    24 class => 'users::Email',
    25 limit => 1,
    26 );
    27 if ( ref $cred && $cred->uid != $object->id ) {
    28 $result{error} = 'E-mail already registered for another user';
    29 }
    30 } else {
    31 $result{error} = 'User not found';
    32 }
    33 } else {
    34 $result{error} = 'User ID is not valid or not defined';
    35 }
    36 } else {
    37 $result{error} = 'E-mail is not valid';
    38 }
    39 } else {
    40 $result{nothing} = 1;
    41 }
    42 $result{ok} = 1 unless exists $result{error} || exists $result{nothing};
    43
    44 my $json = encode_json \%result;
    45
    46 </%init>
  • utf8/plugins/users/comps/contenido/components/inputs/emails.msn

     
    1 % if ( $state->{users}->use_credentials && $object->id ) {
    2 <script type="text/javascript">
    3 <!--
    4 function check_<% $name %>_valid( nID ){
    5 }
    6
    7 $(document).ready(function(){
    8
    9 % foreach my $cred ( @credentials ) {
    10 $('#<% $name %>_name_<% $cred->id %>_text').focusout(function(){
    11 var oEmail = $(this);
    12 $.get('/contenido/ajax/credential_email_valid.html', { 'id' : '<% $object->id %>', 'email' : $(oEmail).val() }, function(data){
    13 if ( data.error ) {
    14 $('#<% $name %>_<% $cred->id %>_check').attr('title', data.error).html('<span style="color:red">Error</span>');
    15 } else {
    16 $('#<% $name %>_<% $cred->id %>_check').attr('title', '').html('<span style="color:green">Ok</span>');
    17 }
    18 }, 'json');
    19 });
    20 % }
    21
    22 $('#<% $name %>_name__text').focusout(function(){
    23 var oEmail = $(this);
    24 $.get('/contenido/ajax/credential_email_valid.html', { 'id' : '<% $object->id %>', 'email' : $(oEmail).val() }, function(data){
    25 if ( data.error ) {
    26 $('#<% $name %>_new_check').attr('title', data.error).html('<span style="color:red">Error</span>');
    27 } else if ( data.nothing ) {
    28 $('#<% $name %>_new_check').attr('title', '').html('');
    29 } else {
    30 $('#<% $name %>_new_check').attr('title', '').html('<span style="color:green">Ok</span>');
    31 }
    32 }, 'json');
    33 });
    34
    35 });
    36 //-->
    37 </script>
    38 <div style="border:1px solid gray; padding:2px; width:95%;">
    39 <table width="100%" cellpadding="5" cellspacing="0">
    40 <tr bgcolor="white">
    41 <th>Main</th>
    42 <th>E-mail</th>
    43 <th>Активен</th>
    44 <th>Удалить</th>
    45 <th></th>
    46 </tr>
    47 % foreach my $cred ( @credentials ) {
    48 % my $checked = $cred->main ? ' checked' : '';
    49 % my $bgcolor = $i++ % 2 ? 'white' : '#e0e0e0';
    50 % my $active = $cred->status == 1 ? ' checked' : '';
    51 <tr bgcolor="<% $bgcolor %>">
    52 <td width="1%"><input type="radio" name="<% $name %>.main" value="<% $cred->id %>"<% $checked %>></td>
    53 <td width="96%"><& /contenido/components/inputs/string.msn, name => $name.'_name_'.$cred->id, prop => $prop, check => $cred->name, object => $object &></td>
    54 <td width="1%"><input type="checkbox" name="<% $name %>_active_<% $cred->id %>" value="1"<% $active %>></td>
    55 <td width="1%"><input type="checkbox" name="<% $name %>.delete" value="<% $cred->id %>"></td>
    56 <td width="1%" id="<% $name %>_<% $cred->id %>_check"><span style="color:green">Ok</span></td>
    57 </tr>
    58 % }
    59 <tr bgcolor="<% $i++ % 2 ? 'white' : '#e0e0e0' %>">
    60 <td><input type="radio" name="<% $name %>.main" value=""></td>
    61 <td><& /contenido/components/inputs/string.msn, name => $name.'_name_', prop => $prop, check => '', object => $object &></td>
    62 <td><input type="checkbox" name="<% $name %>_active_" value="1"></td>
    63 <td></td>
    64 <td id="<% $name %>_new_check"></td>
    65 </tr>
    66 </table>
    67 </div>
    68 % } else {
    69 <& /contenido/components/inputs/string.msn, %ARGS &>
    70 % }
    71 <%args>
    72
    73 $name => undef
    74 $check => undef
    75 $prop => {}
    76 $object => undef
    77
    78 </%args>
    79 <%init>
    80
    81 my @credentials;
    82 if ( $state->{users}->use_credentials ) {
    83 @credentials = $keeper->get_documents(
    84 class => 'users::Email',
    85 uid => $object->id,
    86 order_by => 'main desc, name',
    87 );
    88 }
    89 my $i = 0;
    90
    91 </%init>
  • utf8/plugins/users/comps/contenido/components/outputs/emails.msn

     
    1 <%args>
    2
    3 $object
    4 $name => undef
    5 $SETS => undef
    6
    7 </%args>
    8 <%init>
    9
    10 return undef unless ref $SETS;
    11 return undef unless $name;
    12
    13 my @props = $object->structure();
    14 my ($prop) = grep { $_->{attr} eq $name } @props;
    15 return undef unless ref $prop;
    16
    17 if ( $state->{users}->use_credentials && $object->id ) {
    18 my %struct;
    19 while ( my ($key, $val) = each %$SETS ) {
    20 my $template = $name.'_name_';
    21 if ( $key =~ /^$template/ ) {
    22 my $id = $key =~ /(\d+)/ ? $1 : 'new';
    23 if ( $keeper->{users}->_email_format( $val ) ) {
    24 $struct{$id}{orig} = $val;
    25 $struct{$id}{name} = $keeper->{users}->_email_reduction($val);
    26 $struct{$id}{id} = $id;
    27 }
    28 }
    29 $template = $name.'_active_';
    30 if ( $key =~ /^$template/ ) {
    31 my $id = $key =~ /(\d+)/ ? $1 : 'new';
    32 if ( $val ) {
    33 $struct{$id}{status} = 1;
    34 $struct{$id}{id} = $id;
    35 }
    36 }
    37 }
    38 if ( exists $SETS->{$name.'.delete'} ) {
    39 if ( ref $SETS->{$name.'.delete'} eq 'ARRAY' ) {
    40 map { $struct{$_}{delete} = 1 } @{$SETS->{$name.'.delete'}};
    41 } elsif ( $SETS->{$name.'.delete'} ) {
    42 $struct{$SETS->{$name.'.delete'}}{delete} = 1;
    43 }
    44 }
    45 if ( exists $SETS->{$name.'.main'} && $SETS->{$name.'.main'} && exists $struct{$SETS->{$name.'.main'}} && !exists $struct{$SETS->{$name.'.main'}}{delete} ) {
    46 $struct{$SETS->{$name.'.main'}}{main} = 1;
    47 } elsif ( exists $struct{new} ) {
    48 $struct{new}{main} = 1;
    49 } else {
    50 my @main = grep { exists $_->{name} && exists $_->{main} && $_->{main} && !exists $_->{delete} } values %struct;
    51 unless ( @main ) {
    52 my @valid = grep { exists $_->{name} && !exists $_->{delete} } values %struct;
    53 if ( @valid ) {
    54 $valid[0]->{main} = 1;
    55 }
    56 }
    57 }
    58 my @delete_ids = map { $_->{id} } grep { $_->{id} && exists $_->{delete} } values %struct;
    59 if ( @delete_ids ) {
    60 my $sql = $keeper->SQL->prepare('delete from profile_credentials where class = ? and uid = ? and id in ('.join(',', map {'?'} @delete_ids).')');
    61 $sql->execute( 'users::Email', $object->id, @delete_ids );
    62 $sql->finish;
    63 }
    64 my @credentials = $keeper->get_documents(
    65 class => 'users::Email',
    66 uid => $object->id,
    67 order_by => 'main desc, name',
    68 );
    69 foreach my $cred ( @credentials ) {
    70 my $check = exists $struct{$cred->id} ? $struct{$cred->id} : undef;
    71 my $store = 0;
    72 if ( ref $check && exists $check->{name} && ($cred->name ne $check->{name} || $cred->name_orig ne $check->{orig}) ) {
    73 my $exists_foreign = $keeper->get_documents( class => 'users::Email', name => $check->{name}, uid_not => $object->id, count => 1 );
    74 unless ( $exists_foreign ) {
    75 $cred->name( $check->{name} );
    76 $cred->name_orig( $check->{orig} );
    77 $store = 1;
    78 }
    79 }
    80 if ( ref $check && int($check->{main}) != int($cred->main) ) {
    81 $cred->main( int($check->{main}) );
    82 $store = 1;
    83 }
    84 if ( ref $check && int($check->{status}) != int($cred->status) ) {
    85 $cred->status( int($check->{status}) );
    86 $store = 1;
    87 }
    88 if ( $store ) {
    89 $cred->store;
    90 }
    91 }
    92 if ( exists $struct{new} && exists $struct{new}{name} ) {
    93 my @found = grep { $_->name eq $struct{new}{name} } @credentials;
    94 unless ( @found ) {
    95 my $check = $struct{new};
    96 my $exists_foreign = $keeper->get_documents( class => 'users::Email', name => $check->{name}, count => 1 );
    97 unless ( $exists_foreign ) {
    98 my $cred = $object->create_credential( email => $check->{orig}, main => $check->{main}, status => ($check->{status} || 0) );
    99 push @credentials, $cred if ref $cred;
    100 }
    101 }
    102 }
    103 my ($main) = grep { $_->main } @credentials;
    104 $object->{$name.'s'} = \@credentials;
    105 return $main;
    106 } else {
    107 return $keeper->{users}->_email_format( $SETS->{$name} );
    108 }
    109
    110 </%init>
  • utf8/plugins/users/lib/users/SQL/CredentialsTable.pm

     
    27 27 _excludes_filter
    28 28 _link_filter
    29 29 _uid_filter
    30 _uid_not_filter
    30 31 _ext_id_filter
    31 32 _main_filter
    32 33 );
     
    126 127 return &SQL::Common::_generic_int_filter('d.uid', $opts{uid});
    127 128 }
    128 129
    130 sub _uid_not_filter {
    131 my ($self,%opts)=@_;
    132 return undef unless ( exists $opts{uid_not} );
    133 return &SQL::Common::_generic_int_filter('d.uid', $opts{uid_not}, 1);
    134 }
    135
    129 136 sub _main_filter {
    130 137 my ($self,%opts)=@_;
    131 138 return undef unless ( exists $opts{main} );
  • utf8/plugins/users/lib/users/SQL/UserProfile.pm

     
    151 151 },
    152 152 { # E-mail...
    153 153 'attr' => 'email',
    154 'type' => 'string',
    154 'type' => 'emails',
    155 155 'rusname' => 'E-mail (primary)',
    156 156 'hidden' => $state->{users}->use_credentials ? 1 : undef,
    157 157 'readonly' => $state->{users}->use_credentials ? 1 : undef,
  • utf8/plugins/users/lib/users/UserProfile.pm

     
    192 192
    193 193 sub confirm_credential {
    194 194 my ($self, %opts) = @_;
    195 return undef unless $self->id;
    195 196 my $object;
    196 197 if ( exists $opts{confirm} && $opts{name} && $opts{class} ) {
    197 198 ($object) = $self->keeper->get_documents(
     
    216 217 $object->store;
    217 218 }
    218 219 }
    220 if ( ref $object && ($object->class eq 'users::Phone' || $object->class eq 'users::Email') && $object->main && $self->status == 5 ) {
    221 $self->status(1);
    222 $self->store;
    223 }
    219 224 return $object;
    220 225 }
    221 226
     
    422 427 }
    423 428
    424 429
    430 sub post_store
    431 {
    432 my $self = shift;
    433
    434 if ( $state->{users}->use_credentials && $self->email ) {
    435 $self->create_credential( email => $self->email, main => 1, $self->status == 1 ? (status => 1) : () );
    436 }
    437
    438 1;
    439 }
    440
    441
    425 442 sub post_delete
    426 443 {
    427 444 my $self = shift;
  • utf8/plugins/users/sql/TOAST/credentials.sql

     
    14 14 confirm varchar(32),
    15 15 data text
    16 16 );
    17 create index profile_credentials_user_class_name on profile_credentials (class, uid, name);
    18 create index profile_credentials_user_class_ext_id on profile_credentials (class, uid, ext_id);
    17 create index profile_credentials_user_class_ext_id on profile_credentials (class, uid, ext_id) where ext_id != 0;
    18 create index profile_credentials_user_class_name on profile_credentials (class, uid, name) where ext_id = 0;
    19 19 create unique index profile_credentials_class_ext_id on profile_credentials (class, ext_id) where ext_id != 0;
    20 20 create unique index profile_credentials_class_name on profile_credentials (class, name) where ext_id = 0;

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

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

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

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

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