Padre::Sync - Utility functions for handling remote Configuration Syncing


Padre documentation Contained in the Padre distribution.

Index


Code Index:

NAME

Top

Padre::Sync - Utility functions for handling remote Configuration Syncing

DESCRIPTION

Top

The Padre::Sync class contains logic for communicating with a remote Madre::Sync server. This class interacts with the Padre::Wx::Dialog::Sync class for user interface display.

METHODS

Top

new

The constructor returns a new Padre::Sync object, but you should normally access it via the main Padre object:

  my $manager = Padre->ide->config_sync;

First argument should be a Padre object.

main

A convenience method to get to the main window.

config

A convenience method to get to the config object

ua

A convenience method to get to the useragent object

register

Attempts to register a user account with the information provided on the Sync server. Parameters: a list of key value pairs to be interpreted as POST parameters Returns error string if user state is already logged in or serverside error occurs.

login

Will log in to remote Sync server using given credentials. State will be updated if login successful.

logout

If currently logged in, will log the Sync session out from the server. State will be updated.

server_delete

Given a logged in session, will attempt to delete the config currently stored on the Sync server (if one currently exists). Will fail if not logged in.

local_to_server

Given a logged in session, will attempt to place the current local config to the Sync server.

server_to_local

Given a logged in session, will replace the local config with what is stored on the server. TODO: is validation of config before replacement required?

english_status

Will return a string explaining current state of Sync dependent on $self->{state}

SEE ALSO

Top

Padre, Padre::Config

COPYRIGHT & LICENSE

Top


Padre documentation Contained in the Padre distribution.
package Padre::Sync;

use 5.008;
use strict;
use warnings;
use Carp           ();
use File::Spec     ();
use Scalar::Util   ();
use Params::Util   ();
use JSON::XS       ();
use LWP::UserAgent ();
use HTTP::Cookies  ();
use HTTP::Request::Common qw/GET POST DELETE/;
use Padre::Util     ();
use Padre::Current  ();
use Padre::Constant ();

our $VERSION = '0.86';





#####################################################################
# Constructor and Accessors

sub new {
	my $class = shift;
	my $ide = Params::Util::_INSTANCE( shift, 'Padre' );
	unless ($ide) {
		Carp::croak("Creation of a Padre::Sync without a Padre not possible");
	}

	# Create the useragent.
	# We need this to handle login actions.
	# Save cookies for state management from Padre session to session
	# is this even wanted? remove at padre close?
	my $ua = LWP::UserAgent->new;
	push @{ $ua->requests_redirectable }, 'POST';
	$ua->timeout(2);
	$ua->cookie_jar(
		HTTP::Cookies->new(
			file => File::Spec->catfile(
				Padre::Constant::CONFIG_DIR,
				'lwp_cookies.dat',
			),
			autosave => 1,
		)
	);

	my $self = bless {
		ide   => $ide,
		state => 'not_logged_in',
		ua    => $ua,
		json  => JSON::XS->new,
		@_,
	}, $class;

	return $self;
}

sub main {
	$_[0]->{ide}->wx->main;
}

sub config {
	$_[0]->{ide}->config;
}

sub ua {
	$_[0]->{ua};
}

sub register {
	my $self   = shift;
	my $params = shift;
	my $server = $self->config->config_sync_server;

	return 'Registration Failure'      unless %$params;
	return 'Failure: no server found.' unless $server;

	if ( $self->{state} ne 'not_logged_in' ) {
		return 'Failure: cannot register account, user already logged in.';
	}

	# this crashes if server is unavailable. FIXME
	my $resp = $self->ua->request(
		POST "$server/register",
		'Content-Type' => 'application/json',
		'Content'      => $self->{json}->encode($params),
	);
	if ( $resp->code == 200 ) {
		return 'Account registered successfully. Please log in.';
	}

	my $h = $self->{json}->decode( $resp->content );

	return "Registration Failure: $h->{error}" if $h->{error};
	return "Registration failure.";
}

sub login {
	my $self   = shift;
	my $params = [@_];
	my $server = $self->config->config_sync_server;

	return 'Failure: no server found.' unless $server;

	if ( $self->{state} ne 'not_logged_in' ) {
		return 'Failure: cannot log in, user already logged in.';
	}

	my $resp = $self->ua->request( POST "$server/login", $params );

	if ( $resp->content !~ /Wrong username or password/i and $resp->code == 200 ) {
		$self->{state} = 'logged_in';
		return 'Logged in successfully.';
	}

	return 'Login Failure.';
}

sub logout {
	my $self   = shift;
	my $server = $self->config->config_sync_server;

	return 'Failure: no server found.' if not $server;

	if ( $self->{state} ne 'logged_in' ) {
		return 'Failure: cannot logout, user not logged in.';
	}

	my $resp = $self->ua->request( GET "$server/logout" );

	if ( $resp->code == 200 ) {
		$self->{state} = 'not_logged_in';
		return 'Logged out successfully.';
	}

	return 'Failed to log out.';
}

sub server_delete {
	my $self   = shift;
	my $server = $self->config->config_sync_server;

	return 'Failure: no server found.' if not $server;

	if ( $self->{state} ne 'logged_in' ) {
		return 'Failure: user not logged in.';
	}

	my $resp = $self->ua->request( DELETE "$server/user/config" );

	if ( $resp->code == 200 ) {
		return 'Configuration deleted successfully.';
	}

	return 'Failed to delete serverside configuration file.';

}

sub local_to_server {
	my $self   = shift;
	my $server = $self->config->config_sync_server;

	return 'Failure: no server found.' if not $server;

	if ( $self->{state} ne 'logged_in' ) {
		return 'Failure: user not logged in.';
	}

	my $conf = $self->config->human;

	# theres gotta be a better way to do this
	my %h;
	for my $k ( keys %$conf ) {
		$h{$k} = $conf->{$k};
	}

	my $resp = $self->ua->request(
		POST "$server/user/config",
		'Content-Type' => 'application/json',
		'Content'      => $self->{json}->encode( \%h ),
	);
	if ( $resp->code == 200 ) {
		return 'Configuration uploaded successfully.';
	}

	return 'Failed to upload configuration file to server.';
}

sub server_to_local {
	my $self   = shift;
	my $config = $self->config;
	my $server = $config->config_sync_server;

	return 'Failure: no server found.' if not $server;

	if ( $self->{state} ne 'logged_in' ) {
		return 'Failure: user not logged in.';
	}

	my $resp = $self->ua->request( GET "$server/user/config", 'Accept' => 'application/json' );

	my $c;
	eval { $c = $self->{json}->decode( $resp->content ); };
	if ($@) {
		return 'Failed to deserialize serverside configuration.';
	}

	# apply each setting to the global config. should only be HUMAN settings
	delete $c->{Version};
	delete $c->{version};
	for my $key ( keys %$c ) {
		$config->apply( $key, $c->{$key} );
	}
	$config->apply( main_singleinstance => 1 );
	$config->write;

	if ( $resp->code == 200 ) {
		return 'Configuration downloaded and applied successfully.';
	}

	return 'Failed to download serverside configuration file to local Padre instance.';
}

sub english_status {
	my $self = shift;
	return 'User is not currently logged into the system.' if $self->{state} eq 'not_logged_in';
	return 'User is currently logged into the system.'     if $self->{state} eq 'logged_in';
	return "State unknown: $self->{state}";
}

1;

# Copyright 2008-2011 The Padre development team as listed in Padre.pm.
# LICENSE
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl 5 itself.