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