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 – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.