class ElasticSearchModel:
    def __init__(self, tid=None, ip=None):

        logger = logging.getLogger('Avispa')
        self.lggr = AvispaLoggerAdapter(logger, {'tid': tid, 'ip': ip})

    def get_a_b(self, handle, ring, q=None):

        # Connect to Elastic Search Node
        es_url = ES_NODE
        connections.create_connection(hosts=[es_url])

        field = '_all'

        s = Search(index=handle,doc_type=ring) \
            .query("match", **{field:q})

        response = s.execute()

        print("Searching in %s/%s" % (handle, ring))
        print(s.to_dict())

        #return response

        out = []

        for hit in response:
            # hit meta contains: index,score,id,doc_type
            # i.e:  hit.meta.score

            item = collections.OrderedDict()
            item['_id'] = hit.meta.id

            #print
            #print(hit.meta.score)
            #print('%s/%s/%s'%(hit.meta.index,hit.meta.doc_type,hit.meta.id))

            for m in hit:
                item[m] = hit[m]
                item[m + '_flag'] = u'1000'

                #print (m,hit[m])

            out.append(item)

        return out

    def unindexer(self, handle, ring=None, idx=None):

        # Connect to Elastic Search Node
        es = Elasticsearch([ES_NODE])

        out = {}
        out['unindexed'] = []

        if handle and ring and idx:

            es.delete(index=handle, doc_type=ring, id=idx, ignore=[400, 404])
            i = '%s/%s/%s' % (handle, ring, idx)
        elif handle and ring:
            #es.delete(index=handle,doc_type=ring, ignore=[400, 404]) This doesnt work
            # Could not make elasticsearch_py delete a doc_type only
            requests.delete('%s/%s/%s' % (ES_NODE, handle, ring))
            i = '%s/%s' % (handle, ring)
        elif handle:
            es.indices.delete(index=handle, ignore=[400, 404])
            i = '%s' % (handle)

        self.lggr.info('UnIndexing:%s' % i)

        out['unindexed'].append(i)

        d = {}
        d['json_out'] = json.dumps(out)
        d['template'] = 'base_json.html'
        return d

        #'index':handle,'type':ringname,'id': idx

    def handle_indexer(self, url, handle):

        #1. Get all the active rings for this handle
        self.RIM = RingsModel()
        ringlist = self.RIM.user_get_rings(handle)
        print('RINGLIST:', ringlist)

        #2. Index one by one
        out = {}
        out['indexed'] = []

        for ring in ringlist:

            result = self.indexer(url, handle, ring['ringname'])

            x = json.loads(result['json_out'])
            out['indexed'] += x['indexed']

        self.lggr.info('Handle Indexed:%s' % handle)

        d = {}
        d['json_out'] = json.dumps(out)
        d['template'] = 'base_json.html'
        return d

    def indexer(self, url, handle, ring, idx=None):
        self.lggr.info('START indexer')
        # Good to Index (a/b) and (a/b/c) as they use same ring_class.
        # If you want to index a whole handle (a) use handle_indexer

        # Connect to Elastic Search Node
        es_url = ES_NODE
        self.lggr.info('START @ create_connection')
        connections.create_connection(hosts=[es_url])
        self.lggr.info('END @ create_connection')
        o = urlparse.urlparse(url)

        if idx:
            path = '_api/%s/%s/%s' % (handle, ring, idx)
        else:
            path = '_api/%s/%s' % (handle, ring)
        origin_url = urlparse.urlunparse(
            (URL_SCHEME, o.netloc, path, '', '', ''))
        schema, items = self.get_items(origin_url)
        #Preprare the ES Map (as a class)
        ring_class, ring_map = self.prepare_class(schema)
        #Create the index in the ES Cluster (indempotent action)
        self.create_index(ring_class, origin_url)
        #Index the item
        d = {}
        out = {}
        out['indexed'] = []

        for item in items:
            #Check that item is valid before attempting to index it
            if self.valid_item(item, ring_map):

                #try:
                if True:
                    handle, ring, idx = self.index_item(
                        ring_class, origin_url, item)
                    i = '%s/%s/%s' % (handle, ring, idx)
                    out['indexed'].append(i)
                    self.lggr.info('Indexed:%s' % i)

            else:

                #Here we store possible indexing errors
                if 'not_indexed' not in out:
                    out['not_indexed'] = []

                out['not_indexed'].append(item)
                self.lggr.error('Document invalid. Not Indexed:%s' % item)

        d['json_out'] = json.dumps(out)
        d['template'] = 'base_json.html'

        self.lggr.info('END indexer')
        return d

    def valid_item(self, item, ring_map):

        self.lggr.info('START valid_item')

        print("Check item against map:")
        print(ring_map)
        v_item = {}

        for f in ring_map:

            #print(f)
            valid = False
            if f in item:

                #print(ring_map[f],type(ring_map[f]))
                #if ring_map[f] is elasticsearch_dsl.field.String:
                if isinstance(ring_map[f], String):
                    #Check if item[f] is a string
                    if (isinstance(item[f], str)
                            or isinstance(item[f], unicode)):
                        valid = True
                        self.lggr.info('%s -> %s is a string (%s)' %
                                       (f, item[f], type(item[f])))
                    else:
                        self.lggr.error('%s -> %s not a string (%s)' %
                                        (f, item[f], type(item[f])))

                #elif ring_map[f] is elasticsearch_dsl.field.Object:
                elif isinstance(ring_map[f], Object):
                    #Check if item[f] is an object
                    if isinstance(item[f], dict):
                        v_item[f] = {}

                        print(ring_map[f].properties)

                        for p in ring_map[f].properties:
                            #Check if the property exists in the item
                            if p in item[f]:
                                #Check if the property is an elasticsearch_dsl.field.String:
                                if isinstance(ring_map[f].properties[p],
                                              String):
                                    #Check if item[f] is a string
                                    if (isinstance(item[f][p], str) or
                                            isinstance(item[f][p], unicode)):
                                        v_item[f][p] = item[f][p]
                                        valid = True
                                else:
                                    self.lggr.error('%s not a string (%s)' %
                                                    (item[f], type(item[f])))
                            else:
                                self.lggr.error('%s not in item' % p)

                    else:
                        self.lggr.error('%s not a dictionary (%s)' %
                                        (item[f], type(item[f])))

                        # TO-DO: Do we want nested objects? If yes develop.

                if valid:
                    # Add field to the output
                    v_item[f] = item[f]
                    self.lggr.info('Valid item. Will Index')
                else:
                    self.lggr.info('Invalid item. Will not index')

            else:
                self.lggr.info('%s not in map' % f)

        self.lggr.info('END valid_item')

        if len(v_item) > 0:
            return v_item
        else:
            return False

    def valid_api_url(self, url):

        o = urlparse.urlparse(url)
        p = o.path.split('/')

        if p[1] != '_api':
            path = '/_api' + o.path
        else:
            path = o.path

        return urlparse.urlunparse(
            (URL_SCHEME, o.netloc, path, '', 'schema=1&limit=_all', ''))

    def get_items(self, url):
        url = self.valid_api_url(
            url) + '&access_token=%s&fieldid=1' % TEMP_ACCESS_TOKEN
        self.lggr.info('START get_items ->%s' % url)
        result = requests.get(url, verify=False)
        self.lggr.info('result ->%s' % result.text)
        self.lggr.info('result.text ->%s' % result.text)
        r = result.json()
        self.lggr.info('result.json() ->%s' % r)
        schema = {'rings': r['rings'], 'fields': r['fields']}
        items = r['items']
        self.lggr.info('END get_items')
        return schema, items

    def prepare_class(self, schema):
        self.lggr.info('START prepare_class')

        d = {}
        for field in schema['fields']:

            if field['FieldType'] == 'INTEGER':
                d[field['FieldId']] = Integer()
            elif field['FieldType'] == 'OBJECT':
                if field['FieldMultilingual']:
                    f = {}
                    f['spa'] = String(analyzer='spanish')
                    f['eng'] = String(analyzer='english')
                    f['ita'] = String(analyzer='italian')
                    f['fra'] = String(analyzer='french')
                    d[field['FieldId']] = Object(properties=f)
                else:
                    #Some other kind of object
                    d[field['FieldId']] = String()
            elif field['FieldType'] == 'ARRAY':
                d[field['FieldId']] = String()
            elif field['FieldType'] == 'BOOLEAN':
                d[field['FieldId']] = Integer()
            else:
                d[field['FieldId']] = String()

        print(d)
        raw_map = d.copy()

        self.lggr.info('END prepare_class')
        return type(str(schema['rings'][0]['RingName']), (DocType, ),
                    d), raw_map

    def subtract_h_r_i(self, origin_url):
        self.lggr.info('START subtract_h_r_i')
        url = self.valid_api_url(origin_url)
        print(url)
        o = urlparse.urlparse(url)
        p = o.path.split('/')
        handle = p[2]
        if len(p) >= 4:
            ringname = p[3]
        else:
            ringname = None
        if len(p) >= 5:
            idx = p[4]
        else:
            idx = None

        self.lggr.info('END subtract_h_r_i')
        return handle, ringname, idx

    def create_index(self, ring_class, origin_url):
        self.lggr.info('START create_index')

        handle, ringname, idx = self.subtract_h_r_i(origin_url)
        # create the mappings in elasticsearch
        R = ring_class.init(handle)
        self.lggr.info('END create_index')
        return R

    def index_item(self, ring_class, origin_url, item):
        self.lggr.info('START index_item')

        handle, ringname, idx = self.subtract_h_r_i(origin_url)

        #overwrite the idx with items
        idx = item['_id']

        # create the mappings in elasticsearch

        #print(R)
        #print(handle)
        #print(ringname)
        #print(idx)
        #print(item)

        # create and save an item
        article = ring_class(meta={
            'index': handle,
            'type': ringname,
            'id': idx
        },
                             **item)
        print(article)
        article.save()
        print('SAVED')

        self.lggr.info('END index_item')
        return (handle, ringname, idx)
Exemple #2
0
class TeamsController:
    def __init__(self, tid=None, ip=None):

        logger = logging.getLogger('Avispa')
        self.lggr = AvispaLoggerAdapter(logger, {'tid': tid, 'ip': ip})

        self.MAM = MainModel(tid=tid, ip=ip)
        self.TEM = TeamsModel(tid=tid, ip=ip)
        self.PEM = PeopleModel(tid=tid, ip=ip)

    # GET/a
    def get_a_m(self, handle, team, *args, **kargs):

        d = {}

        peopleteams = self.MAM.is_org(handle)
        if peopleteams:
            #This is an organization

            d['teamlistlen'] = len(peopleteams['teams'])
            d['teammembership'] = {}
            allteams = {}
            for teamd in peopleteams['teams']:
                #get the profilepic for this person
                self.lggr.debug('teamname:%s' % teamd['teamname'])

                for member in teamd['members']:

                    self.lggr.debug('member:%s' % member['handle'])

                    person_user_doc = self.MAM.select_user_doc_view(
                        'auth/userbasic', member['handle'])
                    if person_user_doc:
                        member['thumbnail'] = person_user_doc['profilepic']

                    if current_user.id == member['handle']:
                        self.lggr.debug('%s is member' % member['handle'])
                        if teamd['teamname'] == 'owner':
                            d['teammembership'][
                                teamd['teamname']] = 'org_owner'
                        else:
                            if len(teamd['roles']) >= 1:
                                d['teammembership'][teamd['teamname']] = teamd[
                                    'roles'][-1]['role']

                allteams[teamd['teamname']] = 'org_owner'

            if 'owner' in d['teammembership']:
                d['teammembership'] = allteams

            d['teamlist'] = peopleteams['teams']
            d['template'] = 'avispa_rest/get_a_m.html'
        else:
            #This is a regular user
            #d['redirect'] = '/'+handle+'/_home'
            d['redirect'] = url_for('avispa_rest.home',
                                    handle=handle,
                                    _external=True,
                                    _scheme=URL_SCHEME)

        return d

        # POST/a
    def post_a_m(self, handle, team, rqform=None, *args, **kargs):
        '''
        Creates a new team
        '''
        #We need to recover from request as it doesn't come via URL
        team = rqform.get('newteam')

        #Check if the team exists or not
        d = {}

        peopleteams = self.MAM.is_org(handle)
        if peopleteams:

            redirect = url_for('avispa_rest.teams_a_m',
                               handle=handle,
                               _external=True,
                               _scheme=URL_SCHEME)

            #This is an organization
            for teamd in peopleteams['teams']:

                if teamd['teamname'] == team:
                    #This team exists in this handle!
                    flash('This team exists already. Use a different name',
                          'ER')
                    #redirect = '/'+handle+'/_teams'

                    d = {'redirect': redirect, 'status': 200}
                    return d

            if self.MAM.add_team(handle, team, current_user.id):
                self.lggr.debug('Awesome , you just created team %s ' % team)
                #msg = 'Item put with id: '+idx
                flash('Awesome , you just created team %s ' % team, 'UI')

            else:
                flash('There was an error adding team %s ' % team, 'UI')

        else:
            #This is not an organization
            #redirect = '/'+current_user.id
            redirect = url_for('avispa_rest.home',
                               handle=handle,
                               _external=True,
                               _scheme=URL_SCHEME)

        d = {'redirect': redirect, 'status': 200}
        return d

    def get_a_m_n(self, handle, team, *args, **kargs):

        d = {}

        rings = self.MAM.select_user_doc_view('rings/count', handle)
        d['rings'] = rings

        peopleteams = self.MAM.is_org(handle)
        if peopleteams:

            d['people'] = peopleteams['people']

            for teamd in peopleteams['teams']:
                #get the profilepic for this person

                if teamd['teamname'] == team:

                    if teamd['roles']:

                        if teamd['roles'][-1]['role'] == 'team_admin':
                            teamauth = 'RWX'
                        elif teamd['roles'][-1]['role'] == 'team_writer':
                            teamauth = 'RW'
                        elif teamd['roles'][-1]['role'] == 'team_reader':
                            teamauth = 'R'
                        else:
                            teamauth = ''

                        teamd['teamauth'] = teamauth

                    for member in teamd['members']:
                        person_user_doc = self.MAM.select_user_doc_view(
                            'auth/userbasic', member['handle'])
                        if person_user_doc:
                            member['thumbnail'] = person_user_doc['profilepic']

                    d['team'] = teamd
                    break

            d['template'] = 'avispa_rest/get_a_m_n.html'
        else:
            #This is a regular user
            #d['redirect'] = '/'+handle+'/_home'
            d['redirect'] = url_for('avispa_rest.home',
                                    handle=handle,
                                    _external=True,
                                    _scheme=URL_SCHEME)

        return d

    #DEPRECATED
    def put_a_m_n(self,
                  handle,
                  team,
                  rqform=None,
                  rqargs=None,
                  *args,
                  **kargs):

        #This function should be refactored into multiple functions that obey RESTFUL:
        # post_a_m_n_members , delete_a_m_n_members , post_a_m_n_rings, delete_a_m_n_rings

        d = {}

        if 'newmember' in rqform:
            member = rqform.get('newmember')
            if self.TEM.post_a_m_n_members(handle, team, member):
                self.lggr.debug('%s has been added to the team.' % member)
                flash('%s has been added to the team.' % member, 'UI')
            else:
                self.lggr.debug('%s is already part of this team.' % member)
                flash('%s is already part of this team.' % member, 'UI')

        if 'delmember' in rqargs:
            member = rqargs.get('delmember')
            if self.TEM.delete_a_m_n_members(handle, team, member):
                self.lggr.debug('%s has been deleted from the team.' % member)
                flash('%s has been deleted from the team.' % member, 'UI')
            else:
                self.lggr.error('There was an issue deleting: %s' % member)
                flash('There was an issue deleting: %s' % member, 'UI')

        if 'newring' in rqform:
            ring = rqform.get('newring')
            if self.TEM.post_a_m_n_rings(handle, team, ring):
                self.lggr.debug('%s has been added to the team.' % ring)
                flash('%s has been added to the team.' % ring, 'UI')
            else:
                self.lggr.error('%s already  exists in this team.' % ring)
                flash('%s already  exists in this team.' % ring, 'UI')

        if 'delring' in rqargs:
            ring = rqargs.get('delring')
            if self.TEM.delete_a_m_n_rings(handle, team, ring):
                self.lggr.debug('%s has been deleted from the team.' % ring)
                flash('%s has been deleted from the team.' % ring, 'UI')
            else:
                self.lggr.error('There was an issue deleting: %s' % ring)
                flash('There was an issue deleting: %s' % ring, 'UI')

        #d['redirect'] = '/'+handle+'/_teams/'+team
        d['redirect'] = url_for('avispa_rest.teams_a_m_n',
                                handle=handle,
                                team=team,
                                _external=True,
                                _scheme=URL_SCHEME)

        return d

    def post_a_m_n_p(self, handle, team, rqform):
        d = {}
        member = rqform.get('newmember')
        if self.TEM.post_a_m_n_members(handle, team, member):
            self.lggr.debug('%s has been added to the team.' % member)
            flash('%s has been added to the team.' % member, 'UI')
        else:
            self.lggr.debug('%s is already part of this team.' % member)
            flash('%s is already part of this team.' % member, 'UI')
        return d

    def delete_a_m_n_p_q(self, handle, team, member):
        '''Deletes a member from a team'''
        d = {}
        if self.TEM.delete_a_m_n_members(handle, team, member):
            self.lggr.debug('%s has been deleted from the team.' % member)
            flash('%s has been deleted from the team.' % member, 'UI')
        else:
            self.lggr.error('There was an issue deleting: %s' % member)
            flash('There was an issue deleting: %s' % member, 'UI')
        '''User Garbage collection'''
        # If a user no longer belongs to any team, it should be also released from the org

        # 1. Call TeamModel to check if this <member> exists in any other <team> in this <handle>
        memberships = self.TEM.get_a_m_all_p_q(handle, member)

        raise Exception

        # 2. If it doesn't, call the PeopleModel to delete this user
        if len(memberships) == 0:
            self.PEM.delete_a_p_q(handle, member)

        return d

    def post_a_m_n_r(self, handle, team, rqform):
        d = {}
        ring = rqform.get('newring')
        if self.TEM.post_a_m_n_rings(handle, team, ring):
            self.lggr.debug('%s has been added to the team.' % ring)
            flash('%s has been added to the team.' % ring, 'UI')
        else:
            self.lggr.error('%s already  exists in this team.' % ring)
            flash('%s already  exists in this team.' % ring, 'UI')
        return d

    def delete_a_m_n_r_b(self, handle, team, ring):
        d = {}
        if self.TEM.delete_a_m_n_rings(handle, team, ring):
            self.lggr.debug('%s has been deleted from the team.' % ring)
            flash('%s has been deleted from the team.' % ring, 'UI')
        else:
            self.lggr.error('There was an issue deleting: %s' % ring)
            flash('There was an issue deleting: %s' % ring, 'UI')
        return d

        #DELETE /a/b
    def delete_a_m_n(self, handle, team, *args, **kargs):
        #Will delete an existing team
        self.lggr.debug('Trying to delete the following team: %s' % team)

        d = {}

        peopleteams = self.MAM.is_org(handle)
        if peopleteams:
            #This is an organization

            for teamd in peopleteams['teams']:

                if teamd['teamname'] == team:

                    if self.MAM.delete_team(handle, team):
                        self.lggr.debug('You just deleted team %s' % team)
                        flash('You just deleted team %s' % team, 'UI')
                    else:
                        self.lggr.error(
                            'There was an error deleting team: %s' % team)
                        flash('There was an error deleting team: %s' % team,
                              'ER')

                    redirect = url_for('avispa_rest.teams_a_m',
                                       handle=handle,
                                       _external=True,
                                       _scheme=URL_SCHEME)

        else:
            #This is not an organization
            #redirect = '/'+current_user.id
            redirect = url_for('avispa_rest.home',
                               handle=handle,
                               _external=True,
                               _scheme=URL_SCHEME)

        d = {'redirect': redirect, 'status': 200}
        return d

    def get_a_m_n_settings(self, handle, team, *args, **kargs):

        #redirect = '/'+handle+'/_teams/'+team
        redirect = url_for('avispa_rest.teams_a_m_n',
                           handle=handle,
                           team=team,
                           _external=True,
                           _scheme=URL_SCHEME)

        d = {'redirect': redirect, 'status': 200}
        return d

    def put_rq_a_m_n_settings(self, handle, team, *args, **kargs):

        d = {}

        peopleteams = self.MAM.is_org(handle)
        if peopleteams:

            d['people'] = peopleteams['people']

            for teamd in peopleteams['teams']:
                #get the profilepic for this person

                if teamd['teamname'] == team:

                    if teamd['roles']:
                        if teamd['roles'][-1]['role'] == 'team_admin':
                            teamauth = 'RWX'
                        elif teamd['roles'][-1]['role'] == 'team_writer':
                            teamauth = 'RW'
                        elif teamd['roles'][-1]['role'] == 'team_reader':
                            teamauth = 'R'
                        else:
                            teamauth = ''

                        teamd['teamauth'] = teamauth

                    d['team'] = teamd
                    break

            d['template'] = 'avispa_rest/put_rq_a_m_n_settings.html'
        else:
            #This is a regular user

            #d['redirect'] = '/'+handle+'/_home'
            d['redirect'] = url_for('avispa_rest.home',
                                    handle=handle,
                                    _external=True,
                                    _scheme=URL_SCHEME)

        return d

    def put_a_m_n_settings(self, handle, team, rqform=None, *args, **kargs):
        d = {}
        p = {}

        if ('description' in rqform) or ('teamauth' in rqform):
            p['description'] = rqform.get('description')
            p['teamauth'] = rqform.get('teamauth')
            if self.TEM.put_a_m_n_settings(handle, team, p):
                self.lggr.debug('%s has been updated.' % team)
                flash('%s has been updated.' % team, 'UI')
            else:
                self.lggr.error('There was a problem updating team %s' % team)
                flash('There was a problem updating team %s' % team, 'ER')

        #d['redirect'] = '/'+handle+'/_teams/'+team
        d['redirect'] = url_for('avispa_rest.teams_a_m_n',
                                handle=handle,
                                team=team,
                                _external=True,
                                _scheme=URL_SCHEME)

        return d

    def get_a_m_n_invite(self, handle, team, *args, **kargs):

        #redirect = '/'+handle+'/_teams/'+team
        redirect = url_for('avispa_rest.teams_a_m_n',
                           handle=handle,
                           team=team,
                           _external=True,
                           _scheme=URL_SCHEME)

        d = {'redirect': redirect, 'status': 200}
        return d

    def put_rq_a_m_n_invite(self, handle, team, *args, **kargs):

        d = {}

        peopleteams = self.MAM.is_org(handle)
        if peopleteams:

            d['people'] = peopleteams['people']

            for teamd in peopleteams['teams']:
                #get the profilepic for this person

                if teamd['teamname'] == team:
                    d['team'] = teamd
                    break

        d['template'] = 'avispa_rest/put_rq_a_m_n_invite.html'

        return d

    def put_a_m_n_invite(self,
                         handle,
                         team,
                         rqurl=None,
                         rqform=None,
                         *args,
                         **kargs):
        d = {}

        self.EMM = EmailModel()
        collabraw = rqform.get('emails')
        valid_emails, invalid_emails = address.validate_list(collabraw,
                                                             as_tuple=True)

        self.lggr.debug('valid_emails:%s' % valid_emails)
        self.lggr.debug('invalid_emails:%s' % invalid_emails)

        #2. If it is an email, send ring subscription url/token

        o = urlparse.urlparse(rqurl)
        host_url = urlparse.urlunparse((o.scheme, o.netloc, '', '', '', ''))

        #2a PENDING
        # Subtract team object from org document
        peopleteams = self.MAM.is_org(handle)
        if peopleteams:

            for teamd in peopleteams['teams']:
                teamfound = False

                if teamd['teamname'] == team:
                    # This team actually exists in this org. You can continue with the invitations
                    teamfound = True
                    break

            if not teamfound:
                # This team doesnt exist. No invitation can be sent
                #d['redirect'] = '/'+handle+'/_teams/'+team
                d['redirect'] = url_for('avispa_rest.teams_a_m_n',
                                        handle=handle,
                                        team=team,
                                        _external=True,
                                        _scheme=URL_SCHEME)
                return d

            # teamd carries the team object
        #Try to convert invalid_emails (myringIDs) into valid_emails

        for invite_handle in invalid_emails:
            user_doc = self.MAM.select_user_doc_view('auth/userbyhandle',
                                                     invite_handle)
            if user_doc:
                if user_doc['email'] not in valid_emails:
                    valid_emails.append(user_doc['email'])

        for email in valid_emails:

            email = str(email)

            invite = {}
            invite['email'] = email
            invite['count'] = 1
            invite['team'] = team
            invite['token'] = flask_bcrypt.generate_password_hash(
                email + str(random.randint(0, 9999)))
            invite['lasttime'] = str(datetime.now())
            invite['author'] = current_user.id

            user_doc = self.MAM.select_user_doc_view('auth/userbyemail', email)

            if user_doc:
                #You are inviting an existing myRing user
                existinguser = True

            else:
                #You are inviting a soon to be myRing user
                existinguser = False

            token = invite['token']
            to = email
            subject = handle + " has invited you to collaborate in the following team : " + team
            # https://avispa.myring.io/_register?h=cdmit&t=staff&k=11111&[email protected]
            content = "Click here to start working with this team: " + host_url + "/_register?h=" + handle + "&t=" + team + "&k=" + token + "&e=" + email
            self.lggr.debug('%s,%s,%s' % (to, subject, content))

            if self.EMM.send_one_email(to, subject, content):
                flash("Invitation email sent.", 'UI')
                self.MAM.append_to_user_field(handle, 'invitations', invite)
            else:
                flash("Invitation email failed.", 'UI')

        #d['redirect'] = '/'+handle+'/_teams/'+team
        d['redirect'] = url_for('avispa_rest.teams_a_m_n',
                                handle=handle,
                                team=team,
                                _external=True,
                                _scheme=URL_SCHEME)

        return d
Exemple #3
0
class Upload:
    def __init__(self, handle):

        self.handle = handle

        self.rs_status = ''
        self.officialsizes = {
            'r100': 100,
            'r240': 240,
            'r320': 320,
            'r500': 500,
            'r640': 640,
            'r800': 800,
            'r1024': 1024
        }
        self.thumbnailsizes = {'t75': 75, 't150': 150}
        self.allowed_formats = set(
            ['txt', 'pdf', 'png', 'jpg', 'JPG', 'jpeg', 'gif'])

        logger = logging.getLogger('Avispa')
        self.lggr = AvispaLoggerAdapter(logger, {
            'tid': g.get('tid', None),
            'ip': g.get('ip', None)
        })

    def blob_from_s3(self, bucket, id):

        #Subtract original from s3 and put it in memory
        image_binary = ''

        return image_binary

    def blob_from_file(self, file):
        #Load the image blob
        print(file)
        file.seek(0)
        image_binary = file.read()

        return image_binary

    #DRIVER FUNCTION
    def do_upload(self, image_binary):

        response = {}
        image_sizes = []

        #Load the image
        with Image(blob=image_binary) as img:

            #Prepare image components
            imgid = self._generate_imgid()
            filename = imgid + '.jpg'

            #Image analysis
            longside, shortside, orientation = self._img_orientation(
                img.width, img.height)

            #Constrain original if needed
            if longside > 2000:
                img = self._img_resize(img, 2000, orientation)

            path = '%s/%s' % (self.handle, 'o')
            self._s3_save(img, path, filename)
            m = self._generate_metadata(img.width, img.height, 'o')
            image_sizes.append(m)

            #Save scaled down versions and thumbnail
            #Plan of action
            regular_wo, thumb_wo = self._image_workorder(longside, shortside)

            #Scaled down versions
            for wo in regular_wo:
                with img.clone() as i:
                    ii = self._img_resize(i, regular_wo[wo], orientation)
                    path = '%s/%s' % (self.handle, wo)

                    if STORE_MODE == 'LOCAL':
                        self._local_save(i, path, filename)
                    elif STORE_MODE == 'S3':
                        self._s3_save(i, path, filename)

                    m = self._generate_metadata(ii.width, ii.height, wo)
                    image_sizes.append(m)

            #Thumbnail versions
            for wo in thumb_wo:
                with img.clone() as i:
                    ii = self._img_resize(i, thumb_wo[wo], orientation)
                    iii = self._img_thumbcrop(ii, orientation)
                    path = '%s/%s' % (self.handle, wo)
                    self._file_save(i, path, filename)
                    m = self._generate_metadata(iii.width, iii.height, wo)
                    image_sizes.append(m)

        response['status'] = self.rs_status
        response['imgid'] = imgid
        response['imgsizes'] = image_sizes

        return response

    #DRIVER FUNCTION
    def do_copy(self, from_handle, to_handle, imgid):

        #Pull file from S3 bucket
        f = self._pull_file_from_s3(origin, targetimgid)

        return response

    def _generate_metadata(self, width, height, sizename):

        multiplied = {}
        multiplied['mime-type'] = 'image/jpeg'
        multiplied['extension'] = 'jpg'
        multiplied['width'] = width
        multiplied['height'] = height
        multiplied['sizename'] = sizename
        multiplied['unit'] = 'pixel'
        #self.lggr.debug(multiplied)

        return multiplied

    def check_extension(self, filename):

        #TO-DO This a very soft check. Please implement Real Format Check

        if not '.' in filename and filename.rsplit(
                '.', 1)[1] in self.allowed_formats:
            self.lggr.error('Error: This file format is not allowed: ' +
                            str(filename))
            flash(u'This file format is not allowed: ' + str(filename), 'ER')
            self.rs_status = '415'
            return False

        return True

    def _pull_file_from_s3(self, handle, imgid):

        pass

        #1. Subtract image from S3

        #2. Put it in self.f

    def _generate_imgid(self):

        return str(random.randrange(1000000000, 9999999999))

    def _image_workorder(self, longside, shortside):

        regular_wo = {}
        thumb_wo = {}

        for r in self.officialsizes:
            if longside >= self.officialsizes[r]:
                regular_wo[r] = self.officialsizes[r]

        for t in self.thumbnailsizes:
            if shortside >= self.thumbnailsizes[t]:
                thumb_wo[t] = self.thumbnailsizes[t]

        return (regular_wo, thumb_wo)

    def _img_orientation(self, width, height):

        if width > height:

            longside = width
            shortside = height
            orientation = "landscape"

        if width < height:

            longside = height
            shortside = width
            orientation = "portrait"

        if width == height:

            longside = height
            shortside = width
            orientation = "square"

        return longside, shortside, orientation

    def _img_resize(self, img, mainside, orientation):

        if orientation == 'portrait':
            img.transform(resize='x' + str(mainside))  #Height based
            #img.resize(height=int(mainside))
        elif orientation == 'landscape':
            img.transform(resize=str(mainside))  #Width based
            #img.resize(width=int(mainside))
            #img.transform(resize=str(mainside))
        elif orientation == 'square':
            img.transform(resize=str(mainside))  #Width based
            #img.resize(width=int(mainside))

        return img

    def _img_thumbcrop(self, img, orientation):
        offset = abs(img.width - img.height) / 2  #This centers the crop
        if orientation == 'portrait':
            img.crop(0, offset, width=img.width, height=img.width)
        if orientation == 'landscape':
            img.crop(offset, 0, width=img.height, height=img.height)

        return img

    def _file_save(self, file, path, filename):

        self._s3_save(file, path, filename)

    def _s3_save(self, file, path, filename):
        self.lggr.info("Storing image in S3: %s/%s" % (path, filename))
        conn = boto.connect_s3(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
        bucket = conn.get_bucket(IMAGE_BUCKET_NAME)
        #k = Key(bucket)
        k = boto.s3.key.Key(bucket)
        k.key = '%s/%s' % (path, filename)
        print(k)
        print(k.key)
        print(file)

        fl = cStringIO.StringIO()
        file.save(fl)

        #print fl
        fl.seek(0)

        k.set_contents_from_file(fl)
        k.set_acl('public-read')
        #AttributeError: 'Image' object has no attribute 'tell'

        #b = fl.read()
        #print(b)
        #k.set_contents_from_string(b)

        return True

    def check_upload_path(self, path):
        pass

    def check_filename(self):
        pass

    def set_max_filesize(self):
        pass

    def set_max_filename(self):
        pass

    def set_max_width(self):
        pass

    def set_max_height(self):
        pass

    def set_allowed_types(self, types):
        pass

    def set_image_properties(self):
        pass

    def set_xss_clean(self):
        pass

    def is_image(self):
        pass

    def is_allowed_filetype(self):
        pass

    def is_allowed_filesize(self):
        pass

    def is_allowed_dimensions(self):
        pass

    def validate_upload_path(self):
        pass

    def get_extension(self, filename):
        pass

    def clean_file_name(self, filename):
        pass

    def limit_filename_length(self, filename, length):
        pass

    def do_xss_clean(self):
        pass

    def set_error(self, msg):
        pass

    def display_errors(self):
        pass

    def mime_types(self, mime):
        pass

    def _prep_filename(self, filename):
        pass

    def _file_mime_type(self, file):
        pass
class PeopleController:

    def __init__(self,tid=None,ip=None):
        
        logger = logging.getLogger('Avispa')
        self.lggr = AvispaLoggerAdapter(logger, {'tid': tid,'ip': ip})
               
        self.MAM = MainModel(tid=tid,ip=ip)
        self.PEM = PeopleModel(tid=tid,ip=ip)
        self.TEM = TeamsModel(tid=tid,ip=ip)
        
    # GET/a
    def get_a_p(self,handle,person,*args,**kargs):

        d = {}

        peopleteams = self.MAM.is_org(handle) 
        if peopleteams: 
            #This is an organization         
            d['peoplelist'] = peopleteams['people'] 
            d['peoplelistlen'] = len(peopleteams['people'])
            
            for person in peopleteams['people']:
                #get the profilepic for this person
                person_user_doc = self.MAM.select_user_doc_view('auth/userbasic',person['handle'])
                if person_user_doc:
                    person['thumbnail'] = person_user_doc['profilepic']
                    person['memberships'] = self.TEM.get_a_m_all_p_q(handle,person['handle'])
                

            
            d['template'] = 'avispa_rest/get_a_p.html'
        else:
            #This is a regular user
         
            #d['redirect'] = '/'+handle+'/_home'
            d['redirect'] = url_for('avispa_rest.home',
                                     handle=handle,
                                     _external=True,
                                     _scheme=URL_SCHEME) 
     
        return d


        # POST/a
    def post_a_p(self,handle,person,rqform=None,*args,**kargs):

        #We need to recover from request as it doesn't come via URL
        person = rqform.get('newperson')

        #Check if the user exists or not
        if self.MAM.user_exists(person):

            result = self.PEM.post_a_p(handle,person)
                
            if result:
                self.lggr.debug('Awesome , you just added %s to the organization'%person)
                #msg = 'Item put with id: '+idx
                flash('Awesome , you just added %s to the organization'%person,'UI')

            else:
                self.lggr.error('Awesome , you just added %s to the organization'%person)
                flash('There was an error adding %s to the organization.'%s,'ER')

        else:
            self.lggr.debug('%s is not a MyRing user. Please create it first.'%person)
            flash('%s is not a MyRing user. Please create it first.'%person,'ER')

  
        #redirect = '/'+handle+'/_people'
        redirect = url_for('avispa_rest.people_a_p',
                                     handle=handle,
                                     _external=True,
                                     _scheme=URL_SCHEME) 

        d = {'redirect': redirect, 'status':200}
        return d


        #DELETE /a/b
    def delete_a_p_q(self,handle,person,*args,**kargs):
        #Will delete an existing person
        self.lggr.debug('Trying to delete the following person: %s'%person)

        #Check if the user exists or not
        if self.MAM.user_exists(person):

            result = self.PEM.delete_a_p_q(handle,person)
                
            if result:
                self.lggr.debug('You just deleted %s from the organization'%person)
                flash('You just deleted %s from the organization'%person,'UI')

            else:
                self.lggr.error('There was an error deleting %s from the organization.'%person)
                flash('There was an error deleting %s from the organization.'%person,'ER')

        else:
            self.lggr.debug('%s is not a MyRing user.'%person)
            flash('%s is not a MyRing user.'%person,'ER')


        
        #redirect = '/'+handle+'/_people'
        redirect = url_for('avispa_rest.people_a_p',
                                     handle=handle,
                                     _external=True,
                                     _scheme=URL_SCHEME) 

        d = {'redirect': redirect, 'status':200}
        return d
Exemple #5
0
class User(UserMixin):
    def __init__(self,
                 username=None,
                 email=None,
                 passhash=None,
                 owner=None,
                 location=None,
                 url=None,
                 profilepic=None,
                 name=None,
                 isOrg=False,
                 active=True,
                 id=None,
                 onlogin=False,
                 about=None,
                 tid=None,
                 ip=None):

        logger = logging.getLogger('Avispa')
        self.lggr = AvispaLoggerAdapter(logger, {'tid': tid, 'ip': ip})

        self.lggr.debug('__init__()')

        self.username = username
        self.email = email
        self.location = location
        self.passhash = passhash
        self.about = about
        self.url = url
        self.profilepic = profilepic
        self.name = name
        self.isOrg = isOrg
        self.active = active
        self.isAdmin = False
        self.id = None
        self.onlogin = onlogin

        if owner:
            self.owner = owner
        else:
            self.owner = username

        if isinstance(self.location, basestring):
            self.location = self.location.lower()

        if isinstance(self.email, basestring):
            self.email = self.email.lower()

        if isinstance(self.username, basestring):
            self.usernme = self.username.lower()

        self.ATM = AuthModel()

    def set_user(self):

        user = {}
        # Defaults coming via self

        user['username'] = self.username
        user['email'] = self.email
        user['location'] = self.location
        user['owner'] = self.owner
        user['location'] = self.location
        user['url'] = self.url
        user['profilepic'] = self.profilepic
        user['name'] = self.name
        user['passhash'] = self.passhash
        user['onlogin'] = self.onlogin
        user['about'] = self.about

        self.lggr.info(user)

        if not self.isOrg:
            self.lggr.info('is an Org')
            #You are registering a regular User
            if self.ATM.saas_create_user(user):
                self.lggr.info("new user id = %s " % user['username'])
                return user['username']
            else:
                return False
        else:
            self.lggr.info('is NOT an Org')
            #You are registering an Organization
            if self.ATM.saas_create_orguser(user):
                self.lggr.info("new organization id = %s " % user['username'])
                return user['username']
            else:
                return False

    def set_password_key(self, key):

        self.lggr.info('set_password_key:')
        self.lggr.info(self.id)

        return self.ATM.saas_create_password_key(self.id, key)

    def set_password(self, passhash):

        self.lggr.info('set_password:'******'value']['email']
                self.location = dbUser['value']['location']
                self.active = dbUser['value']['is_active']
                self.password = dbUser['value']['passhash']
                self.id = dbUser['value']['_id']
                return self
            else:
                return None
        except:
            self.lggr.error("Notice: UnExpected error :",
                            sys.exc_info()[0],
                            sys.exc_info()[1])
            self.lggr.error("there was an error")
            return None

    def get_user(self):

        #raise Exception ('stop here')

        try:

            if self.email:
                self.lggr.debug('self.email:' + self.email)
                dbUser = self.ATM.userdb_get_user_by_email(self.email)
            elif self.username:
                self.lggr.info('START AUTHENTICATION:' + self.username)
                dbUser = self.ATM.userdb_get_user_by_handle(self.username)
            else:
                return None

            if dbUser:

                self.lggr.info("END AUTHENTICATION:%s" %
                               dbUser['value']['name'])

                self.name = dbUser['value']['name']
                self.email = dbUser['value']['email']
                self.url = dbUser['value']['url']
                self.profilepic = dbUser['value']['profilepic']
                self.location = dbUser['value']['location']
                self.about = dbUser['value']['about']
                self.onlogin = dbUser['value']['onlogin']
                self.active = dbUser['value']['is_active']
                self.password = dbUser['value']['passhash']
                self.id = dbUser['value']['_id']
                return self
            else:
                self.lggr.error('User: not found')
                return None
        except (KeyError):
            self.lggr.error("Notice: UnExpected error :",
                            sys.exc_info()[0],
                            sys.exc_info()[1])
            self.lggr.error(
                "there was an error, we need to repair the user_document")

            preconditions = [
                'name', 'email', 'url', 'profilepic', 'location', 'about',
                'onlogin'
            ]
            repaired = False
            for element_to_add in preconditions:
                MAM = MainModel()
                if MAM.repair_user_doc(element_to_add, dbUser['value']['_id']):
                    repaired = True
                    self.lggr.info('Repaired ' + element_to_add + '. ')
                    #flash('Repaired '+element_to_add+'. ')

            #Let's try again
            if repaired:

                if self.email:
                    dbUser = self.ATM.userdb_get_user_by_email(self.email)
                elif self.username:
                    dbUser = self.ATM.userdb_get_user_by_handle(self.username)

                if dbUser:

                    self.name = dbUser['value']['name']
                    self.email = dbUser['value']['email']
                    self.url = dbUser['value']['url']
                    self.profilepic = dbUser['value']['profilepic']
                    self.location = dbUser['value']['location']
                    self.about = dbUser['value']['about']
                    self.active = dbUser['value']['is_active']
                    self.password = dbUser['value']['passhash']
                    self.id = dbUser['value']['_id']
                    return self
                else:
                    return False

            else:
                return False

    def update_user_profile(self, request):

        dbUser = self.ATM.userdb_get_user_by_handle(self.username)
        changes = {}

        if dbUser:
            if request.form.get('profilepic') != dbUser['value']['profilepic']:
                self.lggr.info('profilepic changed!')
                changes['profilepic'] = request.form.get('profilepic')

            if request.form.get('name') != dbUser['value']['name']:
                self.lggr.info('name changed!')
                changes['name'] = request.form.get('name')
                mp_change = True

            if request.form.get('url') != dbUser['value']['url']:
                self.lggr.info('url changed!')
                changes['url'] = request.form.get('url')

            if request.form.get('location') != dbUser['value']['location']:
                self.lggr.info('location changed!')
                changes['location'] = request.form.get('location')

            if request.form.get('about') != dbUser['value']['about']:
                self.lggr.info('about changed!')
                changes['about'] = request.form.get('about')

            if request.form.get('onlogin') != dbUser['value']['onlogin']:
                self.lggr.info('onlogin changed!')
                changes['onlogin'] = request.form.get('onlogin')

        return self.ATM.saas_update_user_profile(self.username, changes)

    def is_valid_password_key(self, email, key):

        try:
            #self.lggr.info('flag1')
            dbUser = self.ATM.userdb_get_user_by_email(email)
            #self.lggr.info('flag2')
            #self.lggr.info(dbUser)
            if dbUser['value']['new_password_key'] == key:
                return True
            else:
                return False
        except:
            self.lggr.error("Notice: UnExpected error :",
                            sys.exc_info()[0],
                            sys.exc_info()[1])
            self.lggr.error("There was an error validating the Key")
            return False

    def is_active(self):
        return self.active

    def is_authenticated(self):
        return True

    def is_anonymous(self):
        return False
Exemple #6
0
class CollectionsModel:
    def __init__(self, tid=None, ip=None):

        logger = logging.getLogger('Avispa')
        self.lggr = AvispaLoggerAdapter(logger, {'tid': tid, 'ip': ip})

        self.MAM = MainModel(tid=tid, ip=ip)

    #COLLECTIONSMODEL
    def get_a_x(self, handle):

        # Returns list of collections

        try:
            doc = self.MAM.select_user(handle)
            collections = doc['collections']
            rings = doc['rings']

            # 1. Here we need to call the DB again but now to get which

            validring = {}
            ringorigins = {}
            ringcounts = {}

            for ring in rings:

                if not 'deleted' in ring:
                    ringname = str(ring['ringname'])

                    if 'origin' in ring:
                        ringorigin = str(ring['origin'])
                    else:
                        ringorigin = str(handle)

                    ringorigins[ringname] = ringorigin
                    ringcounts[ringname] = ring['count']

            #raise Exception('debug')
            self.lggr.info(ringcounts)

            for coll in collections:
                for ring in coll['rings']:
                    if ring['ringname'] in ringcounts:
                        ring['count'] = ringcounts[ring['ringname']]
                    if ring['ringname'] in ringorigins:
                        ring['ringorigin'] = ringorigins[ring['ringname']]

            return collections

        except (ResourceNotFound, TypeError) as e:
            self.lggr.error("Notice: Expected error:%s,%s" %
                            (sys.exc_info()[0], sys.exc_info()[1]))

        return False

    #COLLECTIONSMODEL
    def post_a_x(self, handle, collectiond):
        '''Creates new collection'''

        doc = self.MAM.select_user(handle)
        if 'description' not in collectiond:
            collectiond['description'] = ''

        newcollection = {
            'collectionname': str(collectiond['name']),
            'collectiondescription': str(collectiond['description']),
            'version': str(collectiond['version']),
            'rings': collectiond['ringlist'],
            'added': str(datetime.now())
        }

        doc['collections'].append(newcollection)
        self.MAM.post_user_doc(doc)
        return True

    #COLLECTIONSMODEL
    def get_a_x_y(self, handle, collection):
        #Not used directly, but used by put_rq_a_x_y to return collection details
        #Returns just one collection

        try:
            doc = self.MAM.select_user(handle)

            collections = doc['collections']
            rings = doc['rings']

            validring = {}

            for ring in rings:
                if not 'deleted' in ring:
                    ringname = str(ring['ringname'])
                    validring[ringname] = ring['count']

            for coll in collections:
                #coll['valid'] = True
                if coll['collectionname'] == collection:

                    #coll['valid'] = True
                    for ring in coll['rings']:
                        if ring['ringname'] in validring:
                            ring['count'] = validring[ring['ringname']]
                        else:
                            pass
                            #InValid Collection, at least one of its rings is marked as deleted
                            #coll['valid'] = False

                    return coll

            return False

        except (ResourceNotFound, TypeError) as e:
            self.lggr.error("Notice: Expected error:%s,%s" %
                            (sys.exc_info()[0], sys.exc_info()[1]))

    #COLLECTIONSMODEL
    def put_a_x_y(self, handle, collectiond):

        doc = self.MAM.select_user(handle)

        newcollection = {
            'collectionname': str(collectiond['name']),
            'collectiondescription': str(collectiond['description']),
            'version': str(collectiond['version']),
            'rings': collectiond['ringlist'],
            'added': str(datetime.now())
        }

        i = 0
        for coll in doc['collections']:

            if coll['collectionname'] == newcollection['collectionname']:
                #This is a match. This is what we need to replace with incoming document
                doc['collections'][i] = newcollection

            i = i + 1

        self.MAM.post_user_doc(doc)
        return True

        #COLLECTIONSMODEL
    def patch_a_x_y(self, handle, collection, collectiond):

        doc = self.MAM.select_user(handle)

        path = {}
        if 'name' in collectiond:
            patch['collectionname'] = str(collectiond['name'])
        if 'description' in collectiond:
            patch['collectiondescription'] = str(collectiond['description'])
        if 'version' in collectiond:
            patch['version'] = str(collectiond['version'])
        if 'rings' in collectiond:
            patch['rings'] = collectiond['ringlist']

        i = 0
        for coll in doc['collections']:

            if coll['collectionname'] == collection:

                for p in patch:
                    doc['collections'][i][p] = patch[p]

            i = i + 1

        self.MAM.post_user_doc(doc)
        return True

    def add_ring_to_collection(self, handle, collection, ringd):

        doc = self.MAM.select_user(handle)
        for coll in doc['collections']:
            if coll['collectionname'] == collection:
                coll['rings'].append(ringd)

        self.lggr.info('Ring added to collection:', doc)
        self.MAM.post_user_doc(doc)
        return True

    #COLLECTIONSMODEL
    def delete_a_x_y(self, handle, collection):

        doc = self.MAM.select_user(handle)

        i = 0
        for coll in doc['collections']:
            if coll['collectionname'] == collection:
                del doc['collections'][i]

            i = i + 1

        self.MAM.post_user_doc(doc)
        return True