<commit_before>"""
Module that defines all the objects required to handle polymorphic
collection read requests.

Only ES-based models that have collection view registered are handled
by this module.

Im particular:
    * PolymorphicACL: Dynamic factory class that generates ACL considering
        ACLs of all the collections requested.
    * PolymorphicESView: View that handles polymorphic collection read
        requests.
    * add_url_polymorphic: Wrapper class that is used instead of default
        `nefertari.wrappers.add_object_url`.

To use this module, simply include it in your `main()` AFTER root
resource's `auth` variable and after Pyramid ACLAuthorizationPolicy
is set up.

By default this module is included by 'nefertari.elasticsearch' when
`elasticsearch.enable_polymorphic_query` setting is True.

After inclusion, PolymorphicESView view will be registered to handle GET
requests. To access polymorphic API endpoint, compose URL with names
used to access collection GET API endpoints.

E.g. If API has endpoints '/users' and '/stories', polymorphic endpoint
would be available at '/users,stories' and '/stories,users'.

Polymorphic endpoints support all the read functionality regular ES
endpoint supports: query, search, filter, sort, aggregation, etc.
"""
from pyramid.security import DENY_ALL, Allow

from nefertari.view import BaseView
from nefertari.acl import BaseACL
from nefertari.utils import dictset
from nefertari import wrappers

def includeme(config):
    """ Connect view to route that catches all URIs like
    'something,something,...'
    """
    root = config.get_root_resource()
    root.add('nef_polymorphic', '{collections:.+,.+}',
             view=PolymorphicESView,
             factory=PolymorphicACL)

class PolymorphicHelperMixin(object):
    """ Helper mixin class that contains methods used by:
        * PolymorphicACL
        * PolymorphicESView
        * add_url_polymorphic wrapper
    """
    def get_collections(self):
        """ Get names of collections from request matchdict.

        :return: Names of collections
        :rtype: list of str
        """
        collections = self.request.matchdict['collections'].split('/')[0]
        collections = [coll.strip() for coll in collections.split(',')]
        return set(collections)

    def get_resources(self, collections):
        """ Get resources that correspond to values from :collections:.

        :param collections: Collection names for which resources should be
            gathered
        :type collections: list of str
        :return: Gathered resources
        :rtype: list of Resource instances
        """
        res_map = self.request.registry._resources_map
        resources = [res for res in res_map.values()
                     if res.collection_name in collections
                     and not res.is_singular]
        resources = [res for res in resources if res]
        return set(resources)

class PolymorphicACL(PolymorphicHelperMixin, BaseACL):
    """ ACL used by PolymorphicESView.

    Generates ACEs checking whether current request user has 'index'
    permissions in all of the requested collection views/contexts.
    """
    def __init__(self, request):
        """ Set ACL generated from collections affected. """
        super(PolymorphicACL, self).__init__(request)
        self.set_collections_acl()

    def _get_least_permissions_aces(self, resources):
        """ Get ACEs with the least permissions that fit all resources.

        To have access to polymorph on N collections, user MUST have
        access to all of them. If this is true, ACEs are returned, that
        allows 'index' permissions to current request principals.

        Otherwise None is returned thus blocking all permissions except
        those defined in `nefertari.acl.BaseACL`.

        :param resources:
        :type resources: list of Resource instances
        :return: Generated Pyramid ACEs or None
        :rtype: tuple or None
        """
        factories = [res.view._factory for res in resources]
        contexts = [factory(self.request) for factory in factories]
        for ctx in contexts:
            if not self.request.has_permission('index', ctx):
                return
        else:
            return [
                (Allow, principal, 'index')
                for principal in self.request.effective_principals
            ]

    def set_collections_acl(self):
        """ Calculate and set ACL valid for requested collections.

        DENY_ALL is added to ACL to make sure no access rules are
        inherited.
        """
        self.__acl__ = []
        collections = self.get_collections()
        resources = self.get_resources(collections)
        aces = self._get_least_permissions_aces(resources)
        if aces is not None:
            for ace in aces:
                self.acl = ace
        self.acl = DENY_ALL

class PolymorphicESView(PolymorphicHelperMixin, BaseView):
    """ Polymorphic ES collection read view.

    Has default implementation of 'index' view method that supports
    all the ES collection read actions(query, aggregation, etc.) across
    multiple collections of ES-based documents.

    To be displayed by polymorphic view, model must have collection view
    setup that serves instances of this model. Models that only have
    singular views setup are not served by polymorhic view.
    """
    def __init__(self, *args, **kwargs):
        """ Init view and set fake `self.Model` so its __name__ would
        contain names of all requested collections.
        """
        super(PolymorphicESView, self).__init__(*args, **kwargs)
        types = self.determine_types()
        self.Model = dictset({'__name__': ','.join(types)})

    def _run_init_actions(self):
        self.setup_default_wrappers()
        self.set_public_limits()

    def setup_default_wrappers(self):
        self._after_calls['index'] = [
            wrappers.wrap_in_dict(self.request),
            wrappers.add_meta(self.request),
            add_url_polymorphic(self.request),
            wrappers.add_etag(self.request),
        ]
        if self._auth_enabled:
            self._after_calls['index'] += [
                wrappers.apply_privacy(self.request),
            ]

    def determine_types(self):
        """ Determine ES type names from request data.

        In particular `request.matchdict['collections']` is used to
        determine types names. Its value is comma-separated sequence
        of collection names under which views have been registered.
        """
        from nefertari.elasticsearch import ES
        collections = self.get_collections()
        resources = self.get_resources(collections)
        models = set([res.view.Model for res in resources])
        es_models = [mdl for mdl in models if mdl
                     and getattr(mdl, '_index_enabled', False)]
        types = [ES.src2type(mdl.__name__) for mdl in es_models]
        return types

    def index(self, collections):
        """ Handle collection GET request.

        Set default limit and call :self.get_collection_es: to query ES.
        """
        self._query_params.process_int_param('_limit', 20)
        return self.get_collection_es()

class add_url_polymorphic(PolymorphicHelperMixin, wrappers.add_object_url):
    """ Wrapper that adds 'self' to each object in results

    For each object in `result['data']` adds a uri which points
    to current object
    """
    def get_models_map(self):
        """ Get map of {model_name: resource} for each collection
        requested by request.
        """
        collections = self.get_collections()
        resources = self.get_resources(collections)
        return {res.view.Model._type: res for res in resources}

    def _set_object_self(self, obj):
        """ Override to generate urls instead of just concatenating.

        'self' key is not set for singular resources.
        """
        type_, obj_id = obj['_type'], obj['id']
        resource = self.model_resources[type_]
        obj['self'] = self.request.route_url(
            resource.uid, **{resource.id_name: obj_id})

    def __call__(self, **kwargs):
        self.model_resources = self.get_models_map()
        return super(add_url_polymorphic, self).__call__(**kwargs)
<commit_msg>Update docstring<commit_after>"""
Module that defines all the objects required to handle polymorphic
collection read requests.

Only ES-based models that have collection view registered are handled
by this module.

Im particular:
    * PolymorphicACL: Dynamic factory class that generates ACL considering
        ACLs of all the collections requested.
    * PolymorphicESView: View that handles polymorphic collection read
        requests.
    * add_url_polymorphic: Wrapper class that is used instead of default
        `nefertari.wrappers.add_object_url`.

To use this module, simply include it in your `main()` AFTER root
resource's `auth` variable and after Pyramid ACLAuthorizationPolicy
is set up.

By default this module is included by 'nefertari.elasticsearch' when
`elasticsearch.enable_polymorphic_query` setting is True.

After inclusion, PolymorphicESView view will be registered to handle GET
requests. To access polymorphic API endpoint, compose URL with names
used to access collection GET API endpoints.

E.g. If API had collection endpoints '/users' and '/stories', polymorphic
endpoint would be available at '/users,stories' and '/stories,users'.

Polymorphic endpoints support all the read functionality regular ES
endpoint supports: query, search, filter, sort, aggregation, etc.
"""
from pyramid.security import DENY_ALL, Allow

from nefertari.view import BaseView
from nefertari.acl import BaseACL
from nefertari.utils import dictset
from nefertari import wrappers

def includeme(config):
    """ Connect view to route that catches all URIs like
    'something,something,...'
    """
    root = config.get_root_resource()
    root.add('nef_polymorphic', '{collections:.+,.+}',
             view=PolymorphicESView,
             factory=PolymorphicACL)

class PolymorphicHelperMixin(object):
    """ Helper mixin class that contains methods used by:
        * PolymorphicACL
        * PolymorphicESView
        * add_url_polymorphic wrapper
    """
    def get_collections(self):
        """ Get names of collections from request matchdict.

        :return: Names of collections
        :rtype: list of str
        """
        collections = self.request.matchdict['collections'].split('/')[0]
        collections = [coll.strip() for coll in collections.split(',')]
        return set(collections)

    def get_resources(self, collections):
        """ Get resources that correspond to values from :collections:.

        :param collections: Collection names for which resources should be
            gathered
        :type collections: list of str
        :return: Gathered resources
        :rtype: list of Resource instances
        """
        res_map = self.request.registry._resources_map
        resources = [res for res in res_map.values()
                     if res.collection_name in collections
                     and not res.is_singular]
        resources = [res for res in resources if res]
        return set(resources)

class PolymorphicACL(PolymorphicHelperMixin, BaseACL):
    """ ACL used by PolymorphicESView.

    Generates ACEs checking whether current request user has 'index'
    permissions in all of the requested collection views/contexts.
    """
    def __init__(self, request):
        """ Set ACL generated from collections affected. """
        super(PolymorphicACL, self).__init__(request)
        self.set_collections_acl()

    def _get_least_permissions_aces(self, resources):
        """ Get ACEs with the least permissions that fit all resources.

        To have access to polymorph on N collections, user MUST have
        access to all of them. If this is true, ACEs are returned, that
        allows 'index' permissions to current request principals.

        Otherwise None is returned thus blocking all permissions except
        those defined in `nefertari.acl.BaseACL`.

        :param resources:
        :type resources: list of Resource instances
        :return: Generated Pyramid ACEs or None
        :rtype: tuple or None
        """
        factories = [res.view._factory for res in resources]
        contexts = [factory(self.request) for factory in factories]
        for ctx in contexts:
            if not self.request.has_permission('index', ctx):
                return
        else:
            return [
                (Allow, principal, 'index')
                for principal in self.request.effective_principals
            ]

    def set_collections_acl(self):
        """ Calculate and set ACL valid for requested collections.

        DENY_ALL is added to ACL to make sure no access rules are
        inherited.
        """
        self.__acl__ = []
        collections = self.get_collections()
        resources = self.get_resources(collections)
        aces = self._get_least_permissions_aces(resources)
        if aces is not None:
            for ace in aces:
                self.acl = ace
        self.acl = DENY_ALL

class PolymorphicESView(PolymorphicHelperMixin, BaseView):
    """ Polymorphic ES collection read view.

    Has default implementation of 'index' view method that supports
    all the ES collection read actions(query, aggregation, etc.) across
    multiple collections of ES-based documents.

    To be displayed by polymorphic view, model must have collection view
    setup that serves instances of this model. Models that only have
    singular views setup are not served by polymorhic view.
    """
    def __init__(self, *args, **kwargs):
        """ Init view and set fake `self.Model` so its __name__ would
        contain names of all requested collections.
        """
        super(PolymorphicESView, self).__init__(*args, **kwargs)
        types = self.determine_types()
        self.Model = dictset({'__name__': ','.join(types)})

    def _run_init_actions(self):
        self.setup_default_wrappers()
        self.set_public_limits()

    def setup_default_wrappers(self):
        self._after_calls['index'] = [
            wrappers.wrap_in_dict(self.request),
            wrappers.add_meta(self.request),
            add_url_polymorphic(self.request),
            wrappers.add_etag(self.request),
        ]
        if self._auth_enabled:
            self._after_calls['index'] += [
                wrappers.apply_privacy(self.request),
            ]

    def determine_types(self):
        """ Determine ES type names from request data.

        In particular `request.matchdict['collections']` is used to
        determine types names. Its value is comma-separated sequence
        of collection names under which views have been registered.
        """
        from nefertari.elasticsearch import ES
        collections = self.get_collections()
        resources = self.get_resources(collections)
        models = set([res.view.Model for res in resources])
        es_models = [mdl for mdl in models if mdl
                     and getattr(mdl, '_index_enabled', False)]
        types = [ES.src2type(mdl.__name__) for mdl in es_models]
        return types

    def index(self, collections):
        """ Handle collection GET request.

        Set default limit and call :self.get_collection_es: to query ES.
        """
        self._query_params.process_int_param('_limit', 20)
        return self.get_collection_es()

class add_url_polymorphic(PolymorphicHelperMixin, wrappers.add_object_url):
    """ Wrapper that adds 'self' to each object in results

    For each object in `result['data']` adds a uri which points
    to current object
    """
    def get_models_map(self):
        """ Get map of {model_name: resource} for each collection
        requested by request.
        """
        collections = self.get_collections()
        resources = self.get_resources(collections)
        return {res.view.Model._type: res for res in resources}

    def _set_object_self(self, obj):
        """ Override to generate urls instead of just concatenating.

        'self' key is not set for singular resources.
        """
        type_, obj_id = obj['_type'], obj['id']
        resource = self.model_resources[type_]
        obj['self'] = self.request.route_url(
            resource.uid, **{resource.id_name: obj_id})

    def __call__(self, **kwargs):
        self.model_resources = self.get_models_map()
        return super(add_url_polymorphic, self).__call__(**kwargs)
<|endoftext|>


<commit_before>from flask import session, Blueprint, redirect, request
from flask.ext.login import login_user, logout_user, current_user
from werkzeug.exceptions import BadRequest

from aleph import authz
from aleph.providers import PROVIDERS, Stub
from aleph.core import db, url_for
from aleph.views.util import jsonify
from aleph.model import User

blueprint = Blueprint('sessions', __name__)

@blueprint.route('/api/1/sessions')
def status():
    oauth_providers = {}
    for name, provider in PROVIDERS.items():
        if not isinstance(provider, Stub):
            oauth_providers[name] = url_for('.login', provider=name)

    return jsonify({
        'logged_in': authz.logged_in(),
        'api_key': current_user.api_key if authz.logged_in() else None,
        'user': current_user if authz.logged_in() else None,
        'permissions': {},
        'logins': oauth_providers,
        'logout': url_for('.logout')
    })

@blueprint.route('/api/1/sessions/logout')
def logout():
    logout_user()
    return redirect(request.args.get('next_url', url_for('ui')))

@blueprint.route('/api/1/sessions/login/<provider>')
def login(provider):
    if provider not in PROVIDERS:
        raise BadRequest('Unknown provider: %s' % provider)
    if current_user.is_authenticated():
        return redirect(url_for('ui'))
    callback = url_for('.%s_authorized' % provider)
    session['next_url'] = request.args.get('next_url', url_for('ui'))
    return PROVIDERS[provider].authorize(callback=callback)

handler = PROVIDERS.get('twitter')

@blueprint.route('/api/1/sessions/callback/twitter')
@handler.authorized_handler
def twitter_authorized(resp):
    next_url = session.get('next_url', url_for('ui'))
    if resp is None or 'oauth_token' not in resp:
        return redirect(next_url)
    session['twitter_token'] = (resp['oauth_token'],
                                resp['oauth_token_secret'])
    provider = PROVIDERS.get('twitter')
    res = provider.get('users/show.json?user_id=%s' % resp.get('user_id'))
    data = {
        'display_name': res.data.get('name'),
        'twitter_id': res.data.get('id')
    }
    user = User.load(data)
    db.session.commit()
    login_user(user, remember=True)
    return redirect(next_url)

handler = PROVIDERS.get('facebook')

@blueprint.route('/api/1/sessions/callback/facebook')
@handler.authorized_handler
def facebook_authorized(resp):
    next_url = session.get('next_url', url_for('ui'))
    if resp is None or 'access_token' not in resp:
        return redirect(next_url)
    session['facebook_token'] = (resp.get('access_token'), '')
    profile = PROVIDERS.get('facebook').get('/me').data
    data = {
        'display_name': profile.get('name'),
        'email': profile.get('email'),
        'facebook_id': profile.get('id')
    }
    user = User.load(data)
    db.session.commit()
    login_user(user, remember=True)
    return redirect(next_url)
<commit_msg>Try resetting the session. <commit_after>from flask import session, Blueprint, redirect, request
from flask.ext.login import login_user, logout_user, current_user
from werkzeug.exceptions import BadRequest

from aleph import authz
from aleph.providers import PROVIDERS, Stub
from aleph.core import db, url_for
from aleph.views.util import jsonify
from aleph.model import User

blueprint = Blueprint('sessions', __name__)

@blueprint.route('/api/1/sessions')
def status():
    oauth_providers = {}
    for name, provider in PROVIDERS.items():
        if not isinstance(provider, Stub):
            oauth_providers[name] = url_for('.login', provider=name)

    return jsonify({
        'logged_in': authz.logged_in(),
        'api_key': current_user.api_key if authz.logged_in() else None,
        'user': current_user if authz.logged_in() else None,
        'permissions': {},
        'logins': oauth_providers,
        'logout': url_for('.logout')
    })

@blueprint.route('/api/1/sessions/logout')
def logout():
    logout_user()
    return redirect(request.args.get('next_url', url_for('ui')))

@blueprint.route('/api/1/sessions/login/<provider>')
def login(provider):
    if provider not in PROVIDERS:
        raise BadRequest('Unknown provider: %s' % provider)
    if current_user.is_authenticated():
        return redirect(url_for('ui'))
    session.clear()
    callback = url_for('.%s_authorized' % provider)
    session['next_url'] = request.args.get('next_url', url_for('ui'))
    return PROVIDERS[provider].authorize(callback=callback)

handler = PROVIDERS.get('twitter')

@blueprint.route('/api/1/sessions/callback/twitter')
@handler.authorized_handler
def twitter_authorized(resp):
    next_url = session.get('next_url', url_for('ui'))
    if resp is None or 'oauth_token' not in resp:
        return redirect(next_url)
    session['twitter_token'] = (resp['oauth_token'],
                                resp['oauth_token_secret'])
    provider = PROVIDERS.get('twitter')
    res = provider.get('users/show.json?user_id=%s' % resp.get('user_id'))
    data = {
        'display_name': res.data.get('name'),
        'twitter_id': res.data.get('id')
    }
    user = User.load(data)
    db.session.commit()
    login_user(user, remember=True)
    return redirect(next_url)

handler = PROVIDERS.get('facebook')

@blueprint.route('/api/1/sessions/callback/facebook')
@handler.authorized_handler
def facebook_authorized(resp):
    next_url = session.get('next_url', url_for('ui'))
    if resp is None or 'access_token' not in resp:
        return redirect(next_url)
    session['facebook_token'] = (resp.get('access_token'), '')
    profile = PROVIDERS.get('facebook').get('/me').data
    data = {
        'display_name': profile.get('name'),
        'email': profile.get('email'),
        'facebook_id': profile.get('id')
    }
    user = User.load(data)
    db.session.commit()
    login_user(user, remember=True)
    return redirect(next_url)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from optparse import make_option
import logging
import json
import datetime

from django.core.management.base import BaseCommand
from django import db
from django.conf import settings
from django.db import transaction
from django.contrib.gis.geos import MultiLineString, LineString, Point, GEOSGeometry

import django.contrib.gis
from django.contrib.gis.gdal import DataSource
from django.contrib.gis.utils import LayerMapping

from services.models import *

def espoo_coordinates_to_gk25(x, y):
    a = 6600290.731951121200000
    b = 25443205.726901203000000
    c = 0.999869662254702
    d = -0.015128383929030
    e = 0.015134113397130
    f = 0.999867560105837
    return (
        (b + (e * y) + (f * x)),
        (a + (c * y) + (d * x)))

HELSINKI_GROUPS = {
    'skiing': {
        2147483643: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483641: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483608: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483616: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483630: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483631: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483633: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483642: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483637: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483634: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483610: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483609: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483612: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483615: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483614: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483628: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483629: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        214748362: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' } # TOODO: ID faulty
    }
}

class Command(BaseCommand):
    help = "Import ski track units from GeoJSON derived from mSki"
    option_list = list(BaseCommand.option_list + (
        make_option('--helsinki-file', dest='helsinki_filename', help='input filename'),
        make_option('--vantaa-file', dest='vantaa_filename', help='input filename'),
        make_option('--espoo-file', dest='espoo_filename', help='input filename'),
    ))

    def clean_text(self, text):
        #text = text.replace('\n', ' ')
        #text = text.replace(u'\u00a0', ' ')
        # remove consecutive whitespaces
        text = re.sub(r'\s\s+', ' ', text, re.U)
        # remove nil bytes
        text = text.replace('\u0000', ' ')
        text = text.strip()
        return text

    def unit_defaults(self, name, geometry, point):
        return {
            'name_fi': name,
            'provider_type': 101,
            'origin_last_modified_time': datetime.datetime.now(),
            'organization_id': 91,
            'geometry': geometry,
            'location': point
        }

    def import_helsinki_units(self, filename):
        geojson = json.load(open(filename, 'r'))
        for feature in geojson['features']:
            properties = feature['properties']
            geometry = feature['geometry']
            point = Point(geometry['coordinates'][0][0])
            linestrings = [LineString(ls) for ls in geometry['coordinates']]
            multilinestring = MultiLineString(linestrings)
            geom_src = geometry['coordinates']
            if len(geom_src) == 1 and len(geom_src[0]) == 2:
                # There are some tracks with fake route coordinates
                # standing in for a point coord
                multilinestring = None
            defaults = self.unit_defaults(properties['NIMI'], multilinestring, point)
            unit, created = Unit.objects.get_or_create(
                pk=properties['unit_id'],
                defaults=defaults)
            unit.services.add(self.ski_service)

    def get_lowest_high_unit_id(self):
        uid = Unit.objects.aggregate(db.models.Max('id'))['id__max']
        while True:
            try:
                Unit.objects.get(pk=uid)
                uid -= 1
            except Unit.DoesNotExist as e:
                break
        return uid

    def import_vantaa_units(self, filename):
        ds = DataSource(filename)
        assert(len(ds) == 1)
        lyr = ds[0]
        srs = lyr.srs
        uid = self.get_lowest_high_unit_id()
        for feat in lyr:
            assert feat.geom_type == 'LineString'
            if type(feat.geom) == django.contrib.gis.gdal.geometries.MultiLineString:
                multilinestring = GEOSGeometry(feat.geom.wkt)
            else:
                multilinestring = MultiLineString(GEOSGeometry(feat.geom.wkt))

            defaults = self.unit_defaults(
                feat.get('nimi'),
                multilinestring,
                Point(feat.geom[0][0], feat.geom[0][1]))
            unit, created = Unit.objects.get_or_create(
                pk=uid,
                defaults=defaults)
            unit.services.add(self.ski_service)
            uid -= 1

    def import_espoo_units(self, filename):
        ds = DataSource(filename)
        assert len(ds) == 1
        uid = self.get_lowest_high_unit_id()
        lyr = ds[0]
        for feat in lyr:
            print(feat.get('NIMI'))
            if type(feat.geom) == django.contrib.gis.gdal.geometries.MultiLineString:
                multilinestring = GEOSGeometry(feat.geom.wkt)
            else:
                multilinestring = MultiLineString(GEOSGeometry(feat.geom.wkt))
            converted_multilinestring_coords = []
            for line in multilinestring:
                converted_multilinestring_coords.append(
                    LineString(tuple((espoo_coordinates_to_gk25(point[0], point[1]) for point in line))))

            converted_multilinestring = (
                MultiLineString((converted_multilinestring_coords), srid=3879))
            defaults = self.unit_defaults(
                feat.get('NIMI'),
                converted_multilinestring,
                Point(converted_multilinestring[0][0], converted_multilinestring[0][1], srid=3879))
            unit, created = Unit.objects.get_or_create(
                pk=uid,
                defaults=defaults)
            unit.services.add(self.ski_service)
            uid -= 1

    def handle(self, **options):
        self.options = options
        self.verbosity = int(options.get('verbosity', 1))
        self.logger = logging.getLogger(__name__)
        self.ski_service = Service.objects.get(pk=33483)
        if self.options.get('helsinki_filename', False):
            self.import_helsinki_units(self.options['helsinki_filename'])
        if self.options.get('vantaa_filename', False):
            self.import_vantaa_units(self.options['vantaa_filename'])
        if self.options.get('espoo_filename', False):
            self.import_espoo_units(self.options['espoo_filename'])
<commit_msg>Use ski track name as key.<commit_after># -*- coding: utf-8 -*-

from optparse import make_option
import logging
import json
from django.utils import timezone

from django.core.management.base import BaseCommand
from django import db
from django.conf import settings
from django.db import transaction
from django.contrib.gis.geos import MultiLineString, LineString, Point, GEOSGeometry

import django.contrib.gis
from django.contrib.gis.gdal import DataSource
from django.contrib.gis.utils import LayerMapping

from services.models import *

def espoo_coordinates_to_gk25(x, y):
    a = 6600290.731951121200000
    b = 25443205.726901203000000
    c = 0.999869662254702
    d = -0.015128383929030
    e = 0.015134113397130
    f = 0.999867560105837
    return (
        (b + (e * y) + (f * x)),
        (a + (c * y) + (d * x)))

HELSINKI_GROUPS = {
    'skiing': {
        2147483643: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483641: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483608: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483616: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483630: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483631: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483633: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483642: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483637: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483634: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483610: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483609: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483612: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483615: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483614: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483628: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        2147483629: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' },
        214748362: { 'maintenance_subgroup_id': 'ita', 'maintenance_subgroup_name': 'Itä' } # TOODO: ID faulty
    }
}

class Command(BaseCommand):
    help = "Import ski track units from GeoJSON derived from mSki"
    option_list = list(BaseCommand.option_list + (
        make_option('--helsinki-file', dest='helsinki_filename', help='input filename'),
        make_option('--vantaa-file', dest='vantaa_filename', help='input filename'),
        make_option('--espoo-file', dest='espoo_filename', help='input filename'),
    ))

    def clean_text(self, text):
        #text = text.replace('\n', ' ')
        #text = text.replace(u'\u00a0', ' ')
        # remove consecutive whitespaces
        text = re.sub(r'\s\s+', ' ', text, re.U)
        # remove nil bytes
        text = text.replace('\u0000', ' ')
        text = text.strip()
        return text

    def unit_defaults(self, uid, geometry, point):
        return {
            'id': uid,
            'provider_type': 101,
            'origin_last_modified_time': timezone.now(),
            'geometry': geometry,
            'location': point,
            'data_source': 'manual_import'
        }

    def import_helsinki_units(self, filename):
        geojson = json.load(open(filename, 'r'))
        uid = self.get_lowest_high_unit_id()
        for feature in geojson['features']:
            properties = feature['properties']
            geometry = feature['geometry']
            point = Point(geometry['coordinates'][0][0])
            linestrings = [LineString(ls) for ls in geometry['coordinates']]
            multilinestring = MultiLineString(linestrings)
            geom_src = geometry['coordinates']
            if len(geom_src) == 1 and len(geom_src[0]) == 2:
                # There are some tracks with fake route coordinates
                # standing in for a point coord
                multilinestring = None
            defaults = self.unit_defaults(uid, multilinestring, point)
            defaults['municipality_id'] = 'helsinki'
            defaults['organization_id'] = 91
            print('creating helsinki', uid)
            unit, created = Unit.objects.get_or_create(
                name_fi=properties['NIMI'],
                defaults=defaults)
            unit.services.add(self.ski_service)
            uid -= 1

    def get_lowest_high_unit_id(self):
        MAX_PK = 2147483647
        if not Unit.objects.filter(pk=MAX_PK).exists():
            return MAX_PK
        uid = Unit.objects.aggregate(db.models.Max('id'))['id__max']
        while True:
            try:
                Unit.objects.get(pk=uid)
                uid -= 1
            except Unit.DoesNotExist as e:
                break
        return uid

    def import_vantaa_units(self, filename):
        ds = DataSource(filename)
        assert(len(ds) == 1)
        lyr = ds[0]
        srs = lyr.srs
        uid = self.get_lowest_high_unit_id()
        for feat in lyr:
            assert feat.geom_type == 'LineString'
            if type(feat.geom) == django.contrib.gis.gdal.geometries.MultiLineString:
                multilinestring = GEOSGeometry(feat.geom.wkt)
            else:
                multilinestring = MultiLineString(GEOSGeometry(feat.geom.wkt))

            defaults = self.unit_defaults(
                uid,
                multilinestring,
                Point(feat.geom[0][0], feat.geom[0][1]))
            defaults['municipality_id'] = 'vantaa'
            defaults['organization_id'] = 92
            print('creating vantaa', uid)
            unit, created = Unit.objects.get_or_create(
                name_fi=feat.get('nimi'),
                defaults=defaults)
            unit.services.add(self.ski_service)
            uid -= 1

    def import_espoo_units(self, filename):
        ds = DataSource(filename)
        assert len(ds) == 1
        uid = self.get_lowest_high_unit_id()
        lyr = ds[0]
        for feat in lyr:
            if type(feat.geom) == django.contrib.gis.gdal.geometries.MultiLineString:
                multilinestring = GEOSGeometry(feat.geom.wkt)
            else:
                multilinestring = MultiLineString(GEOSGeometry(feat.geom.wkt))
            converted_multilinestring_coords = []
            for line in multilinestring:
                converted_multilinestring_coords.append(
                    LineString(tuple((espoo_coordinates_to_gk25(point[0], point[1]) for point in line))))

            converted_multilinestring = (
                MultiLineString((converted_multilinestring_coords), srid=3879))
            defaults = self.unit_defaults(
                uid,
                converted_multilinestring,
                Point(converted_multilinestring[0][0], converted_multilinestring[0][1], srid=3879))
            defaults['municipality_id'] = 'espoo'
            defaults['organization_id'] = 49
            print('creating espoo', uid)
            unit, created = Unit.objects.get_or_create(
                name_fi=feat.get('NIMI'),
                defaults=defaults)
            unit.services.add(self.ski_service)
            uid -= 1

    def handle(self, **options):
        self.options = options
        self.verbosity = int(options.get('verbosity', 1))
        self.logger = logging.getLogger(__name__)
        defaults = {
            'name_fi': 'Latu',
            'name_sv': 'Skidspår',
            'name_en': 'Ski track',
            'unit_count': 0,
            'last_modified_time': timezone.now()
        }
        self.ski_service, created = Service.objects.get_or_create(pk=33483, defaults=defaults)
        if self.options.get('helsinki_filename', False):
            self.import_helsinki_units(self.options['helsinki_filename'])
        if self.options.get('vantaa_filename', False):
            self.import_vantaa_units(self.options['vantaa_filename'])
        if self.options.get('espoo_filename', False):
            self.import_espoo_units(self.options['espoo_filename'])
        self.ski_service.unit_count = self.ski_service.get_unit_count()
<|endoftext|>


<commit_before>import contextlib
import subprocess

import pytest
import pytest_docker.plugin

def is_responsive(container_name: str, port: int) -> bool:
    ret = subprocess.run(
        f"docker exec {container_name} /bin/bash -c 'echo -n > /dev/tcp/localhost/{port}'",
        shell=True,
    )
    return ret.returncode == 0

def wait_for_port(
    docker_services: pytest_docker.plugin.Services,
    container_name: str,
    container_port: int,
    timeout: float = 30.0,
) -> None:
    # port = docker_services.port_for(container_name, container_port)
    docker_services.wait_until_responsive(
        timeout=timeout,
        pause=0.5,
        check=lambda: is_responsive(container_name, container_port),
    )

@pytest.fixture
def docker_compose_runner(docker_compose_project_name, docker_cleanup):
    @contextlib.contextmanager
    def run(compose_file_path: str, key: str) -> pytest_docker.plugin.Services:
        with pytest_docker.plugin.get_docker_services(
            str(compose_file_path),
            f"{docker_compose_project_name}-{key}",
            docker_cleanup,
        ) as docker_services:
            yield docker_services

    return run
<commit_msg>feat(ingest): print docker logs on timeout (#2743)<commit_after>import contextlib
import subprocess

import pytest
import pytest_docker.plugin

def is_responsive(container_name: str, port: int) -> bool:
    ret = subprocess.run(
        f"docker exec {container_name} /bin/bash -c 'echo -n > /dev/tcp/localhost/{port}'",
        shell=True,
    )
    return ret.returncode == 0

def wait_for_port(
    docker_services: pytest_docker.plugin.Services,
    container_name: str,
    container_port: int,
    timeout: float = 30.0,
) -> None:
    try:
        # port = docker_services.port_for(container_name, container_port)
        docker_services.wait_until_responsive(
            timeout=timeout,
            pause=0.5,
            check=lambda: is_responsive(container_name, container_port),
        )
    finally:
        # use check=True to raise an error if command gave bad exit code
        subprocess.run(f"docker logs {container_name}", shell=True, check=True)

@pytest.fixture
def docker_compose_runner(docker_compose_project_name, docker_cleanup):
    @contextlib.contextmanager
    def run(compose_file_path: str, key: str) -> pytest_docker.plugin.Services:
        with pytest_docker.plugin.get_docker_services(
            str(compose_file_path),
            f"{docker_compose_project_name}-{key}",
            docker_cleanup,
        ) as docker_services:
            yield docker_services

    return run
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2015-2017:
#   Matthieu Estrada, ttamalfor@gmail.com
#
# This file is part of (AlignakApp).
#
# (AlignakApp) is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# (AlignakApp) is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with (AlignakApp).  If not, see <http://www.gnu.org/licenses/>.

"""
    User manage QWidget who display User Profile.
"""

from logging import getLogger

from alignak_app.core.utils import get_image_path, get_css
from alignak_app.widgets.app_widget import AppQWidget
from alignak_app.widgets.banner import send_banner

from PyQt5.QtWidgets import QWidget, QPushButton, QCheckBox  # pylint: disable=no-name-in-module
from PyQt5.QtWidgets import QGridLayout, QVBoxLayout  # pylint: disable=no-name-in-module
from PyQt5.QtWidgets import QLabel  # pylint: disable=no-name-in-module
from PyQt5.Qt import QIcon  # pylint: disable=no-name-in-module

logger = getLogger(__name__)

class UserProfile(QWidget):
    """
        Class who create QWidget for User Profile.
    """

    def __init__(self, app_backend, parent=None):
        super(UserProfile, self).__init__(parent)
        self.setStyleSheet(get_css())
        # Fields
        self.user = None
        self.app_backend = app_backend
        self.app_widget = None

    def initialize(self):
        """
        Initialize User QWidget

        """

        # Get the user data first
        self.get_user_data()

        # Then initialize AppQWidget
        self.app_widget = AppQWidget()
        self.app_widget.initialize('User view: %s' % self.user['alias'])
        self.app_widget.add_widget(self)

        layout = QVBoxLayout()
        self.setLayout(layout)

        layout.addWidget(self.get_main_user_widget())
        layout.addWidget(self.get_info_user_widget())

        layout.addWidget(self.get_notifications_widget())

    def get_user_data(self):
        """
        Get and set the user data

        """

        projection = [
            '_realm',
            'is_admin',
            'alias',
            'name',
            'notes',
            'email',
            'can_submit_commands',
            'token',
            'host_notifications_enabled',
            'service_notifications_enabled',
            'host_notification_period',
            'service_notification_period',
            'host_notification_options',
            'service_notification_options',
        ]

        self.user = self.app_backend.get_user(projection)

    def get_main_user_widget(self):
        """
        Create and return QWidget with main informations

        :return: main QWidget
        :rtype: QWidget
        """

        main_user_widget = QWidget()
        main_layout = QGridLayout()
        main_user_widget.setLayout(main_layout)

        main_title = QLabel('Main informations:')
        main_layout.addWidget(main_title, 0, 0, 1, 2)

        realm_title = QLabel('Realm:')
        main_layout.addWidget(realm_title, 1, 0, 1, 1)
        realm_data = QLabel(self.user['_realm'])
        main_layout.addWidget(realm_data)

        role_title = QLabel('Role:')
        main_layout.addWidget(role_title, 2, 0, 1, 1)
        role_data = QLabel(str(self.user['is_admin']))
        main_layout.addWidget(role_data, 2, 1, 1, 1)

        mail_title = QLabel('Email:')
        main_layout.addWidget(mail_title, 3, 0, 1, 1)
        mail_data = QLabel(self.user['email'])
        main_layout.addWidget(mail_data, 3, 1, 1, 1)

        return main_user_widget

    def get_info_user_widget(self):
        """
        Create and return inf of user in a QWidget

        :return: information QWidet
        :rtype: QWidget
        """

        info_widget = QWidget()
        info_layout = QGridLayout()
        info_widget.setLayout(info_layout)

        info_layout.addWidget(self.get_rights_widget(), 0, 0, 1, 1)
        info_layout.addWidget(self.get_notes_widget(), 0, 1, 1, 1)

        return info_widget

    def get_rights_widget(self):
        """
        Create and return Rights QWidget

        :return: rights QWidget
        :rtype: QWidget
        """

        rights_widget = QWidget()
        rights_layout = QGridLayout()
        rights_widget.setLayout(rights_layout)

        rights_title = QLabel('Rights:')
        rights_layout.addWidget(rights_title, 0, 0, 1, 2)

        admin_title = QLabel('Administrator:')
        rights_layout.addWidget(admin_title, 1, 0, 1, 1)
        admin_data = QLabel(str(self.user['is_admin']))
        rights_layout.addWidget(admin_data, 1, 1, 1, 1)

        command_title = QLabel('Commands:')
        rights_layout.addWidget(command_title, 2, 0, 1, 1)
        command_data = QLabel(str(self.user['can_submit_commands']))
        rights_layout.addWidget(command_data, 2, 1, 1, 1)

        password_title = QLabel('Password:')
        rights_layout.addWidget(password_title, 3, 0, 1, 1)
        password_btn = QPushButton()
        password_btn.setIcon(QIcon(get_image_path('user')))
        password_btn.setFixedSize(32, 32)
        rights_layout.addWidget(password_btn, 3, 1, 1, 1)

        return rights_widget

    def get_notes_widget(self):
        """
        Create and return Notes QWidget

        :return: notes QWidget
        :rtype: QWidget
        """

        notes_widget = QWidget()
        notes_layout = QGridLayout()
        notes_widget.setLayout(notes_layout)

        notes_title = QLabel('Notes:')
        notes_layout.addWidget(notes_title, 0, 0, 1, 2)

        alias_title = QLabel('Alias')
        notes_layout.addWidget(alias_title, 1, 0, 1, 1)
        alias_data = QLabel(self.user['alias'])
        notes_layout.addWidget(alias_data, 1, 1, 1, 1)

        note_title = QLabel('Notes')
        notes_layout.addWidget(note_title, 2, 0, 1, 1)
        note_data = QLabel(self.user['notes'])
        notes_layout.addWidget(note_data, 2, 1, 1, 1)

        token_title = QLabel('Token')
        notes_layout.addWidget(token_title, 3, 0, 1, 1)
        token_data = QLabel(self.user['token'])
        notes_layout.addWidget(token_data, 3, 1, 1, 1)

        return notes_widget

    def get_notifications_widget(self):
        """
        Create and return notification QWidget for hosts and services

        :return: notifications QWidget
        :rtype: QWidget
        """

        notification_widget = QWidget()
        notification_layout = QGridLayout()
        notification_widget.setLayout(notification_layout)

        notification_layout.addWidget(self.get_hosts_notif_widget(), 0, 0, 1, 1)
        notification_layout.addWidget(self.get_services_notif_widget(), 0, 1, 1, 1)

        return notification_widget

    def get_hosts_notif_widget(self):
        """
        Create and return notification QWidget for hosts

        :return: hosts notification QWidget
        :rtype: QWidget
        """

        host_notif_widget = QWidget()
        host_notif_layout = QGridLayout()
        host_notif_widget.setLayout(host_notif_layout)

        notif_title = QLabel("Hosts notifications configurations")
        host_notif_layout.addWidget(notif_title, 0, 0, 1, 2)

        state_title = QLabel("State:")
        host_notif_layout.addWidget(state_title, 1, 0, 1, 1)
        notif_state = QCheckBox()
        notif_state.setChecked(self.user['host_notifications_enabled'])
        notif_state.stateChanged.connect(self.enable_notifications)
        notif_state.setObjectName('hostactions')
        notif_state.setFixedSize(18, 18)
        host_notif_layout.addWidget(notif_state, 1, 1, 1, 1)

        period_title = QLabel("Notification period:")
        host_notif_layout.addWidget(period_title, 2, 0, 1, 1)
        period_data = QLabel(self.user['host_notification_period'])
        host_notif_layout.addWidget(period_data, 2, 1, 1, 1)

        enable_title = QLabel("Notification enabled:")
        host_notif_layout.addWidget(enable_title, 3, 0, 1, 1)
        enable_data = QLabel(str(self.user['host_notifications_enabled']))
        host_notif_layout.addWidget(enable_data, 3, 1, 1, 1)

        option_title = QLabel("Options:")
        host_notif_layout.addWidget(option_title, 4, 0, 1, 1)
        options_data = QLabel(str(self.user['host_notification_options']))
        host_notif_layout.addWidget(options_data, 4, 1, 1, 1)

        return host_notif_widget

    def get_services_notif_widget(self):
        """
        Create and return notification QWidget for services

        :return: services notification QWidget
        :rtype: QWidget
        """

        service_notif_widget = QWidget()
        service_notif_layout = QGridLayout()
        service_notif_widget.setLayout(service_notif_layout)

        notif_title = QLabel("Services notifications configurations")
        service_notif_layout.addWidget(notif_title, 0, 0, 1, 2)

        state_title = QLabel("State:")
        service_notif_layout.addWidget(state_title, 1, 0, 1, 1)
        notif_state = QCheckBox()
        notif_state.setObjectName('serviceactions')
        notif_state.setChecked(self.user['service_notifications_enabled'])
        notif_state.stateChanged.connect(self.enable_notifications)
        notif_state.checkState()
        notif_state.setFixedSize(18, 18)
        service_notif_layout.addWidget(notif_state, 1, 1, 1, 1)

        period_title = QLabel("Notification period:")
        service_notif_layout.addWidget(period_title, 2, 0, 1, 1)
        period_data = QLabel(self.user['service_notification_period'])
        service_notif_layout.addWidget(period_data, 2, 1, 1, 1)

        enable_title = QLabel("Notification enabled:")
        service_notif_layout.addWidget(enable_title, 3, 0, 1, 1)
        enable_data = QLabel(str(self.user['service_notifications_enabled']))
        service_notif_layout.addWidget(enable_data, 3, 1, 1, 1)

        option_title = QLabel("Options:")
        service_notif_layout.addWidget(option_title, 4, 0, 1, 1)
        options_data = QLabel(str(self.user['service_notification_options']))
        service_notif_layout.addWidget(options_data, 4, 1, 1, 1)

        return service_notif_widget

    def enable_notifications(self):
        """
        Enable notification for the wanted type: hosts or services

        """

        check_btn = self.sender()

        notification_type = ''
        if 'hostactions' in check_btn.objectName():
            notification_type = 'host_notifications_enabled'
        elif 'serviceactions' in check_btn.objectName():
            notification_type = 'service_notifications_enabled'
        else:
            logger.error('Wrong caller %s' % self.sender().objectName())

        if notification_type:
            # check_btn.checkState() is equal to 0 or 2
            notification_enabled = True if check_btn.checkState() else False
            data = {notification_type: notification_enabled}
            headers = {'If-Match': self.user['_etag']}
            endpoint = '/'.join(['user', self.user['_id']])

            patched = self.app_backend.patch(endpoint, data, headers)

            if patched:
                enabled = 'enabled' if notification_enabled else 'disabled'
                message = "Notifications for %ss are %s" % (
                    check_btn.objectName().replace('actions', ''),
                    enabled
                )
                send_banner('OK', message, duration=10000)
            else:
                send_banner('ERROR', "Backend PATCH failed, please check your logs !")

class User(object):
    """
        User manage the UserProfile QWidget creation
    """

    def __init__(self, app_backend):
        self.app_backend = app_backend
        self.user_widget = None

    def create_user_profile(self):
        """
        Create the USerProfile QWidget. Store old informations if needed.

        """

        old_pos = None
        if self.user_widget:
            old_pos = self.user_widget.app_widget.pos()
            self.user_widget.deleteLater()
            self.user_widget = None

        self.user_widget = UserProfile(self.app_backend)
        self.user_widget.initialize()

        if old_pos:
            self.user_widget.app_widget.move(old_pos)

    def show_user_widget(self):
        """
        Destroy and create the UserProfile, then show it

        """

        self.create_user_profile()
        self.user_widget.app_widget.show()
<commit_msg>Add icons and timeperiods<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2015-2017:
#   Matthieu Estrada, ttamalfor@gmail.com
#
# This file is part of (AlignakApp).
#
# (AlignakApp) is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# (AlignakApp) is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with (AlignakApp).  If not, see <http://www.gnu.org/licenses/>.

"""
    User manage QWidget who display User Profile.
"""

from logging import getLogger

from alignak_app.core.utils import get_image_path, get_css
from alignak_app.widgets.app_widget import AppQWidget
from alignak_app.widgets.banner import send_banner

from PyQt5.QtWidgets import QWidget, QPushButton, QCheckBox  # pylint: disable=no-name-in-module
from PyQt5.QtWidgets import QGridLayout, QVBoxLayout  # pylint: disable=no-name-in-module
from PyQt5.QtWidgets import QLabel  # pylint: disable=no-name-in-module
from PyQt5.Qt import QIcon, QPixmap  # pylint: disable=no-name-in-module

logger = getLogger(__name__)

class UserProfile(QWidget):
    """
        Class who create QWidget for User Profile.
    """

    def __init__(self, app_backend, parent=None):
        super(UserProfile, self).__init__(parent)
        self.setStyleSheet(get_css())
        self.setMinimumSize(800, 600)
        # Fields
        self.user = None
        self.app_backend = app_backend
        self.app_widget = None

    def initialize(self):
        """
        Initialize User QWidget

        """

        # Get the user data first
        self.get_user_data()

        # Then initialize AppQWidget
        self.app_widget = AppQWidget()
        self.app_widget.initialize('User view: %s' % self.user['alias'])
        self.app_widget.add_widget(self)

        layout = QVBoxLayout()
        self.setLayout(layout)

        layout.addWidget(self.get_main_user_widget())
        layout.addWidget(self.get_rights_widget())
        layout.addWidget(self.get_notes_widget())

        layout.addWidget(self.get_notifications_widget())

    def get_user_data(self):
        """
        Get and set the user data

        """

        projection = [
            '_realm',
            'is_admin',
            'back_role_super_admin',
            'alias',
            'name',
            'notes',
            'email',
            'can_submit_commands',
            'token',
            'host_notifications_enabled',
            'service_notifications_enabled',
            'host_notification_period',
            'service_notification_period',
            'host_notification_options',
            'service_notification_options',
        ]

        self.user = self.app_backend.get_user(projection)

    def get_main_user_widget(self):
        """
        Create and return QWidget with main informations

        :return: main QWidget
        :rtype: QWidget
        """

        main_user_widget = QWidget()
        main_layout = QGridLayout()
        main_user_widget.setLayout(main_layout)

        main_title = QLabel('Main informations:')
        main_title.setObjectName("usertitle")
        main_layout.addWidget(main_title, 0, 0, 1, 2)

        realm_title = QLabel('Realm:')
        realm_title.setObjectName("usersubtitle")
        main_layout.addWidget(realm_title, 1, 0, 1, 1)
        realm_data = QLabel(self.user['_realm'])
        main_layout.addWidget(realm_data)

        role_title = QLabel('Role:')
        role_title.setObjectName("usersubtitle")
        main_layout.addWidget(role_title, 2, 0, 1, 1)
        role_data = QLabel(self.get_role().capitalize())
        main_layout.addWidget(role_data, 2, 1, 1, 1)

        mail_title = QLabel('Email:')
        mail_title.setObjectName("usersubtitle")
        main_layout.addWidget(mail_title, 3, 0, 1, 1)
        mail_data = QLabel(self.user['email'])
        main_layout.addWidget(mail_data, 3, 1, 1, 1)

        return main_user_widget

    def get_role(self):
        """
        Get user role

        :return: role of user
        :rtype: str
        """

        role = 'user'

        if self.user['is_admin'] or self.user['back_role_super_admin']:
            role = 'administrator'
        if self.user['can_submit_commands'] and not self.user['is_admin']:
            role = 'power'

        return role

    def get_rights_widget(self):
        """
        Create and return Rights QWidget

        :return: rights QWidget
        :rtype: QWidget
        """

        rights_widget = QWidget()
        rights_layout = QGridLayout()
        rights_widget.setLayout(rights_layout)

        rights_title = QLabel('Rights:')
        rights_title.setObjectName("usertitle")
        rights_layout.addWidget(rights_title, 0, 0, 1, 2)

        admin_title = QLabel('Administrator:')
        admin_title.setObjectName("usersubtitle")
        admin_title.setMinimumHeight(32)
        rights_layout.addWidget(admin_title, 1, 0, 1, 1)
        admin_data = self.get_enable_label_icon(
            self.user['is_admin']
        )
        rights_layout.addWidget(admin_data, 1, 1, 1, 1)

        command_title = QLabel('Commands:')
        command_title.setObjectName("usersubtitle")
        command_title.setMinimumHeight(32)
        rights_layout.addWidget(command_title, 2, 0, 1, 1)
        command_data = self.get_enable_label_icon(
            self.user['can_submit_commands']
        )
        rights_layout.addWidget(command_data, 2, 1, 1, 1)

        password_title = QLabel('Password:')
        password_title.setObjectName("usersubtitle")
        rights_layout.addWidget(password_title, 3, 0, 1, 1)
        password_btn = QPushButton()
        password_btn.setIcon(QIcon(get_image_path('user')))
        password_btn.setFixedSize(32, 32)
        rights_layout.addWidget(password_btn, 3, 1, 1, 1)

        return rights_widget

    def get_notes_widget(self):
        """
        Create and return Notes QWidget

        :return: notes QWidget
        :rtype: QWidget
        """

        notes_widget = QWidget()
        notes_layout = QGridLayout()
        notes_widget.setLayout(notes_layout)

        main_notes_title = QLabel('Notes:')
        main_notes_title.setObjectName("usertitle")
        notes_layout.addWidget(main_notes_title, 0, 0, 1, 2)

        alias_title = QLabel('Alias:')
        alias_title.setObjectName("usersubtitle")
        notes_layout.addWidget(alias_title, 1, 0, 1, 1)
        alias_data = QLabel(self.user['alias'])
        notes_layout.addWidget(alias_data, 1, 1, 1, 1)

        notes_title = QLabel('Notes:')
        notes_title.setObjectName("usersubtitle")
        notes_layout.addWidget(notes_title, 2, 0, 1, 1)
        note_data = QLabel(self.user['notes'])
        notes_layout.addWidget(note_data, 2, 1, 1, 1)

        token_title = QLabel('Token:')
        token_title.setObjectName("usersubtitle")
        notes_layout.addWidget(token_title, 3, 0, 1, 1)
        token_data = QLabel(self.user['token'])
        notes_layout.addWidget(token_data, 3, 1, 1, 1)

        return notes_widget

    def get_notifications_widget(self):
        """
        Create and return notification QWidget for hosts and services

        :return: notifications QWidget
        :rtype: QWidget
        """

        notification_widget = QWidget()
        notification_layout = QGridLayout()
        notification_widget.setLayout(notification_layout)

        notification_layout.addWidget(self.get_hosts_notif_widget(), 0, 0, 1, 1)
        notification_layout.addWidget(self.get_services_notif_widget(), 0, 1, 1, 1)

        return notification_widget

    def get_hosts_notif_widget(self):
        """
        Create and return notification QWidget for hosts

        :return: hosts notification QWidget
        :rtype: QWidget
        """

        host_notif_widget = QWidget()
        host_notif_layout = QGridLayout()
        host_notif_widget.setLayout(host_notif_layout)

        notif_title = QLabel("Hosts notifications configurations")
        notif_title.setObjectName("usertitle")
        host_notif_layout.addWidget(notif_title, 0, 0, 1, 2)

        state_title = QLabel("State:")
        state_title.setObjectName("usersubtitle")
        host_notif_layout.addWidget(state_title, 1, 0, 1, 1)
        notif_state = QCheckBox()
        notif_state.setChecked(self.user['host_notifications_enabled'])
        notif_state.stateChanged.connect(self.enable_notifications)
        notif_state.setObjectName('hostactions')
        notif_state.setFixedSize(18, 18)
        host_notif_layout.addWidget(notif_state, 1, 1, 1, 1)

        enable_title = QLabel("Notification enabled:")
        enable_title.setMinimumHeight(32)
        enable_title.setObjectName("usersubtitle")
        host_notif_layout.addWidget(enable_title, 2, 0, 1, 1)
        enable_icon = self.get_enable_label_icon(
            self.user['host_notifications_enabled']
        )
        host_notif_layout.addWidget(enable_icon, 2, 1, 1, 1)

        period_title = QLabel("Notification period:")
        period_title.setObjectName("usersubtitle")
        host_notif_layout.addWidget(period_title, 3, 0, 1, 1)
        period = self.get_period_name(self.user['host_notification_period'])
        period_data = QLabel(period.capitalize())
        host_notif_layout.addWidget(period_data, 3, 1, 1, 1)

        option_title = QLabel("Options:")
        option_title.setObjectName("usersubtitle")
        host_notif_layout.addWidget(option_title, 4, 0, 1, 1)
        options_data = QLabel(str(self.user['host_notification_options']))
        host_notif_layout.addWidget(options_data, 4, 1, 1, 1)

        return host_notif_widget

    def get_services_notif_widget(self):
        """
        Create and return notification QWidget for services

        :return: services notification QWidget
        :rtype: QWidget
        """

        service_notif_widget = QWidget()
        service_notif_layout = QGridLayout()
        service_notif_widget.setLayout(service_notif_layout)

        notif_title = QLabel("Services notifications configurations")
        notif_title.setObjectName("usertitle")
        service_notif_layout.addWidget(notif_title, 0, 0, 1, 2)

        state_title = QLabel("State:")
        state_title.setObjectName("usersubtitle")
        service_notif_layout.addWidget(state_title, 1, 0, 1, 1)
        notif_state = QCheckBox()
        notif_state.setObjectName('serviceactions')
        notif_state.setChecked(self.user['service_notifications_enabled'])
        notif_state.stateChanged.connect(self.enable_notifications)
        notif_state.checkState()
        notif_state.setFixedSize(18, 18)
        service_notif_layout.addWidget(notif_state, 1, 1, 1, 1)

        enable_title = QLabel("Notification enabled:")
        enable_title.setObjectName("usersubtitle")
        enable_title.setMinimumHeight(32)
        service_notif_layout.addWidget(enable_title, 2, 0, 1, 1)
        enable_data = self.get_enable_label_icon(
            self.user['service_notifications_enabled']
        )
        service_notif_layout.addWidget(enable_data, 2, 1, 1, 1)

        period_title = QLabel("Notification period:")
        period_title.setObjectName("usersubtitle")
        service_notif_layout.addWidget(period_title, 3, 0, 1, 1)
        period = self.get_period_name(self.user['service_notification_period'])
        period_data = QLabel(period.capitalize())
        service_notif_layout.addWidget(period_data, 3, 1, 1, 1)

        option_title = QLabel("Options:")
        option_title.setObjectName("usersubtitle")
        service_notif_layout.addWidget(option_title, 4, 0, 1, 1)
        options_data = QLabel(str(self.user['service_notification_options']))
        service_notif_layout.addWidget(options_data, 4, 1, 1, 1)

        return service_notif_widget

    def get_period_name(self, uuid):
        """
        Get the period name or alias

        :param uuid: the Id of the timeperiod
        :type uuid: str
        :return: name or alias of timeperiod
        :rtype: str
        """

        projection = [
            'name',
            'alias'
        ]

        endpoint = '/'.join(['timeperiod', uuid])

        period = self.app_backend.get(endpoint, projection=projection)

        if period:
            if period['alias']:
                return period['alias']
            else:
                return period['name']
        return ''

    def enable_notifications(self):
        """
        Enable notification for the wanted type: hosts or services

        """

        check_btn = self.sender()

        notification_type = ''
        if 'hostactions' in check_btn.objectName():
            notification_type = 'host_notifications_enabled'
        elif 'serviceactions' in check_btn.objectName():
            notification_type = 'service_notifications_enabled'
        else:
            logger.error('Wrong caller %s', self.sender().objectName())

        if notification_type:
            # check_btn.checkState() is equal to 0 or 2
            notification_enabled = True if check_btn.checkState() else False
            data = {notification_type: notification_enabled}
            headers = {'If-Match': self.user['_etag']}
            endpoint = '/'.join(['user', self.user['_id']])

            patched = self.app_backend.patch(endpoint, data, headers)

            if patched:
                enabled = 'enabled' if notification_enabled else 'disabled'
                message = "Notifications for %ss are %s" % (
                    check_btn.objectName().replace('actions', ''),
                    enabled
                )
                send_banner('OK', message, duration=10000)
            else:
                send_banner('ERROR', "Backend PATCH failed, please check your logs !")

    @staticmethod
    def get_enable_label_icon(state):
        """
        Return red crosse or green check QPixmap in QLabel, depending state is True of False

        :param state: state True of False
        :type state: bool
        :return: corresponding QLabel with QPixmap
        :rtype: QLabel
        """

        states = {
            True: 'checked',
            False: 'error'
        }

        icon = QPixmap(get_image_path(states[state]))

        enable_icon = QLabel()
        enable_icon.setFixedSize(18, 18)
        enable_icon.setPixmap(icon)
        enable_icon.setScaledContents(True)

        return enable_icon

class User(object):
    """
        User manage the UserProfile QWidget creation
    """

    def __init__(self, app_backend):
        self.app_backend = app_backend
        self.user_widget = None

    def create_user_profile(self):
        """
        Create the USerProfile QWidget. Store old informations if needed.

        """

        old_pos = None
        if self.user_widget:
            old_pos = self.user_widget.app_widget.pos()
            self.user_widget.deleteLater()
            self.user_widget = None

        self.user_widget = UserProfile(self.app_backend)
        self.user_widget.initialize()

        if old_pos:
            self.user_widget.app_widget.move(old_pos)

    def show_user_widget(self):
        """
        Destroy and create the UserProfile, then show it

        """

        self.create_user_profile()
        self.user_widget.app_widget.show()
<|endoftext|>


<commit_before>from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'(?P<pid>[\d\w]*)/(?P<wid>[\d\w]*)', 'iridium.scm.views.viewRepo'),
    (r'(?P<pid>[\d\w]*)', 'iridium.scm.views.listRepos'),
)
<commit_msg>Updated scm urls<commit_after>from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'(?P<pid>[\d\w]*)/(?P<rid>[\d\w]*)/diff/(?P<cid>[\d\w]*)', 'iridium.scm.views.viewDiff'),
    (r'(?P<pid>[\d\w]*)/(?P<rid>[\d\w]*)', 'iridium.scm.views.viewRepo'),
    (r'(?P<pid>[\d\w]*)', 'iridium.scm.views.listRepos'),
)
<|endoftext|>


<commit_before>from py2neo import neo4j
import sys
from .exception import DoesNotExist
from .util import camel_to_upper

OUTGOING = neo4j.Direction.OUTGOING
INCOMING = neo4j.Direction.INCOMING
EITHER = neo4j.Direction.EITHER

def _related(direction):
    if direction == OUTGOING:
        return '-[:{0}]->'
    elif direction == INCOMING:
        return '<-[:{0}]-'
    else:
        return '-[:{0}]-'

def _properties(ident, **kwargs):
    props = [ident + '.' + k + '! = {' + k + '}' for k in kwargs]
    return '(' + ', '.join(props) + ')'

class RelationshipManager(object):
    def __init__(self, direction, relation_type, node_classes, origin):
        self.direction = direction
        self.relation_type = relation_type
        if isinstance(node_classes, list):
            self.node_classes = node_classes
            self.class_map = dict(zip([camel_to_upper(c.__name__) for c in node_classes],
                node_classes))
        else:
            self.node_class = node_classes
        self.origin = origin

    @property
    def client(self):
        return self.origin.client

    def __len__(self):
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(x) RETURN COUNT(x)"
        return int(self.origin.cypher(query)[0][0][0])

    def count(self):
        return self.__len__()

    def all(self):
        if hasattr(self, 'node_classes'):
            return self._all_multi_class()
        else:
            return self._all_single_class()

    def _inflate_nodes_by_rel(self, results):
        """With resultset containing [node, rel] pairs
        wrap each node in correct neomodel class based on rel.type"""
        nodes = [row[0] for row in results]
        classes = [self.class_map[row[1].type] for row in results]
        return [cls.inflate(node) for node, cls in zip(nodes, classes)]

    def _all_multi_class(self):
        cat_types = "|".join([camel_to_upper(c.__name__) for c in self.node_classes])
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(x)<-[r:{0}]-() RETURN x, r".format(cat_types)
        results = self.origin.cypher(query)[0]
        return self._inflate_nodes_by_rel(results)

    def _all_single_class(self):
        nodes = self.origin.__node__.get_related_nodes(self.direction, self.relation_type)
        if not nodes:
            return []
        return [self.node_class.inflate(n) for n in nodes]

    def get(self, **kwargs):
        result = self.search(**kwargs)
        if len(result) == 1:
            return result[0]
        if len(result) > 1:
            raise Exception("Multiple items returned")
        if not result:
            if hasattr(self, 'node_class'):
                raise self.node_class.DoesNotExist("No items exist for the specified arguments")
            else:
                raise DoesNotExist("No items exist for the specified arguments")

    def search(self, **kwargs):
        if not kwargs:
            if hasattr(self, 'node_classes'):
                return self._all_multi_class()
            else:
                return self._all_single_class()

        if hasattr(self, 'node_classes'):
            return self._search_multi_class(**kwargs)
        else:
            return self._search_single_class(**kwargs)

    def _search_single_class(self, **kwargs):
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(b) WHERE " + _properties('b', **kwargs)
        query += " RETURN b"

        results = self.origin.cypher(query, kwargs)[0]
        return [self.node_class.inflate(row[0]) for row in results]

    def _search_multi_class(self, **kwargs):
        cat_types = "|".join([camel_to_upper(c.__name__) for c in self.node_classes])
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(b)<-[r:{0}]-() ".format(cat_types)
        query += "WHERE " + _properties('b', **kwargs)
        query += " RETURN b, r"
        results = self.origin.cypher(query, kwargs)[0]
        return self._inflate_nodes_by_rel(results)

    def is_connected(self, obj):
        return self.origin.__node__.has_relationship_with(obj.__node__, self.direction, self.relation_type)

    def connect(self, obj):
        if self.direction == EITHER:
            raise Exception("Cannot connect with direction EITHER")
        # is single class rel
        if hasattr(self, 'node_class'):
            if not self.node_class.__subclasscheck__(obj.__class__):
                raise Exception("Expected object of class (or a subclass of) "
                        + self.node_class.__name__ + " got " + obj.__class__.__name__)
        # or is multi class rel
        elif hasattr(self, 'node_classes'):
            for cls in self.node_classes:
                if cls.__subclasscheck__(obj.__class__):
                    node_class = cls
            if not node_class:
                allowed_cls = ", ".join([c.__name__ for c in self.node_classes])
                raise Exception("Expected object of class of "
                        + allowed_cls + " got " + obj.__class__.__name__)

        if not obj.__node__:
            raise Exception("Can't create relationship to unsaved node")
        if self.direction == OUTGOING:
            self.client.get_or_create_relationships((self.origin.__node__, self.relation_type, obj.__node__))
        elif self.direction == INCOMING:
            self.client.get_or_create_relationships((obj.__node__, self.relation_type, self.origin.__node__))
        else:
            raise Exception("Unknown relationship direction {0}".format(self.direction))

    def reconnect(self, old_obj, new_obj):
        if self.is_connected(old_obj):
            rels = self.origin.__node__.get_relationships_with(
                    old_obj.__node__, self.direction, self.relation_type)
            for r in rels:
                r.delete()
        else:
            raise NotConnected(old_obj.__node__.id)

        self.client.get_or_create_relationships((self.origin.__node__, self.relation_type, new_obj.__node__),)

    def disconnect(self, obj):
        rels = self.origin.__node__.get_relationships_with(obj.__node__, self.direction, self.relation_type)
        if not rels:
            raise NotConnected(obj.__node__.id)
        if len(rels) > 1:
            raise Exception("Expected single relationship got {0}".format(rels))
        rels[0].delete()

    def single(self):
        nodes = self.all()
        if nodes:
            return nodes[0]
        else:
            return None

class RelationshipDefinition(object):
    def __init__(self, relation_type, cls_name, direction, manager=RelationshipManager):
        self.module_name = sys._getframe(4).f_globals['__name__']
        self.relation_type = relation_type
        self.node_class = cls_name
        self.manager = manager
        self.direction = direction

    def lookup_classes(self):
        if isinstance(self.node_class, list):
            return [self._lookup(name) for name in self.node_class]
        else:
            return self._lookup(self.node_class)

    def _lookup(self, name):
        if name.find('.') is -1:
            module = self.module_name
        else:
            module, _, name = name.rpartition('.')

        if not module in sys.modules:
            __import__(module)
        return getattr(sys.modules[module], name)

    def build_manager(self, origin, name):
        rel = self.manager(
                self.direction,
                self.relation_type,
                self.lookup_classes(),
                origin
               )
        rel.name = name
        return rel

def _relate(cls_name, direction, rel_type, cardinality=None):
    if not isinstance(cls_name, (str, unicode, list)):
        raise Exception('Expected class name or list of class names, got ' + repr(cls_name))
    if not cardinality: # TODO do we need this? - avoid circular ref
        from .cardinality import ZeroOrMore
        cardinality = ZeroOrMore
    return RelationshipDefinition(rel_type, cls_name, direction, cardinality)

def RelationshipTo(cls_name, rel_type, cardinality=None):
    return _relate(cls_name, OUTGOING, rel_type, cardinality)

def RelationshipFrom(cls_name, rel_type, cardinality=None):
    return _relate(cls_name, INCOMING, rel_type, cardinality)

def Relationship(cls_name, rel_type, cardinality=None):
    return _relate(cls_name, EITHER, rel_type, cardinality)

class NotConnected(Exception):
    pass
<commit_msg>updated _all_multi_class query to incorporate __instance__ property<commit_after>from py2neo import neo4j
import sys
from .exception import DoesNotExist
from .util import camel_to_upper

OUTGOING = neo4j.Direction.OUTGOING
INCOMING = neo4j.Direction.INCOMING
EITHER = neo4j.Direction.EITHER

def _related(direction):
    if direction == OUTGOING:
        return '-[:{0}]->'
    elif direction == INCOMING:
        return '<-[:{0}]-'
    else:
        return '-[:{0}]-'

def _properties(ident, **kwargs):
    props = [ident + '.' + k + '! = {' + k + '}' for k in kwargs]
    return '(' + ', '.join(props) + ')'

class RelationshipManager(object):
    def __init__(self, direction, relation_type, node_classes, origin):
        self.direction = direction
        self.relation_type = relation_type
        if isinstance(node_classes, list):
            self.node_classes = node_classes
            self.class_map = dict(zip([camel_to_upper(c.__name__) for c in node_classes],
                node_classes))
        else:
            self.node_class = node_classes
        self.origin = origin

    @property
    def client(self):
        return self.origin.client

    def __len__(self):
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(x) RETURN COUNT(x)"
        return int(self.origin.cypher(query)[0][0][0])

    def count(self):
        return self.__len__()

    def all(self):
        if hasattr(self, 'node_classes'):
            return self._all_multi_class()
        else:
            return self._all_single_class()

    def _inflate_nodes_by_rel(self, results):
        """With resultset containing [node, rel] pairs
        wrap each node in correct neomodel class based on rel.type"""
        nodes = [row[0] for row in results]
        classes = [self.class_map[row[1].type] for row in results]
        return [cls.inflate(node) for node, cls in zip(nodes, classes)]

    def _all_multi_class(self):
        cat_types = "|".join([camel_to_upper(c.__name__) for c in self.node_classes])
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(x)<-[r:{0}]-() WHERE r.__instance__ = true RETURN x, r".format(cat_types)
        results = self.origin.cypher(query)[0]
        return self._inflate_nodes_by_rel(results)

    def _all_single_class(self):
        nodes = self.origin.__node__.get_related_nodes(self.direction, self.relation_type)
        if not nodes:
            return []
        return [self.node_class.inflate(n) for n in nodes]

    def get(self, **kwargs):
        result = self.search(**kwargs)
        if len(result) == 1:
            return result[0]
        if len(result) > 1:
            raise Exception("Multiple items returned")
        if not result:
            if hasattr(self, 'node_class'):
                raise self.node_class.DoesNotExist("No items exist for the specified arguments")
            else:
                raise DoesNotExist("No items exist for the specified arguments")

    def search(self, **kwargs):
        if not kwargs:
            if hasattr(self, 'node_classes'):
                return self._all_multi_class()
            else:
                return self._all_single_class()

        if hasattr(self, 'node_classes'):
            return self._search_multi_class(**kwargs)
        else:
            return self._search_single_class(**kwargs)

    def _search_single_class(self, **kwargs):
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(b) WHERE " + _properties('b', **kwargs)
        query += " RETURN b"

        results = self.origin.cypher(query, kwargs)[0]
        return [self.node_class.inflate(row[0]) for row in results]

    def _search_multi_class(self, **kwargs):
        cat_types = "|".join([camel_to_upper(c.__name__) for c in self.node_classes])
        query = "START a=node({self}) MATCH (a)"
        query += _related(self.direction).format(self.relation_type)
        query += "(b)<-[r:{0}]-() ".format(cat_types)
        query += "WHERE " + _properties('b', **kwargs)
        query += " RETURN b, r"
        results = self.origin.cypher(query, kwargs)[0]
        return self._inflate_nodes_by_rel(results)

    def is_connected(self, obj):
        return self.origin.__node__.has_relationship_with(obj.__node__, self.direction, self.relation_type)

    def connect(self, obj):
        if self.direction == EITHER:
            raise Exception("Cannot connect with direction EITHER")
        # is single class rel
        if hasattr(self, 'node_class'):
            if not self.node_class.__subclasscheck__(obj.__class__):
                raise Exception("Expected object of class (or a subclass of) "
                        + self.node_class.__name__ + " got " + obj.__class__.__name__)
        # or is multi class rel
        elif hasattr(self, 'node_classes'):
            for cls in self.node_classes:
                if cls.__subclasscheck__(obj.__class__):
                    node_class = cls
            if not node_class:
                allowed_cls = ", ".join([c.__name__ for c in self.node_classes])
                raise Exception("Expected object of class of "
                        + allowed_cls + " got " + obj.__class__.__name__)

        if not obj.__node__:
            raise Exception("Can't create relationship to unsaved node")
        if self.direction == OUTGOING:
            self.client.get_or_create_relationships((self.origin.__node__, self.relation_type, obj.__node__))
        elif self.direction == INCOMING:
            self.client.get_or_create_relationships((obj.__node__, self.relation_type, self.origin.__node__))
        else:
            raise Exception("Unknown relationship direction {0}".format(self.direction))

    def reconnect(self, old_obj, new_obj):
        if self.is_connected(old_obj):
            rels = self.origin.__node__.get_relationships_with(
                    old_obj.__node__, self.direction, self.relation_type)
            for r in rels:
                r.delete()
        else:
            raise NotConnected(old_obj.__node__.id)

        self.client.get_or_create_relationships((self.origin.__node__, self.relation_type, new_obj.__node__),)

    def disconnect(self, obj):
        rels = self.origin.__node__.get_relationships_with(obj.__node__, self.direction, self.relation_type)
        if not rels:
            raise NotConnected(obj.__node__.id)
        if len(rels) > 1:
            raise Exception("Expected single relationship got {0}".format(rels))
        rels[0].delete()

    def single(self):
        nodes = self.all()
        if nodes:
            return nodes[0]
        else:
            return None

class RelationshipDefinition(object):
    def __init__(self, relation_type, cls_name, direction, manager=RelationshipManager):
        self.module_name = sys._getframe(4).f_globals['__name__']
        self.relation_type = relation_type
        self.node_class = cls_name
        self.manager = manager
        self.direction = direction

    def lookup_classes(self):
        if isinstance(self.node_class, list):
            return [self._lookup(name) for name in self.node_class]
        else:
            return self._lookup(self.node_class)

    def _lookup(self, name):
        if name.find('.') is -1:
            module = self.module_name
        else:
            module, _, name = name.rpartition('.')

        if not module in sys.modules:
            __import__(module)
        return getattr(sys.modules[module], name)

    def build_manager(self, origin, name):
        rel = self.manager(
                self.direction,
                self.relation_type,
                self.lookup_classes(),
                origin
               )
        rel.name = name
        return rel

def _relate(cls_name, direction, rel_type, cardinality=None):
    if not isinstance(cls_name, (str, unicode, list)):
        raise Exception('Expected class name or list of class names, got ' + repr(cls_name))
    if not cardinality: # TODO do we need this? - avoid circular ref
        from .cardinality import ZeroOrMore
        cardinality = ZeroOrMore
    return RelationshipDefinition(rel_type, cls_name, direction, cardinality)

def RelationshipTo(cls_name, rel_type, cardinality=None):
    return _relate(cls_name, OUTGOING, rel_type, cardinality)

def RelationshipFrom(cls_name, rel_type, cardinality=None):
    return _relate(cls_name, INCOMING, rel_type, cardinality)

def Relationship(cls_name, rel_type, cardinality=None):
    return _relate(cls_name, EITHER, rel_type, cardinality)

class NotConnected(Exception):
    pass
<|endoftext|>


<commit_before>#! /usr/bin/env python
#
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
# GENI Public License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#
# }}}
#

#
#
import sys
import pwd
import getopt
import os
import re

ACCEPTSLICENAME=1
URN = None

execfile( "test-common.py" )

if len(REQARGS) < 1:
    print >> sys.stderr, "Must provide the action (start/stop/restart)"
    sys.exit(1)
else:
    action = REQARGS[0]
    if action != "start" and action != "stop" and action != "restart":
        print >> sys.stderr, "Action must be one of start/stop/restart"
        sys.exit(1)
        pass
    if len(REQARGS) == 2:
        URN = REQARGS[1]
        pass
    pass

#
# Get a credential for myself, that allows me to do things at the SA.
#
mycredential = get_self_credential()
print "Got my SA credential. Looking for slice ..."

#
# Lookup slice, delete before proceeding.
#
myslice = resolve_slice( SLICENAME, mycredential )
print "Found the slice, asking for a credential ..."

if admincredentialfile:
  f = open( admincredentialfile )
  slivercred = f.read()
  f.close()
else:
  #
  # Get the slice credential.
  #
  slicecred = get_slice_credential( myslice, mycredential )
  print "Got the slice credential, asking for a sliver credential ..."

  #
  # Get the sliver credential.
  #
  params = {}
  params["credentials"] = (slicecred,)
  params["slice_urn"]   = myslice["urn"]
  rval,response = do_method("cm", "GetSliver", params, version="2.0")
  if rval:
    Fatal("Could not get Sliver credential")
    pass
  slivercred = response["value"]

if action == "start":
    method = "StartSliver"
elif action == "stop":
    method = "StopSliver"
else:
    method = "RestartSliver"
    pass

#
# Start the sliver.
#
print "Got the sliver credential, calling " + method + " on the sliver";
params = {}
params["credentials"] = (slivercred,)
if URN:
    params["component_urns"] = (URN,)
else:
    params["slice_urn"] = myslice["urn"]
    pass
rval,response = do_method("cm", method, params, version="2.0")
if rval:
    Fatal("Could not start sliver")
    pass
print "Sliver has been " + action + "'ed."

<commit_msg>Add reload sliver action.<commit_after>#! /usr/bin/env python
#
# Copyright (c) 2008-2014 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
# GENI Public License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#
# }}}
#

#
#
import sys
import pwd
import getopt
import os
import re

ACCEPTSLICENAME=1
URN = None

execfile( "test-common.py" )

if len(REQARGS) < 1:
    print >> sys.stderr, "Must provide the action (start/stop/restart)"
    sys.exit(1)
else:
    action = REQARGS[0]
    if (action != "start" and action != "stop" and
        action != "restart" and action != "reload"):
        print >> sys.stderr, "Action must be one of start/stop/restart/reload"
        sys.exit(1)
        pass
    if len(REQARGS) == 2:
        URN = REQARGS[1]
        pass
    pass

#
# Get a credential for myself, that allows me to do things at the SA.
#
mycredential = get_self_credential()
print "Got my SA credential. Looking for slice ..."

#
# Lookup slice, delete before proceeding.
#
myslice = resolve_slice( SLICENAME, mycredential )
print "Found the slice, asking for a credential ..."

if admincredentialfile:
  f = open( admincredentialfile )
  slivercred = f.read()
  f.close()
else:
  #
  # Get the slice credential.
  #
  slicecred = get_slice_credential( myslice, mycredential )
  print "Got the slice credential, asking for a sliver credential ..."

  #
  # Get the sliver credential.
  #
  params = {}
  params["credentials"] = (slicecred,)
  params["slice_urn"]   = myslice["urn"]
  rval,response = do_method("cm", "GetSliver", params, version="2.0")
  if rval:
    Fatal("Could not get Sliver credential")
    pass
  slivercred = response["value"]

if action == "start":
    method = "StartSliver"
elif action == "stop":
    method = "StopSliver"
elif action == "reload":
    method = "ReloadSliver"
else:
    method = "RestartSliver"
    pass

#
# Start the sliver.
#
print "Got the sliver credential, calling " + method + " on the sliver";
params = {}
params["credentials"] = (slivercred,)
if URN:
    params["component_urns"] = (URN,)
else:
    params["slice_urn"] = myslice["urn"]
    pass
rval,response = do_method("cm", method, params, version="2.0")
if rval:
    Fatal("Could not start sliver")
    pass
print "Sliver has been " + action + "'ed."

<|endoftext|>