2013-10-27 01:06:58 +02:00
< ? php
class ApplicationController extends Rails\ActionController\Base
{
public function __call ( $method , $params )
{
if ( preg_match ( " /^( \ w+)_only $ / " , $method , $m )) {
if ( current_user () -> { 'is_' . $m [ 1 ] . '_or_higher' }()) {
return true ;
} else {
$this -> access_denied ();
return false ;
}
}
# For many actions, GET invokes the HTML UI, and a POST actually invokes
# the action, so we often want to require higher access for POST (so the UI
# can invoke the login dialog).
elseif ( preg_match ( " /^post_( \ w+)_only $ / " , $method , $m )) {
if ( ! $this -> request () -> isPost ())
return true ;
elseif ( current_user () -> { 'is_' . $m [ 1 ] . '_or_higher' }())
return true ;
else {
$this -> access_denied ();
return false ;
}
}
return parent :: __call ( $method , $params );
}
/**
* This is found in SessionHelper in Moebooru
*/
public function page_number ()
{
if ( ! isset ( $this -> page_number ))
$this -> page_number = $this -> params () -> page ? : 1 ;
return $this -> page_number ;
}
# LoginSystem {
protected function access_denied ()
{
$previous_url = $this -> params () -> url || $this -> request () -> fullPath ();
$this -> respondTo ([
'html' => function () use ( $previous_url ) {
$this -> notice ( 'Access denied' );
$this -> redirectTo ( " user#login " , array ( 'url' => $previous_url ));
},
'xml' => function () {
$this -> render ( array ( 'xml' => array ( 'success' => false , 'reason' => " access denied " ), 'root' => " response " , 'status' => 403 ));
},
'json' => function () {
$this -> render ( array ( 'json' => array ( 'success' => false , 'reason' => " access denied " ), 'status' => 403 ));
}
]);
}
public function user_can_see_posts ()
{
if ( ! current_user () -> can_see_posts ()) {
$this -> access_denied ();
}
}
protected function set_current_user ()
{
$user = null ;
$AnonymousUser = array (
'id' => 0 ,
'level' => 0 ,
'name' => " Anonymous " ,
'show_samples' => true ,
'language' => '' ,
'secondary_languages' => '' ,
'pool_browse_mode' => 1 ,
'always_resize_images' => true ,
'ip_addr' => $this -> request () -> remoteIp ()
);
if ( ! current_user () && $this -> session () -> user_id ) {
$user = User :: where ([ 'id' => $this -> session () -> user_id ]) -> first ();
} else {
if ( $this -> cookies () -> login && $this -> cookies () -> pass_hash ) {
$user = User :: authenticate_hash ( $this -> cookies () -> login , $this -> cookies () -> pass_hash );
} elseif ( isset ( $this -> params () -> login ) && isset ( $this -> params () -> password_hash )) {
$user = User :: authenticate ( $this -> params () -> login , $this -> params () -> password_hash );
} elseif ( isset ( $this -> params () -> user [ 'name' ]) && isset ( $this -> params () -> user [ 'password' ])) {
$user = User :: authenticate ( $this -> params () -> user [ 'name' ], $this -> params () -> user [ 'password' ]);
}
$user && $user -> updateAttribute ( 'last_logged_in_at' , date ( 'Y-m-d H:i:s' ));
}
if ( $user ) {
if ( $user -> is_blocked () && $user -> ban && $user -> ban -> expires_at < date ( 'Y-m-d H:i:s' )) {
$user -> updateAttribute ( 'level' , CONFIG () -> starting_level );
Ban :: destroyAll ( " user_id = " . $user -> id );
}
$this -> session () -> user_id = $user -> id ;
} else {
$user = new User ();
$user -> assignAttributes ( $AnonymousUser , [ 'without_protection' => true ]);
}
User :: set_current_user ( $user );
$this -> current_user = $user ;
# For convenient access in activerecord models
$user -> ip_addr = $this -> request () -> remoteIp ();
Moebooru\Versioning\Versioning :: init_history ();
if ( ! current_user () -> is_anonymous ())
current_user () -> log ( $this -> request () -> remoteIp ());
}
# iTODO:
protected function set_country ()
{
current_user () -> country = '--' ;
// current_user()->country = Rails::cache()->fetch(['type' => 'geoip', 'ip' => $this->request()->remote_ip()], ['expires_in' => '+1 month']) do
// begin
// GeoIP->new(Rails.root.join('db', 'GeoIP.dat').to_s).country($this->request()->remote_ip()).country_code2
// rescue
// '--'
// end
// end
}
# } RespondToHelpers {
protected function respond_to_success ( $notice , $redirect_to_params , array $options = array ())
{
$extra_api_params = isset ( $options [ 'api' ]) ? $options [ 'api' ] : array ();
$this -> respondTo ( array (
'html' => function () use ( $notice , $redirect_to_params ) {
$this -> notice ( $notice );
$this -> redirectTo ( $redirect_to_params );
},
'json' => function () use ( $extra_api_params ) {
$this -> render ( array ( 'json' => array_merge ( $extra_api_params , array ( 'success' => true ))));
},
'xml' => function () use ( $extra_api_params ) {
$this -> render ( array ( 'xml' => array_merge ( $extra_api_params , array ( 'success' => true )), 'root' => " response " ));
}
));
}
protected function respond_to_error ( $obj , $redirect_to_params , $options = array ())
{
! is_array ( $redirect_to_params ) && $redirect_to_params = array ( $redirect_to_params );
$extra_api_params = isset ( $options [ 'api' ]) ? $options [ 'api' ] : array ();
$status = isset ( $options [ 'status' ]) ? $options [ 'status' ] : 500 ;
if ( $obj instanceof Rails\ActiveRecord\Base ) {
$obj = $obj -> errors () -> fullMessages ( " , " );
$status = 420 ;
}
if ( $status == 420 )
$status = " 420 Invalid Record " ;
elseif ( $status == 421 )
$status = " 421 User Throttled " ;
elseif ( $status == 422 )
$status = " 422 Locked " ;
elseif ( $status == 423 )
$status = " 423 Already Exists " ;
elseif ( $status == 424 )
$status = " 424 Invalid Parameters " ;
$this -> respondTo ( array (
'html' => function () use ( $obj , $redirect_to_params ) {
$this -> notice ( " Error: " . $obj );
$this -> redirectTo ( $redirect_to_params );
},
'json' => function () use ( $obj , $extra_api_params , $status ) {
$this -> render ( array ( 'json' => array_merge ( $extra_api_params , array ( 'success' => false , 'reason' => $obj )), 'status' => $status ));
},
'xml' => function () use ( $obj , $extra_api_params , $status ) {
$this -> render ( array ( 'xml' => array_merge ( $extra_api_params , array ( 'success' => false , 'reason' => $obj )), 'root' => " response " , 'status' => $status ));
}
));
}
protected function respond_to_list ( $inst_var_name , array $formats = array ())
{
$inst_var = $this -> $inst_var_name ;
$this -> respondTo ( array (
'html' ,
isset ( $formats [ 'atom' ]) ? 'atom' : null ,
'json' => function () use ( $inst_var ) {
$this -> render ( array ( 'json' => $inst_var -> toJson ()));
},
'xml' => function () use ( $inst_var , $inst_var_name ) {
$this -> render ( array ( 'xml' => $inst_var , 'root' => $inst_var_name ));
}
));
}
protected function _render_error ( $record )
{
$this -> record = $record ;
$this -> render ([ 'inline' => '<?= $this->record->errors()->fullMessages("<br />") ?>' , 'layout' => " bare " , 'status' => 500 ]);
}
# }
// protected :build_cache_key
// protected :get_cache_key
public function get_ip_ban ()
{
$ban = IpBans :: where ( " ip_addr = ? " , $this -> request () -> remoteIp ()) -> first ();
return $ban ? : null ;
}
protected function check_ip_ban ()
{
if ( $this -> request () -> controller () == " banned " and $this -> request () -> action () == " index " ) {
return ;
}
$ban = $this -> get_ip_ban ();
if ( ! $ban ) {
return ;
}
if ( $ban -> expires_at && $ban -> expires_at < date ( 'Y-m-d H:i:s' )) {
IpBans :: destroyAll ( " ip_addr = ' { $this -> request () -> remoteIp () } ' " );
return ;
}
$this -> redirectTo ( 'banned#index' );
}
protected function save_tags_to_cookie ()
{
if ( $this -> params () -> tags || ( is_array ( $this -> params () -> post ) && isset ( $this -> params () -> post [ 'tags' ]))) {
$post_tags = isset ( $this -> params () -> post [ 'tags' ]) ? ( string ) $this -> params () -> post [ 'tags' ] : '' ;
$tags = TagAlias :: to_aliased ( explode ( ' ' , ( strtolower ( $this -> params () -> tags ? : $post_tags ))));
if ( $recent_tags = trim ( $this -> cookies () -> recent_tags ))
$tags = array_merge ( $tags , explode ( ' ' , $recent_tags ));
$this -> cookies () -> recent_tags = implode ( " " , array_slice ( $tags , 0 , 20 ));
}
}
public function set_cache_headers ()
{
$this -> response () -> headers () -> add ( " Cache-Control " , " max-age=300 " );
}
# iTODO:
public function cache_action ()
{
// if ($this->request()->method() == 'get' && !preg_match('/Googlebot/', $this->request()->env()) && $this->params()->format != "xml" && $this->params()->format != "json") {
// list($key, $expiry) = $this->get_cache_key($this->controller_name(), $this->action_name(), $this->params(), 'user' => current_user());
// if ($key && count($key) < 200) {
// $cached = Rails::cache()->read($key);
// if ($cached) {
// $this->render(['text' => $cached, 'layout' => false]);
// return;
// }
// }
// $this->yield();
// if ($key && strpos($this->response->headers['Status'], '200') === 0) {
// Rails::cache()->write($key, $this->response->body, ['expires_in' => $expiry]);
// }
// } else {
// $this->yield();
// }
}
protected function init_cookies ()
{
2013-12-31 16:20:27 +01:00
if ( $this -> request () -> format () == " xml " || $this -> request () -> format () == " json " ) {
2013-10-27 01:06:58 +02:00
return ;
2013-12-31 16:20:27 +01:00
}
2013-10-27 01:06:58 +02:00
$forum_posts = ForumPost :: where ( " parent_id IS NULL " ) -> order ( " updated_at DESC " ) -> limit ( 10 ) -> take ();
$this -> cookies () -> current_forum_posts = json_encode ( array_map ( function ( $fp ) {
if ( current_user () -> is_anonymous ()) {
$updated = false ;
} else {
$updated = $fp -> updated_at > current_user () -> last_forum_topic_read_at ;
}
return [ $fp -> title , $fp -> id , $updated , ceil ( $fp -> response_count / 30.0 )];
}, $forum_posts -> members ()));
$this -> cookies () -> country = current_user () -> country ;
if ( ! current_user () -> is_anonymous ()) {
$this -> cookies () -> user_id = ( string ) current_user () -> id ;
$this -> cookies () -> user_info = current_user () -> user_info_cookie ();
$this -> cookies () -> has_mail = ( current_user () -> has_mail ? " 1 " : " 0 " );
$this -> cookies () -> forum_updated = ( current_user () -> is_privileged_or_higher () && ForumPost :: updated ( current_user ()) ? " 1 " : " 0 " );
$this -> cookies () -> comments_updated = ( current_user () -> is_privileged_or_higher () && Comment :: updated ( current_user ()) ? " 1 " : " 0 " );
if ( current_user () -> is_janitor_or_higher ()) {
$mod_pending = Post :: where ( " status = 'flagged' OR status = 'pending' " ) -> count ();
$this -> cookies () -> mod_pending = ( string ) $mod_pending ;
}
if ( current_user () -> is_blocked ()) {
if ( current_user () -> ban )
$this -> cookies () -> block_reason = " You have been blocked. Reason: " . current_user () -> ban -> reason . " . Expires: " . substr ( current_user () -> ban -> expires_at , 0 , 10 );
else
$this -> cookies () -> block_reason = " You have been blocked. " ;
} else
$this -> cookies () -> block_reason = " " ;
$this -> cookies () -> resize_image = ( current_user () -> always_resize_images ? " 1 " : " 0 " );
$this -> cookies () -> show_advanced_editing = ( current_user () -> show_advanced_editing ? " 1 " : " 0 " );
$this -> cookies () -> my_tags = current_user () -> my_tags ;
$this -> cookies () -> blacklisted_tags = json_encode ( current_user () -> blacklisted_tags_array ());
$this -> cookies () -> held_post_count = ( string ) current_user () -> held_post_count ();
} else {
$this -> cookies () -> delete ( 'user_info' );
$this -> cookies () -> delete ( 'login' );
$this -> cookies () -> blacklisted_tags = json_encode ( CONFIG () -> default_blacklists );
}
2013-12-31 16:20:27 +01:00
if ( $this -> session () -> notice ) {
$this -> cookies () -> notice = $this -> session () -> notice ;
$this -> session () -> delete ( 'notice' );
}
2013-10-27 01:06:58 +02:00
}
protected function set_title ( $title = null )
{
if ( ! $title )
$title = CONFIG () -> app_name ;
else
$title .= ' | ' . CONFIG () -> app_name ;
$this -> page_title = $title ;
}
protected function notice ( $str )
{
2013-12-31 16:20:27 +01:00
$this -> session () -> notice = $str ;
2013-10-27 01:06:58 +02:00
}
protected function set_locale ()
{
if ( $this -> params () -> locale and in_array ( $this -> params () -> locale , CONFIG () -> available_locales )) {
$this -> cookies () -> locale = [ 'value' => $this -> params () -> locale , 'expires' => '+1 year' ];
$this -> I18n () -> setLocale ( $this -> params () -> locale );
} elseif ( $this -> cookies () -> locale and in_array ( $this -> cookies () -> locale , CONFIG () -> available_locales )) {
$this -> I18n () -> setLocale ( $this -> cookies () -> locale );
} else
$this -> I18n () -> setLocale ( CONFIG () -> default_locale );
}
protected function sanitize_params ()
{
if ( $this -> params () -> page ) {
if ( $this -> params () -> page < 1 )
$this -> params () -> page = 1 ;
} else
$this -> params () -> page = 1 ;
}
protected function admin_only ()
{
if ( ! current_user () -> is_admin ())
$this -> access_denied ();
}
protected function member_only ()
{
if ( ! current_user () -> is_member_or_higher ())
$this -> access_denied ();
}
protected function post_privileged_only ()
{
if ( ! current_user () -> is_privileged_or_higher ())
$this -> access_denied ();
}
protected function post_member_only ()
{
if ( ! current_user () -> is_member_or_higher ())
$this -> access_denied ();
}
protected function no_anonymous ()
{
if ( current_user () -> is_anonymous ())
$this -> access_denied ();
}
protected function sanitize_id ()
{
$this -> params () -> id = ( int ) $this -> params () -> id ;
}
# iTODO:
protected function filters ()
{
return [
'before' => [
'set_current_user' ,
'set_country' ,
'set_locale' ,
'set_title' ,
'sanitize_params' ,
'check_ip_ban'
],
'after' => [
'init_cookies'
]
];
}
}