Tuesday, July 14, 2015

Simple blog using Laravel - Part I

Migrations

Create articles migration:
$ php artisan make:migration create_articles_table --create="articles"
Inside database/migrations find created migration and edit:
2015_07_13_192755_create_articles_table.php
and add these lines to up() method:
Schema::create('articles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title');
    $table->text('body');
    $table->text('excerpt')->nullable();
    $table->timestamp('published_at');
    $table->timestamps();
});
To execute created migration do:
$ php artisan migrate

Routes

Edit
app\Http\routes.php
and add this line:
Route::resource('articles', 'ArticlesController');
Which is easier way and equal to manually supply all CRUD routes following REST convention like so:
Route::get('articles', 'ArticlesController@index');
Route::get('articles/create', 'ArticlesController@create');
Route::get('articles/{id}', 'ArticlesController@show');
Route::post('articles', 'ArticlesController@store');
Route::get('articles/{id}/edit', 'ArticlesController@edit');

Model

We have articles table, so lets create Article model:
$ php artisan make:model Article
Edit our model app\Article.php and add $fillable fields so we can mass assign them while creating article. Also specify published_at field inside $dates so Laravel threat this field as Carbon date object instead of simple string representation.
class Article extends Model
{
    protected $dates = ['published_at'];
    protected $fillable = [
    'title',
    'body',
    'published_at'
    ];
}

Add two rows to article table using Laravel interactive tinker tool:
$ php artisan tinker;
$ App\Article::create(['title' => 'My first article', 'body' => 'Article body', 'published_at' => Carbon\Carbon::now()]);
$ App\Article::create(['title' => 'New article', 'body' => 'New body', 'published_at' => Carbon\Carbon::now()]);
$ App\Article::all();
Update first article:
$article = App\Article::find(1);
$article->body = 'Lorem ipsum';
$article->save();
App\Article::all();
Get collection of articles:
$articles = App\Article::where('body','Lorem ipsum')->get();
Get first article:
$article = App\Article::where('body','Lorem ipsum')->first();

Controller

Let's create plain ArticlesController:
$ php artisan make:controller ArticlesController --plain
So now we will create index action to fetch list of articles.
Edit app\Http\Controllers\ArticlesController.php:
public function index()
{
    $articles = Article::latest('published_at')->published()->get();
    return view('articles.index', compact('articles'));
}
We want to use published() scope while fetching articles to get only those published until today and sort them descending from newest to oldest by published_at using latest(). So let's create published() scope in app\Article.php model. Notation is keyword scope followed by scope name, like this:
use Carbon\Carbon;
public function scopePublished($query)
{
    $query->where('published_at', '<=', Carbon::now());
}
To show details of selected article we need show() action. Edit app\Http\Controllers\ArticlesController.php:
public function show($id)
{
    $article = Article::findOrFail($id);
    return view('articles.show', compact('article'));
}

View

Inside resources folder create app.blade.php:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
@yield('content')
</div>
@yield('footer')
</body>
</html>
Inside resources\articles create index.blade.php:
@extends('app')
@section('content')
<div class="col-md-12 staff-header">
<h5>Articles</h5>
</div>
<div class="col-xs-12 col-md-12">
@foreach( $articles as $article)
<article>
<h4>
<a href="{{ action('ArticlesController@show', [$article->id]) }}">{{ $article->title }}</a>
</h4>
<h6>{{ $article->body }}</h6>
<br/>
</article>
@endforeach
</div>
@stop
Inside resources\articles create show.blade.php:
@extends('app')
@section('content')
<div class="col-md-12 staff-header">
<h5>{{ $article->title }}</h5>
</div>
<div class="col-xs-12 col-md-12">
<article>
<h6>{{ $article->body }}</h6>
</article>
</div>
@stop

Tuesday, June 30, 2015

Laravel on Debian Wheezy

LAMP

First we need LAMP packages installed.
Laravel requires PHP >= 5.5.9 so we will install php56.

Add package repositories to apt sources.
Edit sources.list
$ vi /etc/apt/sources.list
and add these two lines:
deb http://packages.dotdeb.org wheezy-php56 all
deb-src http://packages.dotdeb.org wheezy-php56 all

Add dotdeb.gpg key so apt can authenticate packages from added sources.
$ cd
$ wget http://www.dotdeb.org/dotdeb.gpg
$ apt-key add dotdeb.gpg
$ apt-get update

Install Apache, MySQL and PHP
$ apt-get install mysql-server mysql-client
$ apt-get install apache2
$ apt-get install php5 libapache2-mod-php5 php5-mcrypt

Enable rewrite apache modul
$ a2enmod rewrite
$ /etc/init.d/apache2 restart

Confirm that php is working well with apache by creating info.php file:
$ vi /var/www/info.php
add this line:
<?php phpinfo(); ?>
Access inside browser: http://localhost/info.php

Laravel

# To install laravel we need composer:
$ sudo curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

* Use composer to install laravel:
$ composer global require "laravel/installer=~1.1"

* Add laravel bin to your PATH so you can use laravel executable from any location. Edit bash_profile file:
$ vi ~/.bash_profile
and add these lines:
PATH=$PATH:~/.composer/vendor/bin
export PATH

* Create new base for web application
$ cd ~/NetBeansProjects
$ laravel new LaravelDemo

# Or we could skip installing laravel and using it's executable to create base for web application (steps marked with asterisk *), and go ahead do all that with composer directly:
$ rm -rf ~/NetBeansProjects/LaravelDemo
$ cd ~/NetBeansProjects
$ composer create-project laravel/laravel LaravelDemo --prefer-dist

# Create Apache VirtualHost by:
$ vi /etc/apache2/sites-available/laraveldemo.org
and add these lines:
ServerAdmin webmaster@laraveldemo.org
ServerName  laraveldemo.org
ServerAlias *.laraveldemo.org

DocumentRoot /home/{user}/NetBeansProjects/LaravelDemo/public

        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all

ErrorLog ${APACHE_LOG_DIR}/laraveldemo_error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog ${APACHE_LOG_DIR}/laraveldemo_access.log combined

# Enable virtual host:
$ a2ensite laraveldemo.org

# Add virtual host to hosts file by editing:
$ vi /etc/hosts
add this line:
127.0.0.1 laraveldemo.org

# Restart apache
$ service apache2 restart

# Create simple /about route and appropriate controller, action and view
$ cd ~/NetBeansProjects/LaravelDemo
$ vi app/Http/routes.php 
add this line to routes.php:
Route::get('about', 'PagesController@about');

# Create PagesController by:
$ php artisan make:controller PagesController --plain
$ vi app/Http/Controllers/PagesController.php
 
add about() method to PagesController.php:
    public function about() {
    return view('about');
    }

# Create about view by editing about.blade.php:
$ vi resouces/views/about.blade.php
add this line:
    Hello World

# Make local configuration
$ copy .env.example to .env

# Generate app key
$ php artisan key:generate

# Set Directory Permissions
$ cd ~/NetBeansProjects/LaravelDemo
$ chgrp www-data -Rv storage/
$ chmod g+w -Rv storage/
$ cd bootstrap/
$ chgrp www-data -Rv cache
$ chmod g+w -Rv cache

Test it by pointing browser to:
http://laraveldemo.org/about

Create database
mysql> create database laraveldemo;
mysql> CREATE USER 'laraveldemouser'@'localhost' IDENTIFIED BY 'laraveldemopass';
mysql> GRANT ALL ON laraveldemo.* TO 'laraveldemouser'@'localhost';

# Add mysql authentication data to .env
$ vi .env
change these lines:
DB_HOST=localhost
DB_DATABASE=laraveldemo
DB_USERNAME=laraveldemouser
DB_PASSWORD=laraveldemopass

Monday, August 9, 2010

How to load/write XML using JAXB?

Every now and then you need to load or write some XML files. It is very effective way to put data in machine-readable form. XML is text format file which is well formatted using standardized rules.

So to demonstrate use of JAXB we will:
1) create XML file with some data (bookmarks.xml)
2) create XML schema file to validate our XML file (bookmarks.xsd)
3) create XML object model using xjc utility (xjc.txt)
4) load that XML file into JAXB object (XMLUnmarshall.java)
5) write JAXB object back over original XML file (XMLMarshaller.java)
6) create main java class to call these functions in appropriate order (JAXBLoader,java)

Create XML file
Lets create a simple xml file for storing bookmark data organized through sets. It will contain root element bookmarks with bookmark elements inside and list of attribute elements for storing href values. Also for every bookmark element there will be a attribute set which will identify current bookmark set. Example of this xml can be found here: bookmarks.xml.

Create XML schema file
To validate bookmark.xml we need to create schema file. Example for this example can be found here: bookmarks.xsd.

Create object model
To create object model for our xml we need to run xjc utility and supply it with xsd schema file as argument at command line.

zlaja@orion:~/NetBeansProjects/JAXBLoader> xjc ./data/bookmarks.xsd -p com.blogspot.zetaorionis.bookmarks.model -d ./src
parsing a schema...
compiling a schema...
com/blogspot/zetaorionis/bookmarks/model/AttributeType.java
com/blogspot/zetaorionis/bookmarks/model/Bookmark.java
com/blogspot/zetaorionis/bookmarks/model/Bookmarks.java
com/blogspot/zetaorionis/bookmarks/model/ObjectFactory.java
com/blogspot/zetaorionis/bookmarks/model/package-info.java
zlaja@orion:~/NetBeansProjects/JAXBLoader>

Unmarshalling / loading XML data to object model instance
This utility class will help you read xml file into it's object representation. It will work with every xml file. You just need to supply it with uri path to xml file:
data/bookmarks.xml

and root element class of object model:
Bookmarks.class

Here is XMLUnmarshaller.java utility class:

package com.blogspot.zetaorionis.util.xml;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.net.URI;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.apache.log4j.Logger;

/**
*
* @author zlaja
*/
public class XMLUnmarshaller {

private static final Logger logger = Logger.getLogger(XMLUnmarshaller.class);
/**
* The bookmark file.
*/
protected URI uri;

/**
* Create an xml based loader of bookmarks.
* @param uri the bookmark file
*/
public XMLUnmarshaller(final URI uri) {
this.uri = uri;
}

//
// BookmarksXMLLoader
//
/**
* Load bookmarks into a action list.
*
* @throws IOException
* If an I/O error occurred.
* @throws FileNotFoundException
* If the resource was not found.
*/
public T load(Class docClass) throws IOException {
final InputStream in = getClass().getResourceAsStream("/" + uri.getPath());

if (in == null) {
throw new FileNotFoundException("Cannot find resource: " + uri);
}

try {
return load(docClass, in);
} finally {
in.close();
}
}

protected T load(Class docClass, final InputStream in) {
T o = null;
try {
o = unmarshal(docClass, in);
} catch (JAXBException ex) {
logger.error("Error while unmarshalling.", ex);
}
return o;
}

public T unmarshal(Class docClass, InputStream inputStream)
throws JAXBException {
String packageName = docClass.getPackage().getName();
JAXBContext jc = JAXBContext.newInstance(packageName);
Unmarshaller u = jc.createUnmarshaller();
JAXBElement doc = u.unmarshal(new StreamSource(inputStream), docClass);
return doc.getValue();
}
}

Marshalling / writing data to xml from object model instance
This utility class will help you write data from object representation to xml file. It will work with every xml file. You just need to supply it with uri path to xml file:
data/bookmarks.xml

and root element class of object model:
Bookmarks.class

Here is XMLMarshaller.java utility class:
package com.blogspot.zetaorionis.util.xml;

import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.net.URI;
import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.log4j.Logger;

/**
*
* @author zlaja
*/
public class XMLMarshaller {

private static final Logger logger = Logger.getLogger(XMLUnmarshaller.class);
/**
* The output XML file.
*/
protected URI uri;

/**
* Create an xml based writer for specified jaxbObject.
* @param uri - uri for output XML file
*/
public XMLMarshaller(final URI uri) {
this.uri = uri;
}

//
// XMLMarshaller
//
/**
* Write JAXBElement representation of object to XML file.
*
* @param jaxbObject - object for marshalling to xml, converted to JAXBElement.
* Conversion is done using function inside ObjectFactory.java which is
* created with xjc utility
* @param docClass - class for object that is going to be marshalled to XML
*
* @throws IOException
* If an I/O error occurred.
* @throws FileNotFoundException
* If the resource was not found.
*/
public void write(final JAXBElement jaxbObject, Class docClass) throws IOException {
final OutputStream os = new FileOutputStream(uri.getPath());

if (os == null) {
throw new FileNotFoundException("Cannot create resource: " + uri);
}

try {
write(jaxbObject, docClass, os);
} finally {
os.close();
}
}

protected void write(final JAXBElement jaxbObject, Class docClass, final OutputStream os) {
try {
marshall(jaxbObject, docClass, os);
} catch (JAXBException ex) {
logger.error("Error in marshalling to XML.", ex);
}
}

private void marshall(final JAXBElement jaxbObject, Class docClass, final OutputStream os)
throws JAXBException {
String packageName = docClass.getPackage().getName();
JAXBContext context = JAXBContext.newInstance(packageName);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(jaxbObject, os);
}
}

Call utility classes inside main class
package com.blogspot.zetaorionis.jaxbloader;

import com.blogspot.zetaorionis.bookmarks.model.Bookmarks;
import com.blogspot.zetaorionis.bookmarks.model.ObjectFactory;
import com.blogspot.zetaorionis.util.xml.XMLMarshaller;
import com.blogspot.zetaorionis.util.xml.XMLUnmarshaller;
import java.net.URI;
import org.apache.log4j.Logger;

/**
*
* @author zlaja
*/
public class JAXBLoader {

private static final String LOG4J_PROPERTIES = "data/log4j.properties";
private static final Logger logger = Logger.getLogger(JAXBLoader.class);
private Bookmarks bookmarks = new Bookmarks();

public JAXBLoader() {
Log4J.init(LOG4J_PROPERTIES);
}

/**
* Loads XML data to object
*/
private void loadBookmarks() {
try {
final String path = "data/bookmarks.xml";
final URI uri = new URI(path);

final XMLUnmarshaller xmlBookmarks = new XMLUnmarshaller(uri);
this.bookmarks = xmlBookmarks.load(Bookmarks.class);
logger.info("Info: Bookmarks loaded successfuly.");
} catch (Exception ex) {
logger.error("Error: Loading bookmarks XML file failed", ex);
}
}

/**
* Writes object data to XML
*/
private void writeBookmarks() {
try {
final String path = "data/bookmarks.xml";
final URI uri = new URI(path);

final XMLMarshaller xmlBookmarks = new XMLMarshaller(uri);
ObjectFactory of = new ObjectFactory();
xmlBookmarks.write(of.createBookmarks(this.bookmarks), Bookmarks.class);
logger.info("Info: Bookmarks written successfuly.");
} catch (Exception ex) {
logger.error("Error: Writing bookmarks XML file failed", ex);
}
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
JAXBLoader loader = new JAXBLoader();
loader.loadBookmarks();
loader.writeBookmarks();
}
}

Saturday, February 20, 2010

Use yubikey for safer and less painful browsing

What is yubikey?
Yubikey is usb powered piece of hardware with one action button to generate OTP (one time passwords).

Main advantages:
- There is no need to remember credentials for different sites on the web. Just plug in the yubikey and press action button which will create random OTP password with unique header number of that particular yubikey.
- It will guarantee user inviolability and thus disable fishing attacks and credential information interception.

Main disadvantages:
- You have to carry it with you :), but you can access your web portals without using it in old fashion way by typing your credentials.

Settings things up:
You need to register your account at KeyGenius:
http://kg.yubico.com/

You can use basic or standard account type. Basic will not ask you for any password when logging and all you need is one touch on your yubikey for every login on the web. You are released of typing. Standard account is more secure. It will ask you on first access for your KeyGenius credentials, and after supplying it you can use yubikey like in basic account for every other portal on the web.

Under your account you need to supply information like username, passsword and domain for every domain and credential information.

So it's like this. You want to login on e.g. facebook.com. You will open facebook in browser. Your username will be remembered by your browser. Instead of typing passwords you plug your yubikey and touch button. Login process will continue automatically. First it will send request to KeyGenius to return real password for facebook and after receiving password browser will log you to facebook.

Browser will need to know how to get password from KeyGenius. That is accomplished with java script which can be installed to browser using GreasyMonkey addon. Script can be found here:
http://kg.yubico.com/keygenius.user.js

And thats it. Enjoy your safe browsing... :)

Database synchronization using TableSyncer

Prerequisites:
ruby
ruby-devel
ruby-mysql
rubygems
libmysqlclient
libmysqlclient-devel
libopenssl-devel
zlib-devel

Installation:
sudo gem install mysql
sudo gem install table_syncer

Settings:
cd /usr/lib64/ruby/gems/1.8/gems/table_syncer-0.3.1/lib
cp table_syncer.rb table_syncer.rb.orig
vi table_syncer.rb

Add and change these lines:
local_source_db = {:host => '127.0.0.1', :user => 'user', :password => 'password', :db => 'SourceDatabase'}
local_test_db = {:host => '127.0.0.1', :user => 'user', :password => 'password', :db => 'test'}

Executing
table_syncer --from=local_source_db --to=local_test_db --tables=account

Reference:
http://code.google.com/p/ruby-roger-useful-functions/wiki/TableSyncer
http://www.freelinuxtutorials.com/quick-tips-and-tricks/sync-mysql-tables-via-ruby-gem-tablesyncer/
http://forums.mysql.com/read.php?116,178217,198518#msg-198518

SCP & SSH

At local machine:
ssh-keygen -t rsa
cd ~/.ssh
cp id_rsa.pub authorized_keys
scp -p ~/.ssh/authorized_keys username@remoteMachine:.ssh/

Note that before executing scp you need to make sure there is ~/.ssh at remote machine also and create it if neccecery with
mkdir ~/.ssh

At remote machine:
cd
ls -ld . .ssh .ssh/authorized_keys
drwxr-xr-x 36 username username 4096 Jul 25 02:24 .
drwxr-xr-x 2 username username 512 Apr 10 02:30 .ssh
-rw-r--r-- 1 username username 1674 Apr 10 02:29 .ssh/authorized_keys

cd
chmod go-w . .ssh .ssh/authorized_keys

At local machine:
scp -p file username@remoteMachine:path/to/file

Reference:
http://kimmo.suominen.com/docs/ssh/

Mounting remote windows station

1) Using mount command:
mount -t cifs //192.168.0.4/Movies ~/Desktop/movies/

2) Using /etc/fstab file:
//192.168.0.4/Movies /media/remote/movies cifs file_mode=0777,dir_mode=0777,password=******** 0 0

Mounting iso file image:
mkdir /media/iso
mount -o loop -t iso9660 ~/file.iso /media/iso