суббота, 9 марта 2013 г.

Правильный способ установить Sun Java 6 и/или Oracle Java 7

1. git clone https://github.com/flexiondotorg/oab-java6

2.
если нужна Sun Java 6:
sudo  ./oab-java.sh 
sudo apt-get install sun-java6-jre

если нужна Sun Java 7:
sudo  ./oab-java.sh -7
sudo apt-get install oracle-java7-jre

3. ???
4. Profit

воскресенье, 24 февраля 2013 г.

django + celery

1. Подключаем celery и kombu
2. Пишем обработчики для задач
3. Запускаем celeryd:
    >>> python ./manage.py celeryd -v 2 -B -s celery -E -l INFO
4. Стартуем задачи


Каркас

######## settings.py ########

INSTALLED_APPS += [
    'kombu.transport.django',
    'djcelery',
]

BROKER_URL = "django://"

import djcelery
djcelery.setup_loader()


######## tasks.py ########

from celery.task import task

@task
def your_task(*args, **kwargs):
    from time import sleep
    sleep(10)


######## view.py ########

from django.http import HttpResponseRedirect

from django.core.urlresolvers import reverse

from tasks import your_task


@staff_member_required
def start_task(request):
    your_task.apply_async(kwargs={
        'some_data': 'some_value'
    })
    return HttpResponseRedirect(reverse('index'))


Установка собственного статуса для задачи

from celery import current_task

current_task.update_state(
    state='PROGRESS',
        meta={
            'message': 'Выполняюсь'
        }
)


Сваливание логов в качестве статуса задачи

from logging import getLogger, Handler

class StateUpdaterHandler(Handler):
    def __init__(self, *args, **kwrags):
        super(StateUpdaterHandler, self).__init__(*args, **kwrags)

    def emit(self, record):
        if not current_task:
            return

        current_task.update_state(
            state='PROGRESS',
            meta={
                'message': record.getMessage()
            }
        )

@task
def your_task(**kwargs):
    logger = getLogger('loader')
    logger.addHandler(StateUpdaterHandler())
    logger.info('Работаю')


Задача-синглетон 


def single_instance_task(timeout):
    def task_exc(func):
        def wrapper(*args, **kwargs):
            lock_id = "celery-single-task-" + func.__name__

            acquire_lock = lambda: cache.add(lock_id, "true", timeout)
            release_lock = lambda: cache.delete(lock_id)

            result = None

            if acquire_lock():
                try:
                    result = func(*args, **kwargs)
                finally:
                    release_lock()

            return result

        return wrapper

    return task_exc

@task
@single_instance_task(60 * 10)
def your_task(**kwargs):
    pass

вторник, 29 мая 2012 г.

Авторизация во Flask с помощью Login

Для расширенных возможностей авторизации, во Flask, существует расширение Flask-Login (документация, исходники с примером).

В общих чертах

Расширение Flask-Login предназначено для упрощения управления сессиями пользователей и решает типичные задачи, такие как вход/выход, запоминание сессий на определённый срок.
Что делает это расширение:
  1. Хранит ID залогинившихся пользователей внутри сессии и позволяет достаточно просто управлять их входом/выходом.
  2. Позволяет управлять доступом пользователей к представлениям в зависимости от того, залогинились они или нет.
  3. Реализует функцию "запомнить меня".
Что она не делает, а оставляет на нашей совести:
  1. Не навязывает использование конкретных способов хранения данных о пользователях.
  2. Не ограничивает в выборе способа авторизации и ничего не мешает использовать логин/пароль, OpenID или любой другой способ.
  3. Не берет на себя разграничением прав в зависимости от залогинности пользователя.
  4. Не выполняет регистрацию пользователей и восстановление пароля.

Начало использования

Первое что нужно сделать, для начала работы с расширением, это создать в любом месте программы, экземпляр класса LoginManager:
login_manager = LoginManager()
Класс LoginManager содержит код, который позволяет организовать нюансы работы приложения совместно с этим расширением. Например: как загружать данные пользователя по его ID, куда отправлять пользователей когда они пытаются войти или выйти и т.д.
Когда приложение полностью сконфигурировано, необходимо передать его в LoginManager:
login_manager.setup_app(app)

Как строится работа

На каждого пользователя заводится определённая структура (далее User), в которой кроме прочих, нужных Вам данных о пользователе, должен быть уникальный ID и данные по которым можно авторизовать пользователя (например логин/пароль).
И Flask-Login со своей стороны будет требовать от Вас, во-первых, найти объект User по соответствующему ID, а во-вторых, найти и вернуть объект User по переданным при авторизации данным.
Первое необходимо чтобы найти объект User уже авторизованного пользователя, при его последующих запросах исходя из ID который хранится в его сессии.
Для этого необходимо назначить callback-функцию с помощью декоратора user_loader которая используется расширением для загрузки объекта User по его ID:
@login_manager.user_loader
def load_user(userid):
    return User.get(userid)
Входной параметр один - строка unicode содержащая ID пользователя. Функция должна возвращать None, если ID не существует. В противном случае, если все в порядке и пользователь с там ID существует, нужно вернуть соответствующий ему объект User.
Второй случай происходит на этапе авторизации пользователя, когда Вы имеете некоторые данные (из формы авторизации к примеру) и по ним должны определить, корректны ли они и существует ли пользователь им соответствующий. И в этом случае, для того чтобы Flask-Login поместил нужный ID в сессию пользователя, Вы должны передать ему через функцию login_user объект User. Так же, через в эту функцию можно передать параметр remember со значением True, для реализации функционала «запомнить меня» - чтобы сессия пользователя была восстановлена при следующем входе, без авторизации.
Следующих пример демонстрирует вариант авторизации через логин/пароль. Поиск объекта User осуществляется в функции get_user(login, password).
@app.route("/login", methods=["GET", "POST"])
def login():
  if request.method == "POST":
    login = request.form["login"]
    password = request.form["password"]
    remember_me = request.form["remember"]
    # ищем пользователя по логину и паролю
    # get_user - внутренняя функция, для запроса к БД, например     
    user = get_user(login, password)
    if user:
      # если пользователь с тамим логином и паролем существует -       
      # авторизуем и делаем редирект
      login_user(user, remember=remember_me)
      return redirect(url_for("index"))
  return render_template("login.html")

Ограничение доступа к представлениям

Для ограничения доступа, чтобы к представлению могли обращаться только авторизованные пользователи, используется декоратор login_required. При попытке перейти на URL представления с таким декоратором, неавторизованный пользователь будет отправлен на страницу авторизации.

Завершение сеанса

Для того чтобы завершить сеанс пользователя, существует функция logout_user, обратная по смыслу login_user. После её вызова куки из сессии пользователя будут удалены и он будет считаться неавторизованным. Вот пример использования:
@app.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(somewhere)

Итог

Таким образом подытожим основные действия которые нужно выполнить для добавления в своё приложение функции авторизации:
  1. Определить механизм хранения и создать набор пользователей, каждый из которых будет иметь уникальный ID.
  2. Написать функцию с декоратором user_loader которая будет ставить в соответствие ID конкретный объект пользователя.
  3. Установить декоратор login_required для представлений которые требуют авторизации.
  4. Для авторизации добавить представление, которое будет вызывать функцию login_user с объектом пользователя если данные для авторизации будут верны.
  5. Добавить представление, для реализации выхода пользователя, которое будет вызывать функцию logout_user.