Revision 272
Date:
2013/02/04 17:43:10
Author:
ahitrov
Revision Log:
- New session::Session object that resolves many logon-logoff problems
and simplifies and unifies session support in applications
- Open Graph Auth in Facebook and VK applets now works through
session::Session
Files:
Legend:
Added
Removed
Modified
utf8/plugins/session/comps/www/oauth/facebook.html
27
27
my $auth_url = $fb_connect->authorize_url( state => $state );
28
28
if ( $code ) {
29
29
my $local_session = $fb_connect->authenticate( code => $code, state => $state );
30
if ( ref $local_session && exists $local_session->{id} ) {
31
my $profile = $keeper->{users}->get_profile( id => $local_session->{id} ) if exists $keeper->{users};
30
if ( ref $local_session eq 'session::Session' && $local_session->id ) {
31
my $profile = $keeper->{users}->get_profile( id => $local_session->id ) if exists $keeper->{users};
32
32
if ( ref $profile ) {
33
33
unless ( exists $local_session->{avatar} ) {
34
34
my $avatar = $profile->get_image('avatar');
35
35
$session->{avatar} = ref $avatar && exists $avatar->{filename} ? $avatar->{mini}{'54x54'}{filename} : undef;
36
$keeper->{session}->store_value (
36
$local_session->set (
37
37
name => $profile->name_full,
38
38
last_name => $profile->name_family,
39
39
first_name => $profile->name_part,
40
40
avatar => $session->{avatar},
41
41
);
42
42
} else {
43
$keeper->{session}->store_value (
43
$local_session->set (
44
44
name => $profile->name_full,
45
45
last_name => $profile->name_family,
46
46
first_name => $profile->name_part,
utf8/plugins/session/comps/www/oauth/logoff.html
6
6
<%init>
7
7
8
8
my $referer = $back eq 'referer' ? $r->header_in("Referer") : $back;
9
$keeper->{session}->logoff;
9
$keeper->{session}->get_session->logoff;
10
10
$m->redirect($referer);
11
11
12
12
</%init>
utf8/plugins/session/comps/www/oauth/vkontakte.html
21
21
use session::AUTH::VKontakte;
22
22
my $site = $state->development ? 'www' : 'www';
23
23
my $vk_connect = session::AUTH::VKontakte->new(
24
vk_redirect_uri => 'http://'.$site.'/auth/vkontakte.html',
24
vk_redirect_uri => 'http://'.$site.'/oauth/vkontakte.html',
25
25
);
26
26
27
27
…
…
45
45
my $auth_url = $vk_connect->authorize_url;
46
46
if ( $code ) {
47
47
my $local_session = $vk_connect->authenticate( code => $code );
48
if ( ref $local_session && exists $local_session->{id} ) {
49
my $profile = $keeper->{users}->get_profile( id => $local_session->{id} ) if exists $keeper->{users};
48
if ( ref $local_session eq 'session::Session' && $local_session->id ) {
49
my $profile = $keeper->{users}->get_profile( id => $local_session->id ) if exists $keeper->{users};
50
50
if ( ref $profile ) {
51
51
unless ( exists $local_session->{avatar} ) {
52
52
my $avatar = $profile->get_image('avatar');
53
53
$session->{avatar} = ref $avatar && exists $avatar->{filename} ? $avatar->{mini}{'54x54'}{filename} : undef;
54
$keeper->{session}->store_value (
54
$local_session->set (
55
55
name => $profile->name_full,
56
56
last_name => $profile->name_family,
57
57
first_name => $profile->name_part,
58
58
avatar => $session->{avatar},
59
59
);
60
60
} else {
61
$keeper->{session}->store_value (
61
$local_session->set (
62
62
name => $profile->name_full,
63
63
last_name => $profile->name_family,
64
64
first_name => $profile->name_part,
utf8/plugins/session/lib/session/AUTH/FaceBook.pm
111
111
warn "No access token in response: ".$res->content;
112
112
return undef;
113
113
}
114
$keeper->{session}->store_value( facebook_access_token => $access_token );
115
$local_session->{facebook_access_token} = $access_token;
114
$local_session->set( facebook_access_token => $access_token );
116
115
if( my $expires = $res{expires} ) {
117
$local_session->{facebook_expires} = time + $expires;
118
$keeper->{session}->store_value( facebook_expires => $local_session->{facebook_expires} );
116
$local_session->set( facebook_expires => time + $expires );
119
117
} else {
120
#$c->user_session->{'expires'} = time + 3600*24;
118
#$local_session->set( facebook_expires => time + 3600*24 );
121
119
}
122
120
warn "FB: requested access token" if $DEBUG;
123
121
} else {
…
…
141
139
warn "Userhash = ".Dumper($info) if $DEBUG;
142
140
#warn "facebook: user=$info->{name} / $info->{id} / $info->{gender}";
143
141
144
$keeper->{session}->delete_key( 'facebook_redirect_url' );
145
delete $local_session->{facebook_redirect_url};
142
$local_session->delete( 'facebook_redirect_url' );
146
143
147
144
my @plugins = split (/[\ |\t]+/, $state->{plugins});
148
145
my $name = Encode::encode('utf-8', $info->{name});
…
…
186
183
ltime => time,
187
184
avatar => 'https://graph.facebook.com/'.$info->{username}.'/picture',
188
185
);
189
$keeper->{session}->store_value ( %data );
190
while ( my ( $key, $value ) = each %data ) {
191
$local_session->{$key} = $value;
192
}
186
$local_session->set( %data );
193
187
} else {
194
188
my %data = (
195
189
id => $info->{id},
…
…
201
195
ltime => time,
202
196
avatar => 'https://graph.facebook.com/'.$info->{username}.'/picture?type=large',
203
197
);
204
$keeper->{session}->store_value ( %data );
205
while ( my ( $key, $value ) = each %data ) {
206
$local_session->{$key} = $value;
207
}
198
$local_session->set ( %data );
208
199
}
209
200
return $local_session;
210
201
}
utf8/plugins/session/lib/session/AUTH/VKontakte.pm
62
62
for ( keys %args ) {
63
63
$go->query_param( $_ => $args{$_} );
64
64
}
65
$keeper->{session}->store_value( vk_redirect_url => $self->{vk_redirect_uri} );
65
my $local_session = $session || $keeper->{session}->get_session;
66
$local_session->set( vk_redirect_url => $self->{vk_redirect_uri} );
66
67
return $go;
67
68
}
68
69
…
…
106
107
warn "No access token in response: ".$res->content."\n";
107
108
return undef;
108
109
}
109
$keeper->{session}->store_value( vk_access_token => $access_token );
110
$local_session->{vk_access_token} = $access_token;
111
$keeper->{session}->store_value( vk_user_id => $info->{user_id} );
112
$local_session->{vk_user_id} = $info->{user_id};
110
$local_session->set( vk_access_token => $access_token );
111
$local_session->set( vk_user_id => $info->{user_id} );
113
112
if ( my $expires = $info->{expires_in} ) {
114
$local_session->{vk_expires} = time + $expires;
115
$keeper->{session}->store_value( vk_expires => $local_session->{vk_expires} );
113
$local_session->set( vk_expires => time + $expires );
116
114
} else {
117
#$c->user_session->{'expires'} = time + 3600*24;
115
#$local_session->set( vk_expires => time + 3600*24 );
118
116
}
119
warn "VK: requested access token";
117
warn "VK: requested access token" if $DEBUG;
120
118
} else {
121
warn "VK: have access token";
119
warn "VK: have access token" if $DEBUG;
122
120
}
123
121
124
122
my $req = URI->new( $self->{vk_user_info_url} );
…
…
193
191
if ( $user_info->{photo} ) {
194
192
$data{avatar} = $user_info->{photo};
195
193
}
196
$keeper->{session}->store_value ( %data );
197
while ( my ( $key, $value ) = each %data ) {
198
$local_session->{$key} = $value;
199
}
194
$local_session->set( %data );
200
195
201
196
} else {
202
197
my %data = (
…
…
212
207
if ( $user_info->{photo} ) {
213
208
$data{avatar} = $user_info->{photo};
214
209
}
215
$keeper->{session}->store_value ( %data );
216
while ( my ( $key, $value ) = each %data ) {
217
$local_session->{$key} = $value;
218
}
210
$local_session->set( %data );
219
211
}
220
212
return $local_session;
221
213
}
utf8/plugins/session/lib/session/Init.pm
5
5
6
6
use session::Apache;
7
7
use session::Keeper;
8
use session::Session;
8
9
use session::AUTH::FaceBook;
9
10
use session::AUTH::VKontakte;
10
11
use session::AUTH::Mailru;
utf8/plugins/session/lib/session/Keeper.pm
190
190
}
191
191
untie %$session;
192
192
193
return \%ret;
193
my $session_object = session::Session->new( %ret );
194
return $session_object;
194
195
}
195
196
196
197
…
…
306
307
307
308
}
308
309
310
sub _get_hash_from_profile {
311
my $profile = shift;
312
return unless ref $profile;
313
314
my %data = (
315
id => $profile->id,
316
name => $profile->name,
317
email => $profile->email,
318
login => $profile->login,
319
status => $profile->status,
320
ltime => time,
321
);
322
my ($type_prop) = grep { $_->{attr} eq 'type' } $profile->structure;
323
$data{type} = $profile->type if $type_prop;
324
my ($ava_prop) = grep { $_->{attr} eq 'avatar' } $profile->structure;
325
if ( $ava_prop ) {
326
my $avatar = $profile->get_image('avatar');
327
$data{avatar} = $avatar->{mini}{filename} if ref $avatar && exists $avatar->{filename};
328
}
329
330
return %data;
331
}
332
309
333
1;
utf8/plugins/session/lib/session/Session.pm
1
package session::Session;
2
3
use strict;
4
use warnings 'all';
5
use Contenido::Globals;
6
use session::Keeper;
7
8
sub new {
9
my ($proto, %params) = @_;
10
my $class = ref($proto) || $proto;
11
my $self = {};
12
bless $self, $class;
13
if ( exists $params{_session_id} ) {
14
$self->{_session_id} = delete $params{_session_id};
15
$self->{_timestamp} = delete $params{_timestamp};
16
}
17
$self->{_domain} = delete $params{domain} || $state->{session}->domain;
18
while ( my ($key, $val) = each %params ) {
19
$self->{$key} = $val;
20
}
21
22
return $self;
23
}
24
25
sub session_id {
26
my $self = shift;
27
return $self->{_session_id};
28
}
29
30
sub _session_id {
31
my $self = shift;
32
return $self->{_session_id};
33
}
34
35
sub rehash {
36
my ($self, $session) = @_;
37
return $self if $self->{_session_id} eq $session->{_session_id};
38
39
warn "STORE_VALUE: New or deprecated session. Old sid = [".$self->{_session_id}."], new sid = [".$session->{_session_id}."]" if $DEBUG;
40
session::Keeper::_store_session_id ($session->{_session_id}, domain => $self->{_domain});
41
42
foreach my $key ( keys %$self ) {
43
next if $key eq '_domain';
44
delete $self->{$key};
45
}
46
while ( my ($key, $val) = each %$session ) {
47
$self->{$key} = $val;
48
}
49
return $self;
50
}
51
52
sub id {
53
my $self = shift;
54
return (exists $self->{id} && $self->{id} ? $self->{id} : undef);
55
}
56
57
sub get {
58
my ($self, $name) = @_;
59
return ($name && exists $self->{$name} ? $self->{$name} : undef);
60
}
61
62
sub set {
63
my ($self, %opts) = @_;
64
my $sid = $self->{_session_id};
65
my $session = session::Keeper::_get_session_object( $sid );
66
return unless ref $session;
67
68
$self->rehash( $session );
69
while ( my ($key, $val) = each %opts ) {
70
$session->{$key} = $val;
71
$self->{$key} = $val;
72
}
73
74
untie %$session;
75
1;
76
}
77
78
sub delete {
79
my ($self, @keys) = @_;
80
81
my $sid = $self->{_session_id};
82
my $session = session::Keeper::_get_session_object( $sid );
83
return unless ref $session;
84
85
$self->rehash( $session );
86
87
foreach my $key ( @keys ) {
88
if ( exists $self->{$key} ) {
89
delete $session->{$key};
90
delete $self->{$key};
91
}
92
}
93
94
untie %$session;
95
1;
96
}
97
98
sub logon {
99
my $self = shift;
100
my %opts = @_;
101
102
my $profile = delete $opts{profile};
103
return unless ref $profile || (($opts{login} || $opts{email}) && $opts{passwd});
104
105
if ( ref $profile ) {
106
my %data = session::Keeper::_get_hash_from_profile( $profile );
107
$self->set ( %data );
108
} else {
109
my @plugins = split (/[\ |\t]+/, $state->{plugins});
110
if ( grep { $_ eq 'users' } @plugins ) {
111
#### Авторизация через плагин users
112
#########################################
113
$profile = $keeper->{users}->login (
114
$opts{login} ? (login => $opts{login}) : (),
115
$opts{email} ? (email => lc($opts{email})) : (),
116
passwd => $opts{passwd},
117
);
118
} else {
119
#### Авторизация иным способом
120
}
121
if ( ref $profile ) {
122
my %data = session::Keeper::_get_hash_from_profile( $profile );
123
$self->set ( %data );
124
} else {
125
$self->set( login_error_code => 404 );
126
}
127
}
128
return $self;
129
}
130
131
sub logoff {
132
my ($self, %opts) = @_;
133
134
my $sid = $self->{_session_id};
135
my $session = session::Keeper::_get_session_object( $sid );
136
return unless ref $session;
137
138
$self->rehash( $session );
139
140
if ( exists $opts{clear} ) {
141
my @clear = qw( id email login name nick type status ltime type avatar );
142
push @clear, @{ $opts{clear} } if ref $opts{clear} eq 'ARRAY' && @{ $opts{clear} };
143
foreach my $key ( @clear ) {
144
delete $session->{$key};
145
delete $self->{$key}
146
}
147
} else {
148
foreach my $key ( keys %$session ) {
149
next if $key =~ /^_/;
150
151
delete $session->{$key};
152
delete $self->{$key}
153
}
154
}
155
156
untie %$session;
157
1;
158
}
159
160
161
1;
Небольшая справка по веткам
cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.
koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.
utf8 – актуальная ветка, заточенная под UTF-8.
Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.