コード例 #1
0
def auth_meta_mw(resp):
    """
    Callback for meta.wikimedia.org to send us authentication results.
    This is responsible for fetching existing users or creating new ones.
    If a new user is created, they get the default role of GUEST and
    an email or username to match their details from the OAuth provider.
    """
    if resp is None:
        flash('You need to grant the app permissions in order to login.', 'error')
        return redirect(url_for('login'))
    
    session['access_token'] = (
        resp['oauth_token'],
        resp['oauth_token_secret']
    )
    
    try:
        identify_token_encoded = meta_mw.post(
            app.config['META_MW_BASE_URL'] + app.config['META_MW_IDENTIFY_URI'],
        ).data
        identify_token = process_mw_jwt(identify_token_encoded)
        
        username = identify_token['username']
        userid = identify_token['sub']
        
        db_session = db.get_session()
        user = None
        try:
            user = db_session.query(UserStore).filter_by(meta_mw_id=userid).one()
        
        except NoResultFound:
            user = UserStore(
                username=username,
                meta_mw_id=userid,
                role=UserRole.GUEST,
            )
            db_session.add(user)
            db_session.commit()
        
        except MultipleResultsFound:
            db_session.close()
            return 'Multiple users found with your id!!! Contact Administrator'
        
        user.login(db_session)
        try:
            if login_user(user):
                user.detach_from(db_session)
                redirect_to = session.get('next') or url_for('home_index')
                redirect_to = urllib2.unquote(redirect_to)
                return redirect(redirect_to)
        finally:
            db_session.close()
    
    except Exception, e:
        flash('Access to this application was revoked. Please re-login!')
        app.logger.exception(str(e))
        return redirect(url_for('login'))
コード例 #2
0
def auth_google(resp):
    """
    Callback for Google to send us authentication results.
    This is responsible for fetching existing users or creating new ones.
    If a new user is created, they get the default role of GUEST and
    an email or username to match their details from the OAuth provider.
    """
    if resp is None and request.args.get('error') == 'access_denied':
        flash('You need to grant the app permissions in order to login.', 'error')
        return redirect(url_for('login'))
    
    access_token = resp['access_token'] or request.args.get('code')
    if access_token:
        session['access_token'] = access_token, ''
        r = requests.get(app.config['GOOGLE_USERINFO_URI'], headers={
            'Authorization': 'OAuth ' + access_token
        })
        if r.ok:
            userinfo = json.loads(r.text)
            email = userinfo['email']
            id = userinfo['id']
            
            db_session = db.get_session()
            user = None
            try:
                user = db_session.query(UserStore).filter_by(google_id=id).one()
            
            except NoResultFound:
                try:
                    user = UserStore(
                        email=email,
                        google_id=id,
                        role=UserRole.GUEST,
                    )
                    db_session.add(user)
                    db_session.commit()
                except Exception:
                    db_session.rollback()
                    raise
            
            except MultipleResultsFound:
                return 'Multiple users found with your id!!! Contact Administrator'
            
            user.login(db_session)
            if login_user(user):
                user.detach_from(db_session)
                redirect_to = session.get('next') or url_for('home_index')
                redirect_to = urllib2.unquote(redirect_to)
                return redirect(redirect_to)
    
    flash('Was not allowed to authenticate you with Google.', 'error')
    return redirect(url_for('login'))
コード例 #3
0
def auth_meta_mw():
    """
    Callback for meta.wikimedia.org to send us authentication results.
    This is responsible for fetching existing users or creating new ones.
    If a new user is created, they get the default role of GUEST and
    an email or username to match their details from the OAuth provider.
    """
    try:
        handshaker = make_handshaker_mw()
        raw_req_token = session['request_token']
        request_token = RequestToken(key=raw_req_token[0], secret=raw_req_token[1])
        access_token = handshaker.complete(request_token, request.query_string)
        session['access_token'] = access_token

        identity = handshaker.identify(access_token)
        username = identity['username']
        userid = identity['sub']

        db_session = db.get_session()
        user = None
        try:
            user = db_session.query(UserStore).filter_by(meta_mw_id=userid).one()

        except NoResultFound:
            try:
                user = UserStore(
                    username=username,
                    meta_mw_id=userid,
                    role=UserRole.GUEST,
                )
                db_session.add(user)
                db_session.commit()
            except Exception:
                db_session.rollback()
                raise

        except MultipleResultsFound:
            flash('Multiple users found with your id!!! Contact Administrator', 'error')
            return redirect(url_for('login'))

        user.login(db_session)
        if login_user(user):
            user.detach_from(db_session)
            del session['request_token']

    except Exception:
        flash('You need to grant the app permissions in order to login.', 'error')
        app.logger.exception(traceback.format_exc())
        return redirect(url_for('login'))

    redirect_to = session.get('next') or url_for('home_index')
    return redirect(urllib2.unquote(redirect_to))
コード例 #4
0
    def test_delete_cohort_owner_has_viewer(self):
        viewer_user = UserStore()
        self.session.add(viewer_user)
        self.session.commit()

        viewer_cohort_user = CohortUserStore(user_id=viewer_user.id,
                                             cohort_id=self.cohort.id,
                                             role=CohortUserRole.VIEWER)
        self.session.add(viewer_cohort_user)
        self.session.commit()
        response = self.app.post('/cohorts/delete/{0}'.format(self.cohort.id))

        assert_equal(response.status_code, 200)
        assert_true(response.data.find('isRedirect') >= 0)
        assert_true(response.data.find('/cohorts/') >= 0)
        cohort_id = self.cohort.id
        self.session.commit()

        # Check that all relevant rows are deleted
        cwu = self.session.query(CohortWikiUserStore) \
            .filter(CohortWikiUserStore.cohort_id == cohort_id) \
            .first()
        assert_equal(cwu, None)
        cu = self.session.query(CohortUserStore) \
            .filter(CohortUserStore.cohort_id == cohort_id) \
            .first()
        assert_equal(cu, None)
        wu = self.session.query(WikiUserStore) \
            .filter(WikiUserStore.validating_cohort == cohort_id) \
            .first()
        assert_equal(wu, None)
        c = self.session.query(CohortStore).get(cohort_id)
        assert_equal(c, None)
コード例 #5
0
 def create_wiki_cohort(self, project=mediawiki_project):
     """
     Creates a wiki cohort (spans a whole project)
     and an owner for the cohort
     """
     # cohort data
     basic_wiki_cohort = CohortStore(name='{0}-wiki-cohort'.format(project),
                                     enabled=True,
                                     public=False,
                                     default_project=project,
                                     class_name='WikiCohort'
                                     )
     self.session.add(basic_wiki_cohort)
     self.session.commit()
     self.basic_wiki_cohort = basic_wiki_cohort
     
     owner = UserStore(username='******', email='*****@*****.**')
     self.session.add(owner)
     self.session.commit()
     self.owner_user_id = owner.id
     
     cohort_user = CohortUserStore(
         user_id=self.owner_user_id,
         cohort_id=basic_wiki_cohort.id,
         role=CohortUserRole.OWNER
     )
     self.session.add(cohort_user)
     self.session.commit()
     self.basic_wiki_cohort_owner = cohort_user
コード例 #6
0
    def setUp(self):
        QueueDatabaseTest.setUp(self)
        self.mwSession.add(MediawikiUser(user_name='Editor test-specific-0'))
        self.mwSession.add(MediawikiUser(user_name='Editor test-specific-1'))
        self.mwSession.commit()

        owner_user = UserStore()
        self.session.add(owner_user)
        self.session.commit()
        self.owner_user_id = owner_user.id
コード例 #7
0
def load_user(user_id):
    """
    Callback required by Flask-Login.  Gets the User object from the database.
    """
    db_session = db.get_session()
    try:
        user = UserStore.get(db_session, user_id)
    finally:
        db_session.close()
    return user
コード例 #8
0
def auth_meta_mw():
    """
    Callback for meta.wikimedia.org to send us authentication results.
    This is responsible for fetching existing users or creating new ones.
    If a new user is created, they get the default role of GUEST and
    an email or username to match their details from the OAuth provider.
    """
    try:
        handshaker = make_handshaker_mw()
        raw_req_token = session['request_token']
        request_token = RequestToken(key=raw_req_token[0],
                                     secret=raw_req_token[1])
        access_token = handshaker.complete(request_token, request.query_string)
        session['access_token'] = access_token

        identity = handshaker.identify(access_token)
        username = identity['username']
        userid = identity['sub']

        db_session = db.get_session()
        user = None
        try:
            user = db_session.query(UserStore).filter_by(
                meta_mw_id=userid).one()

        except NoResultFound:
            try:
                user = UserStore(
                    username=username,
                    meta_mw_id=userid,
                    role=UserRole.GUEST,
                )
                db_session.add(user)
                db_session.commit()
            except:
                db_session.rollback()
                raise

        except MultipleResultsFound:
            flash('Multiple users found with your id!!! Contact Administrator',
                  'error')
            return redirect(url_for('login'))

        user.login(db_session)
        if login_user(user):
            user.detach_from(db_session)
            del session['request_token']

    except Exception:
        flash('You need to grant the app permissions in order to login.',
              'error')
        app.logger.exception(traceback.format_exc())
        return redirect(url_for('login'))

    redirect_to = session.get('next') or url_for('home_index')
    return redirect(urllib2.unquote(redirect_to))
コード例 #9
0
def auth_google(resp):
    """
    Callback for Google to send us authentication results.
    This is responsible for fetching existing users or creating new ones.
    If a new user is created, they get the default role of GUEST and
    an email or username to match their details from the OAuth provider.
    """
    if resp is None and request.args.get('error') == 'access_denied':
        flash('You need to grant the app permissions in order to login.',
              'error')
        return redirect(url_for('login'))

    access_token = resp['access_token'] or request.args.get('code')
    if access_token:
        session['access_token'] = access_token, ''
        r = requests.get(app.config['GOOGLE_USERINFO_URI'],
                         headers={'Authorization': 'OAuth ' + access_token})
        if r.ok:
            userinfo = json.loads(r.text)
            email = userinfo['email']
            id = userinfo['id']

            db_session = db.get_session()
            user = None
            try:
                user = db_session.query(UserStore).filter_by(
                    google_id=id).one()

            except NoResultFound:
                try:
                    user = UserStore(
                        email=email,
                        google_id=id,
                        role=UserRole.GUEST,
                    )
                    db_session.add(user)
                    db_session.commit()
                except:
                    db_session.rollback()
                    raise

            except MultipleResultsFound:
                return 'Multiple users found with your id!!! Contact Administrator'

            user.login(db_session)
            if login_user(user):
                user.detach_from(db_session)
                redirect_to = session.get('next') or url_for('home_index')
                redirect_to = urllib2.unquote(redirect_to)
                return redirect(redirect_to)

    flash('Was not allowed to authenticate you with Google.', 'error')
    return redirect(url_for('login'))
コード例 #10
0
    def validate_cohort(self, filename):
        '''
        Given a cohort file with usernames all users but one should validate.
        It will mingle the name of the 1st user.

        Parameters:
            filename : Name of a file that contains a cohort with user names
                       test will search for file in tests/static/public folder
        '''

        names = self.create_users_from_file(filename)

        # establish ownership for this cohort otherwise things do not work
        owner_user = UserStore(username='******',
                               email='*****@*****.**')
        self.session.add(owner_user)
        self.session.commit()

        # creating here kind of like a cohortupload mock
        # flask forms do not lend themselves to easy mocking
        cohort_upload = MockCohort()
        cohort_upload.name = MockCohort()
        cohort_upload.name.data = 'testing-cohort'
        cohort_upload.description = MockCohort()
        cohort_upload.description.data = 'testing-cohort'
        cohort_upload.project = MockCohort()
        cohort_upload.project.data = mediawiki_project
        cohort_upload.validate_as_user_ids = MockCohort()
        cohort_upload.validate_as_user_ids.data = False
        cohort_upload.records = []

        # mingle the name of the first user user
        not_valid_editor_name = 'Mr Not Valid'
        names[0] = not_valid_editor_name

        for name in names:
            cohort_upload.records.append({
                'raw_id_or_name': name,
                'project': mediawiki_project,
            })

        # TODO clear session situation?
        # all operations need to happen on the scope of the same session
        # but this session passed in is going to be closed
        vc = ValidateCohort.from_upload(cohort_upload, owner_user.id,
                                        self.session)

        cohort = self.session.query(CohortStore).first()
        self.session.commit()
        vc.validate_records(self.session, cohort)

        # now we need to assert that all users but the first one validate
        assert_equal(
            len(
                self.session.query(WikiUserStore).filter(
                    WikiUserStore.validating_cohort == cohort.id).filter(
                        WikiUserStore.valid).all()),
            len(names) - 1)

        # retrieve the user that should not be valid, make sure it is not indeed
        wiki_user = self.session.query(WikiUserStore)\
            .filter(WikiUserStore.validating_cohort == cohort.id)\
            .filter(WikiUserStore.raw_id_or_name == not_valid_editor_name).one()

        assert_false(wiki_user.valid)
コード例 #11
0
    def create_test_data(
        self,
        name='test-specific',
        editor_count=0,
        user_registrations=20130101000000,
        revisions_per_editor=0,
        revision_timestamps=None,
        revision_lengths=None,
        page_count=0,
        page_timestamps=None,
        page_namespaces=None,
        page_creator_index=None,
        owner_user_id=None,
        page_touched=20130102000000,
        user_email_token_expires=20200101000000,
        create_cohort=True,
        mw_session=None,
    ):
        """
        Internal multi-purpose data creator.
        Creates a set of users and, if `name` is specified, wraps them in a cohort.
        """
        if revision_timestamps is None:
            revision_timestamps = []
        if revision_lengths is None:
            revision_lengths = []
        if page_timestamps is None:
            page_timestamps = []
        if page_namespaces is None:
            page_namespaces = []
        if page_creator_index is None:
            page_creator_index = []
        
        if type(revision_timestamps) is datetime:
            revision_timestamps = i(revision_timestamps)
        if type(revision_timestamps) is int:
            revision_timestamps = [
                [revision_timestamps] * revisions_per_editor
            ] * editor_count
        
        if type(revision_lengths) is int:
            revision_lengths = [
                [revision_lengths] * revisions_per_editor
            ] * editor_count
        
        if type(user_registrations) is int:
            user_registrations = [user_registrations] * editor_count
        
        project = mediawiki_project
        if create_cohort:
            cohort = CohortStore(
                name='{0}-cohort'.format(name),
                enabled=True,
                public=False,
                validated=True,
            )
            self.session.add(cohort)
            self.session.commit()
        
        if not mw_session:
            mw_session = self.mwSession
        
        page = Page(page_namespace=0, page_title='{0}-page'.format(name),
                    page_touched=page_touched)
        mw_session.add(page)
        mw_session.commit()
        
        mw_session.bind.engine.execute(
            MediawikiUser.__table__.insert(), [
                {
                    'user_name': 'Editor {0}-{1}'.format(name, e),
                    'user_registration': user_registrations[e],
                    'user_email_token_expires': user_email_token_expires
                }
                for e in range(editor_count)
            ]
        )
        mw_session.commit()
        self.add_centralauth_users(['Editor {0}-0'.format(name)], ['wiki', 'wiki2'])
        editors = mw_session.query(MediawikiUser)\
            .filter(MediawikiUser.user_name.like('Editor {0}-%'.format(name)))\
            .order_by(MediawikiUser.user_id)\
            .all()

        # Create logging table records for each inserted user
        mw_session.bind.engine.execute(
            Logging.__table__.insert(), [
                {
                    'log_user': editor.user_id,
                    'log_timestamp': editor.user_registration,
                    'log_title': editor.user_name,
                    'log_type': 'newusers',
                    'log_action': 'create',
                }
                for editor in editors
            ]
        )
        mw_session.commit()

        if create_cohort:
            self.session.bind.engine.execute(
                WikiUserStore.__table__.insert(), [
                    {
                        'raw_id_or_name'        : editor.user_name or editor.user_id,
                        'mediawiki_username'    : editor.user_name,
                        'mediawiki_userid'      : editor.user_id,
                        'project'               : project,
                        'valid'                 : True,
                        'validating_cohort'     : cohort.id,
                    }
                    for editor in editors
                ]
            )
            self.session.commit()
            wiki_users = self.session.query(WikiUserStore)\
                .filter(
                    WikiUserStore.mediawiki_username.like('Editor {0}-%'.format(name)))\
                .all()
            self.session.bind.engine.execute(
                CohortWikiUserStore.__table__.insert(), [
                    {
                        'cohort_id'     : cohort.id,
                        'wiki_user_id'  : wiki_user.id,
                    }
                    for wiki_user in wiki_users
                ]
            )
            self.session.commit()
        
        mw_session.bind.engine.execute(
            Revision.__table__.insert(), [
                {
                    'rev_page'      : page.page_id,
                    'rev_user'      : editors[e].user_id,
                    'rev_comment'   : 'revision {0}, editor {1}'.format(r, e),
                    'rev_timestamp' : revision_timestamps[e][r] or UNICODE_NULL * 14,
                    'rev_len'       : revision_lengths[e][r],
                    # rev_parent_id will be set below, following chronology
                }
                for e, r in product(range(editor_count), range(revisions_per_editor))
            ]
        )
        mw_session.commit()
        revisions = mw_session.query(Revision)\
            .filter(Revision.rev_page == page.page_id)\
            .order_by(Revision.rev_id)\
            .all()
        
        # add rev_parent_id chain in chronological order
        real_revisions = filter(lambda r: r.rev_timestamp, revisions)
        ordered_revisions = sorted(real_revisions, key=lambda r: r.rev_timestamp)
        for idx, revision in enumerate(ordered_revisions):
            if idx == 0:
                revision.rev_parent_id = 0
            else:
                revision.rev_parent_id = ordered_revisions[idx - 1].rev_id
        
        mw_session.commit()
        
        if create_cohort:
            # establish ownership for this cohort
            if not owner_user_id:
                owner = UserStore(username='******', email='*****@*****.**')
                self.session.add(owner)
                self.session.commit()
                owner_user_id = owner.id

            self.session.add(CohortUserStore(
                user_id=owner_user_id,
                cohort_id=cohort.id,
                role=CohortUserRole.OWNER,
            ))
            self.session.commit()
        
        if page_count > 0:
            # create any additional pages
            if type(page_timestamps) is int:
                page_timestamps = [page_timestamps] * page_count
            if type(page_namespaces) is int:
                page_namespaces = [page_namespaces] * page_count
            if type(page_creator_index) is int:
                page_creator_index = [page_creator_index] * page_count
            
            mw_session.bind.engine.execute(
                Page.__table__.insert(), [
                    {
                        'page_namespace'    : page_namespaces[p],
                        'page_title'        : '{0}-additional-page-{1}'.format(name, p),
                        'page_touched'      : page_touched
                    }
                    for p in range(page_count)
                ]
            )
            mw_session.commit()
            pages = mw_session.query(Page)\
                .filter(Page.page_title.like('{0}-additional-page-%'.format(name)))\
                .order_by(Page.page_id)\
                .all()
            
            mw_session.bind.engine.execute(
                Revision.__table__.insert(), [
                    {
                        'rev_page'      : pages[p].page_id,
                        'rev_user'      : editors[page_creator_index[p]].user_id,
                        'rev_comment'   : 'page {0} created'.format(p),
                        'rev_timestamp' : page_timestamps[p],
                        'rev_len'       : 10,
                        'rev_parent_id' : 0,
                    }
                    for p in range(page_count)
                ]
            )
            mw_session.commit()

        if create_cohort:
            self.project = project

            # TODO this is a storage object, should be changed
            # for metrics tests into a logic object, not a storage object
            self.cohort = cohort
            self.page = page
            self.editors = editors
            self.editor_ids = [e.user_id for e in editors]
            self.revisions = revisions
            self.owner_user_id = owner_user_id
コード例 #12
0
def load_user(user_id):
    """
    Callback required by Flask-Login.  Gets the User object from the database.
    """
    db_session = db.get_session()
    return UserStore.get(db_session, user_id)