def render(self): login_url = resource_url(self.request.context, self.request, 'login') referrer = self.request.url # never use the login form itself as came_from if referrer == login_url: referrer = '/' came_from = self.request.params.get('came_from', referrer) login = self.request.params.get('user.login', '') if 'form.submitted' in self.request.params: password = self.request.params.get('user.password', u'') if password: if User.by_ldap_credentials( self.session, login, password, self.request.registry.settings) is not None: log.info('login %r succeed', login) headers = remember(self.request, login) return HTTPFound(location=came_from, headers=headers) if User.by_credentials(self.session, login, password) is not None: log.info('login %r succeed', login) headers = remember(self.request, login) return HTTPFound(location=came_from, headers=headers) return { 'came_from': came_from, 'user': User(login=login), }
def authenticated_userid(self, request): auth = request.environ.get('HTTP_AUTHORIZATION') try: authmeth, auth = auth.split(' ', 1) except AttributeError: # not enough values to unpack return None if authmeth.lower() != 'basic': return None try: # Python 3's string is already unicode auth = base64.b64decode(auth.strip()) except binascii.Error: # can't decode return None if not isinstance(auth, unicode): auth = auth.decode('utf-8') try: login, password = auth.split(':', 1) except ValueError: # not enough values to unpack return None if User.by_credentials(DBSession(), login, password): return login if User.by_ldap_credentials(DBSession(), login, password, request.registry.settings): return login return None
def populate(engine, interactive=True): Base.metadata.create_all(engine) session = DBSession() user_perm = Permission(name=u'user_view') admin_perm = Permission(name=u'admin_view') download_perm = Permission(name=u'download_releasefile') upload_perm = Permission(name=u'upload_releasefile') session.add(user_perm) session.add(upload_perm) session.add(download_perm) session.add(admin_perm) admin_group = Group(name=u'admin') admin_group.permissions.append(user_perm) admin_group.permissions.append(download_perm) admin_group.permissions.append(upload_perm) admin_group.permissions.append(admin_perm) session.add(admin_group) user_group = Group(name=u'developer') user_group.permissions.append(user_perm) user_group.permissions.append(download_perm) user_group.permissions.append(upload_perm) session.add(user_group) pip_group = Group(name=u'installer') pip_group.permissions.append(download_perm) session.add(pip_group) if interactive: login = (input('administrator login [admin]:') or 'admin') password = (input('administrator password [changeme]:') or 'changeme') email = (input('administrator email [[email protected]]') or '*****@*****.**') piplogin = (input('installer login [pip]:') or 'pip') pippassword = (input('installer password [changeme]:') or 'changeme') else: login = '******' password = '******' email = '*****@*****.**' piplogin = '******' pippassword = '******' admin = User(login=unicode(login), password=unicode(password), email=unicode(email)) admin.groups.append(admin_group) session.add(admin) pip = User(login=unicode(piplogin), password=unicode(pippassword), ) pip.groups.append(pip_group) session.add(pip) session.commit()
def authenticated_userid(self, request): auth = request.environ.get('HTTP_AUTHORIZATION') try: authmeth, auth = auth.split(' ', 1) except AttributeError: # not enough values to unpack return None if authmeth.lower() != 'basic': return None try: # Python 3's string is already unicode auth = base64.b64decode(auth.strip()) except binascii.Error: # can't decode return None if not isinstance(auth, unicode): auth = auth.decode('utf-8') try: login, password = auth.split(':', 1) except ValueError: # not enough values to unpack return None if User.by_credentials(DBSession(), login, password): return login if User.by_ldap_credentials(DBSession(), login, password,request.registry.settings): return login return None
def render(self): login_url = resource_url(self.request.context, self.request, 'login') referrer = self.request.url # never use the login form itself as came_from if referrer == login_url: referrer = '/' came_from = self.request.params.get('came_from', referrer) login = self.request.params.get('user.login', '') if 'form.submitted' in self.request.params: password = self.request.params.get('user.password', u'') if password: if User.by_ldap_credentials( self.session, login, password, self.request.registry.settings) is not None: log.info('login %r succeed', login) headers = remember(self.request, login) return HTTPFound(location=came_from, headers=headers) if User.by_credentials( self.session, login, password) is not None: log.info('login %r succeed', login) headers = remember(self.request, login) return HTTPFound(location=came_from, headers=headers) return {'came_from': came_from, 'user': User(login=login), }
def render(self): package = Package.by_name(self.session, self.request.matchdict["package_name"]) if not package: raise HTTPNotFound() if "form.refresh_package" in self.request.params: package.update_at = None self.session.add(package) owners = dict((usr.login, usr) for usr in package.owners) can_edit_role = self.login in owners.keys() and package.local if "form.add_role" in self.request.params: if not can_edit_role: raise HTTPForbidden() user = User.by_login(self.session, self.request.params["login"]) if user and user.has_permission("upload_releasefile"): if self.request.params["role"] == "owner": if user.login not in owners: package.owners.append(user) else: maintainers = [usr.login for usr in package.owners] if user.login not in maintainers: package.maintainers.append(user) self.session.add(package) if "form.remove_maintainer" in self.request.params: if not can_edit_role: raise HTTPForbidden() user = User.by_login(self.session, self.request.params["login"]) if user: maintainers = dict((usr.login, usr) for usr in package.maintainers) if user.login in maintainers: package.maintainers.remove(maintainers[user.login]) self.session.add(package) if "form.remove_owner" in self.request.params: if not can_edit_role: raise HTTPForbidden() user = User.by_login(self.session, self.request.params["login"]) if user: if user.login in owners: package.owners.remove(owners[user.login]) self.session.add(package) if "release_version" in self.request.matchdict: release = Release.by_version(self.session, package.name, self.request.matchdict["release_version"]) else: release = package.sorted_releases[0] return {u"package": package, u"release": release, u"can_edit_role": can_edit_role}
def _create_release(self, package, data): data = self._to_unicode(data) release = Release( package=package, summary=data.get('summary'), version=data.get('version'), stable_version=data.get('stable_version'), home_page=data.get('home_page'), license=data.get('license'), description=data.get('description'), keywords=data.get('keywords'), platform=data.get('platform'), download_url=data.get('download_url'), bugtrack_url=data.get('bugtrack_url'), docs_url=data.get('docs_url'), ) if data.get('author'): author = User.by_login(self.session, data['author'], local=False) if not author: author = User(login=data['author'], local=False, email=data.get('author_email')) self.session.add(author) release.author = author self.session.flush() if data.get('maintainer'): maintainer = User.by_login(self.session, data['maintainer'], local=False) if not maintainer: maintainer = User(login=data['maintainer'], local=False, email=data.get('maintainer_email')) self.session.add(maintainer) release.maintainer = maintainer self.session.flush() for name in data.get('classifiers', []): classifier = Classifier.by_name(self.session, name.decode('utf-8')) while classifier: release.classifiers.append(classifier) if classifier not in package.classifiers: package.classifiers.append(classifier) classifier = classifier.parent self.session.flush() return release
def test_update_post_ok(self): from pyshop.models import User from pyshop.views.user import Edit view = Edit( self.create_request( { "form.submitted": u"1", "user.login": u"root", "user.firstname": u"Admin", "user.lastname": u"Istrator", } ) )() self.assertIsRedirect(view) self.session.flush() admin = User.by_credentials(self.session, u"root", u"changeme") self.assertIsInstance(admin, User) self.assertEqual(admin.login, u"root") self.assertEqual(admin.firstname, u"Admin") self.assertEqual(admin.lastname, u"Istrator") admin.login = u"admin" admin.password = u"changeme" admin.firstname = None admin.lastname = None self.session.add(admin)
def authenticated_userid(self, request): auth = request.environ.get('HTTP_AUTHORIZATION') try: authmeth, auth = auth.split(' ', 1) except AttributeError as ValueError: # not enough values to unpack return None if authmeth.lower() != 'basic': return None try: # Python 3's string is already unicode auth = auth.strip().decode('base64') if sys.version_info[0] == 2: auth = unicode(auth) except binascii.Error: # can't decode return None try: login, password = auth.split(':', 1) except ValueError: # not enough values to unpack return None if User.by_credentials(DBSession(), login, password): return login return None
def _create_release(self, package, data): release = Release(package=package, summary=data.get('summary'), version=data.get('version'), stable_version=data.get('stable_version'), home_page=data.get('home_page'), license=data.get('license'), description=data.get('description'), keywords=data.get('keywords'), platform=data.get('platform'), download_url=data.get('download_url'), bugtrack_url=data.get('bugtrack_url'), docs_url=data.get('docs_url'), ) if data.get('author'): author = User.by_login(self.session, data['author'], local=False) if not author: author = User(login=data['author'], local=False, email=data.get('author_email')) self.session.add(author) release.author = author self.session.flush() if data.get('maintainer'): maintainer = User.by_login(self.session, data['maintainer'], local=False) if not maintainer: maintainer = User(login=data['maintainer'], local=False, email=data.get('maintainer_email')) self.session.add(maintainer) release.maintainer = maintainer self.session.flush() for name in data.get('classifiers', []): classifier = Classifier.by_name(self.session, name) while classifier: release.classifiers.append(classifier) if classifier not in package.classifiers: package.classifiers.append(classifier) classifier = classifier.parent self.session.flush() return release
def test_post_delete_ok(self): from pyshop.views.account import Delete from pyshop.models import User view = Delete(self.create_request({'form.submitted': '1', }, matchdict={'user_id': self.account_id },))() self.assertIsRedirect(view) account = User.by_id(self.session, self.account_id) self.assertIsNone(account) self.account_todelete = []
def setUp(self): super(AccountTestCase, self).setUp() import uuid from pyshop.models import User, Group self.account_login = unicode(uuid.uuid4()) u = User(login=self.account_login, password=u'secret') u.groups.append(Group.by_name(self.session, u'developer')) self.session.add(u) self.session.flush() self.account_id = u.id self.account_todelete = [self.account_id]
def test_change_password_post_ok(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd(self.create_request({'form.submitted': u'1', 'current_password': u'changeme', 'user.password': u'newpassw', 'confirm_password': u'newpassw', }))() admin = User.by_credentials(self.session, u'admin', u'newpassw') self.assertIsInstance(admin, User) admin.password = u'changeme' self.session.add(admin)
def test_change_password_post_ko_unchanged(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd(self.create_request({'form.submitted': u'1', 'current_password': u'changeme', 'user.password': u'changeme', 'confirm_password': u'changeme', }))() self.assertEqual(view['errors'], [u'password is inchanged']) admin = User.by_credentials(self.session, u'admin', u'changeme') self.assertIsInstance(admin, User)
def authbasic(request): """ Authentification basic, Upload pyshop repository access """ if len(request.environ.get('HTTP_AUTHORIZATION','')) > 0: auth = request.environ.get('HTTP_AUTHORIZATION') scheme, data = auth.split(None, 1) assert scheme.lower() == 'basic' data = base64.b64decode(data) if not isinstance(data, unicode): data = data.decode('utf-8') username, password = data.split(':', 1) if User.by_ldap_credentials(DBSession(), username, password, request.registry.settings): return HTTPFound(location=request.url) if User.by_credentials(DBSession(), username, password): return HTTPFound(location=request.url) return Response(status=401, headerlist=[(b'WWW-Authenticate', b'Basic realm="pyshop repository access"' )], )
def test_change_password_post_ko_not_matched(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd(self.create_request({'form.submitted': u'1', 'current_password': u'CHANGEME', 'user.password': u'newpassw', 'confirm_password': u'NEWPASSW', }))() self.assertEqual(view['errors'], [u'current password is not correct', u'passwords do not match']) admin = User.by_credentials(self.session, u'admin', u'changeme') self.assertIsInstance(admin, User)
def test_change_password_post_ko_unchanged(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd( self.create_request({ 'form.submitted': u'1', 'current_password': u'changeme', 'user.password': u'changeme', 'confirm_password': u'changeme', }))() self.assertEqual(view['errors'], [u'password is inchanged']) admin = User.by_credentials(self.session, u'admin', u'changeme') self.assertIsInstance(admin, User)
def validate(self, model, errors): r = self.request if not User.by_credentials(self.session, model.login, r.params['current_password']): errors.append(_(u'current password is not correct')) elif r.params['user.password'] == r.params['current_password']: errors.append(_(u'password is inchanged')) if r.params['user.password'] != r.params['confirm_password']: errors.append(_(u'passwords do not match')) return len(errors) == 0
def test_change_password_post_ok(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd( self.create_request({ 'form.submitted': u'1', 'current_password': u'changeme', 'user.password': u'newpassw', 'confirm_password': u'newpassw', }))() admin = User.by_credentials(self.session, u'admin', u'newpassw') self.assertIsInstance(admin, User) admin.password = u'changeme' self.session.add(admin)
def test_post_delete_ok(self): from pyshop.views.account import Delete from pyshop.models import User view = Delete( self.create_request( { 'form.submitted': '1', }, matchdict={'user_id': self.account_id}, ))() self.assertIsRedirect(view) account = User.by_id(self.session, self.account_id) self.assertIsNone(account) self.account_todelete = []
def test_post_create_ok(self): from pyshop.views.account import Create from pyshop.models import User, Group view = Create(self.create_request({'form.submitted': u'1', 'user.login': u'dummy_new', 'user.password': u'secret', 'user.firstname': u'', 'user.lastname': u'', 'user.email': u'*****@*****.**', 'confirm_password': u'secret', 'groups': [u'1', u'2'] }))() self.assertIsRedirect(view) self.account_todelete.append(User.by_login(self.session, u'dummy_new').id)
def test_change_password_post_ko_not_matched(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd( self.create_request({ 'form.submitted': u'1', 'current_password': u'CHANGEME', 'user.password': u'newpassw', 'confirm_password': u'NEWPASSW', }))() self.assertEqual( view['errors'], [u'current password is not correct', u'passwords do not match']) admin = User.by_credentials(self.session, u'admin', u'changeme') self.assertIsInstance(admin, User)
def test_post_edit_ok(self): from pyshop.views.account import Edit from pyshop.models import User, Group view = Edit(self.create_request({'form.submitted': '1', 'user.login': u'dummy_edited', 'user.firstname': u'', 'user.lastname': u'', 'user.email': u'*****@*****.**', 'groups': [u'1'] }, matchdict={'user_id': self.account_id }))() self.assertIsRedirect(view) self.session.flush() user = User.by_id(self.session, self.account_id) self.assertEqual(user.login, u'dummy_edited') self.assertEqual([g.id for g in user.groups], [1])
def test_change_password_post_ko_not_matched(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd( self.create_request( { "form.submitted": u"1", "current_password": u"CHANGEME", "user.password": u"newpassw", "confirm_password": u"NEWPASSW", } ) )() self.assertEqual(view["errors"], [u"current password is not correct", u"passwords do not match"]) admin = User.by_credentials(self.session, u"admin", u"changeme") self.assertIsInstance(admin, User)
def test_change_password_post_ko_unchanged(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd( self.create_request( { "form.submitted": u"1", "current_password": u"changeme", "user.password": u"changeme", "confirm_password": u"changeme", } ) )() self.assertEqual(view["errors"], [u"password is inchanged"]) admin = User.by_credentials(self.session, u"admin", u"changeme") self.assertIsInstance(admin, User)
def authbasic(request): """ Authentification basic, Upload pyshop repository access """ if len(request.environ.get('HTTP_AUTHORIZATION','')) > 0: auth = request.environ.get('HTTP_AUTHORIZATION') scheme, data = auth.split(None, 1) assert scheme.lower() == 'basic' username, password = data.decode('base64').split(':', 1) if User.by_credentials(DBSession(), username, password): return HTTPFound(location=request.url) return Response(status=401, headerlist=[('WWW-Authenticate', ('Basic realm="%s"' % _('pyshop repository access')).encode('utf-8') )], )
def test_post_create_ok(self): from pyshop.views.account import Create from pyshop.models import User, Group view = Create( self.create_request({ 'form.submitted': u'1', 'user.login': u'dummy_new', 'user.password': u'secret', 'user.firstname': u'', 'user.lastname': u'', 'user.email': u'*****@*****.**', 'confirm_password': u'secret', 'groups': [u'1', u'2'] }))() self.assertIsRedirect(view) self.account_todelete.append( User.by_login(self.session, u'dummy_new').id)
def test_change_password_post_ok(self): from pyshop.models import User from pyshop.views.user import ChangePassword as ChangePwd view = ChangePwd( self.create_request( { "form.submitted": u"1", "current_password": u"changeme", "user.password": u"newpassw", "confirm_password": u"newpassw", } ) )() admin = User.by_credentials(self.session, u"admin", u"newpassw") self.assertIsInstance(admin, User) admin.password = u"changeme" self.session.add(admin)
def test_post_edit_ok(self): from pyshop.views.account import Edit from pyshop.models import User, Group view = Edit( self.create_request( { 'form.submitted': '1', 'user.login': u'dummy_edited', 'user.firstname': u'', 'user.lastname': u'', 'user.email': u'*****@*****.**', 'groups': [u'1'] }, matchdict={'user_id': self.account_id}))() self.assertIsRedirect(view) self.session.flush() user = User.by_id(self.session, self.account_id) self.assertEqual(user.login, u'dummy_edited') self.assertEqual([g.id for g in user.groups], [1])
def test_update_post_ok(self): from pyshop.models import User from pyshop.views.user import Edit view = Edit(self.create_request({'form.submitted': u'1', 'user.login': u'root', 'user.firstname': u'Admin', 'user.lastname': u'Istrator', }))() self.assertIsRedirect(view) self.session.flush() admin = User.by_credentials(self.session, u'root', u'changeme') self.assertIsInstance(admin, User) self.assertEqual(admin.login, u'root') self.assertEqual(admin.firstname, u'Admin') self.assertEqual(admin.lastname, u'Istrator') admin.login = u'admin' admin.password = u'changeme' admin.firstname = None admin.lastname = None self.session.add(admin)
def test_update_post_ok(self): from pyshop.models import User from pyshop.views.user import Edit view = Edit( self.create_request({ 'form.submitted': u'1', 'user.login': u'root', 'user.firstname': u'Admin', 'user.lastname': u'Istrator', }))() self.assertIsRedirect(view) self.session.flush() admin = User.by_credentials(self.session, u'root', u'changeme') self.assertIsInstance(admin, User) self.assertEqual(admin.login, u'root') self.assertEqual(admin.firstname, u'Admin') self.assertEqual(admin.lastname, u'Istrator') admin.login = u'admin' admin.password = u'changeme' admin.firstname = None admin.lastname = None self.session.add(admin)
def render(self): api = pypi.proxy settings = self.request.registry.settings sanitize = asbool(settings['pyshop.mirror.sanitize']) package_name = self.request.matchdict['package_name'] pkg = Package.by_name(self.session, package_name) if pkg is None: pkg = Package.by_name(self.session, package_name.replace('-', '_')) if pkg is None: pkg = Package.by_name(self.session, package_name.replace('-', '.')) refresh = True session_users = {} if pkg: if pkg.local: refresh = False else: if pkg.update_at: log.debug('validating cache interval') current_td = datetime.now() - pkg.update_at max_td = timedelta( hours=int(settings.get('pyshop.mirror.cache.ttl', '24'))) refresh = current_td > max_td log.debug('"%s" > "%s": %s', current_td, max_td, refresh) if refresh: log.info('refresh package %s', package_name) pypi_versions = api.package_releases(package_name, True) # XXX package_releases is case sensitive # but dependencies declaration not... if not pypi_versions: pkg_info = self._search_package(package_name) if not pkg_info and '-' in package_name: tmp_name = package_name.replace('-', '_') pkg_info = self._search_package(tmp_name) if not pkg_info and '-' in package_name: tmp_name = package_name.replace('-', '.') pkg_info = self._search_package(tmp_name) if not pkg_info and '_' in package_name: tmp_name = package_name.replace('_', '-') pkg_info = self._search_package(tmp_name) if pkg_info: package_name, pypi_versions = pkg_info pypi_versions = [ver.decode('utf-8') for ver in pypi_versions] else: pypi_versions = [] if not pkg: if not pypi_versions: log.info('package %s has no versions', package_name) return {'package': None, 'package_name': package_name} if sanitize: re_sanitize = re.compile(settings['pyshop.mirror.' 'sanitize.regex']) pypi_versions = [v for v in pypi_versions if re_sanitize.match(v)] # mirror the package now log.info('mirror package %s now', package_name) pkg = Package.by_name(self.session, package_name) if not pkg: pkg = Package(name=package_name, local=False) self.session.add(pkg) self.session.flush() roles = api.package_roles(package_name) for role, login in roles: login = login.decode('utf-8') # XMLRPC should return utf-8 log.info('Looking for non local user %s', login) if _sanitize(login) in session_users: user = session_users[_sanitize(login)] else: user = User.by_login(self.session, login, local=False) if not user: log.info('Not found. creating user {0}'.format(login)) user = User(login=login, local=False) self.session.add(user) if role == 'Owner': pkg.owners.append(user) self.session.add(pkg) elif role == 'Maintainer': pkg.maintainers.append(user) self.session.add(pkg) session_users[_sanitize(login)] = user self.session.flush() self.session.flush() if not pkg.local and refresh: log.debug('refreshing %s package', package_name) pkg_versions = set(pypi_versions).difference(pkg.versions) if not pkg_versions: log.info('No new version to mirror') log.debug('pypi versions: %s', pypi_versions) log.debug('mirrored versions: %s', pkg.versions) for version in pkg_versions: log.info('Mirroring version %s', version) release_data = api.release_data(package_name, version) release = self._create_release(pkg, release_data, session_users) release_files = api.release_urls(package_name, version) for data in release_files: filename = data['filename'].decode('utf-8') rf = ReleaseFile.by_filename(self.session, release, filename) if not rf: rf = self._create_release_file(release, data) pkg.update_at = func.now() self.session.add(pkg) log.info('package %s mirrored' % package_name) return {'package': pkg, 'whlify': asbool(settings.get('pyshop.mirror.wheelify', '0'))}
def setUpModule(): engine = create_engine(settings) populate(engine, interactive=False) session = DBSession() admin_user = User.by_login(session, u'admin') local_user = User(login=u'local_user', password=u'secret', local=True, firstname=u'Local', lastname=u'User') local_user.groups.append(Group.by_name(session, u'developer')) jdo = User(login=u'johndo', local=False) jdoe = User(login=u'janedoe', local=False) session.add(jdo) session.add(jdoe) session.add(local_user) classifiers_names = [ u'Programming Language :: Python', u'Programming Language :: Python :: 2.6', u'Programming Language :: Python :: 2.7', u'Topic :: Software Development', u'Topic :: System :: Archiving :: Mirroring', u'Topic :: System :: Archiving :: Packaging', u'Intended Audience :: Developers', u'Intended Audience :: System Administrators' ] classifiers = [ Classifier.by_name(session, name=c, create_if_not_exists=True) for c in classifiers_names ] pack1 = Package(name=u'mirrored_package1') pack1.owners.append(jdo) pack1.owners.append(jdoe) pack1.downloads = 7 session.add(pack1) release1 = Release(package=pack1, version=u'0.1', summary=u'Common Usage Library', author=jdoe) for c in classifiers[:3]: release1.classifiers.append(c) session.add(release1) release1.files.append( ReleaseFile(filename=u'mirrored_package1-0.1.tar.gz', package_type=u'sdist')) session.add(release1) release2 = Release(package=pack1, version=u'0.2', summary=u'Common Usage Library') for c in classifiers[:5]: release2.classifiers.append(c) release2.files.append( ReleaseFile(filename=u'mirrored_package1-0.2.tar.gz', package_type=u'sdist')) release2.files.append( ReleaseFile(filename=u'mirrored_package1-0.2.egg', package_type=u'bdist_egg')) session.add(release2) pack2 = Package(name=u'mirrored_package2') pack2.owners.append(jdo) pack2.maintainers.append(jdoe) pack2.downloads = 1 session.add(pack2) release3 = Release(package=pack2, version=u'1.0', summary=u'Web Framework For Everybody') for c in classifiers[:3] + classifiers[-2:-2]: release3.classifiers.append(c) session.add(release3) release3.files.append( ReleaseFile(filename=u'mirrored_package2-1.0.tar.gz', package_type=u'sdist')) session.add(release3) pack3 = Package(name=u'local_package1', local=True) pack3.owners.append(local_user) pack3.owners.append(admin_user) session.add(pack3) release4 = Release(package=pack3, version=u'0.1', summary=u'Pet Shop Application') for c in classifiers: release4.classifiers.append(c) release4.files.append( ReleaseFile(filename=u'local_package1-0.1.tar.gz', package_type=u'sdist')) session.add(release4) session.commit()
def test_by_credentials_ok(self): from pyshop.models import User user = User.by_credentials(self.session, u'local_user', 'secret') self.assertIsInstance(user, User) self.assertEqual(user.login, u'local_user') self.assertEqual(user.name, u'Local User')
def tearDown(self): from pyshop.models import User for id in self.account_todelete: u = User.by_id(self.session, id) self.session.delete(u) super(AccountTestCase, self).tearDown()
def test_by_login_ok_local(self): from pyshop.models import User user = User.by_login(self.session, u'local_user') self.assertIsInstance(user, User)
def test_by_credentials_ko_mirrored(self): from pyshop.models import User user = User.by_credentials(self.session, u'johndo', '') self.assertEqual(user, None)
def test_by_login_ok_mirrored(self): from pyshop.models import User user = User.by_login(self.session, u'johndo', local=False) self.assertIsInstance(user, User) self.assertEqual(user.login, u'johndo')
def test_by_login_ko_mirrored(self): from pyshop.models import User user = User.by_login(self.session, u'johndo') self.assertEqual(user, None)
def render(self): return {u'user_count': User.get_locals(self.session, count=True), u'users': User.get_locals(self.session), }
def render(self): package = Package.by_name(self.session, self.request.matchdict['package_name']) if not package: raise HTTPNotFound() if 'form.refresh_package' in self.request.params: package.update_at = None self.session.add(package) owners = dict((usr.login, usr) for usr in package.owners) can_edit_role = self.login in owners.keys() and package.local if 'form.add_role' in self.request.params: if not can_edit_role: raise HTTPForbidden() user = User.by_login(self.session, self.request.params['login']) if user and user.has_permission('upload_releasefile'): if self.request.params['role'] == 'owner': if user.login not in owners: package.owners.append(user) else: maintainers = [usr.login for usr in package.owners] if user.login not in maintainers: package.maintainers.append(user) self.session.add(package) if 'form.remove_maintainer' in self.request.params: if not can_edit_role: raise HTTPForbidden() user = User.by_login(self.session, self.request.params['login']) if user: maintainers = dict((usr.login, usr) for usr in package.maintainers) if user.login in maintainers: package.maintainers.remove(maintainers[user.login]) self.session.add(package) if 'form.remove_owner' in self.request.params: if not can_edit_role: raise HTTPForbidden() user = User.by_login(self.session, self.request.params['login']) if user: if user.login in owners: package.owners.remove(owners[user.login]) self.session.add(package) if 'release_version' in self.request.matchdict: release = Release.by_version(self.session, package.name, self.request.matchdict['release_version']) else: release = package.sorted_releases[0] return {u'package': package, u'release': release, u'can_edit_role': can_edit_role, }
def render(self): settings = self.request.registry.settings username = authenticated_userid(self.request) if not username: raise exc.HTTPForbidden() remote_user = User.by_login(self.session, username) if not remote_user: raise exc.HTTPForbidden() params = self.request.params if (asbool(settings['pyshop.upload.satanize']) and not re.match(settings['pyshop.upload.satanize.regex'], params['version'] )): raise exc.HTTPForbidden() pkg = Package.by_name(self.session, params['name']) if pkg: auth = [user for user in pkg.owners + pkg.maintainers if user == remote_user] if not auth: raise exc.HTTPForbidden() else: pkg = Package(name=params['name'], local=True) pkg.owners.append(remote_user) content = self.request.POST['content'] input_file = content.file # rewrite the filename, do not use the posted one for security filename = u'%s-%s.%s' % (params['name'], params['version'], {u'sdist': u'tar.gz', u'bdist_egg': u'egg', u'bdist_msi': u'msi', u'bdist_dmg': u'zip', # XXX or gztar ? u'bdist_rpm': u'rpm', u'bdist_dumb': u'msi', u'bdist_wininst': u'exe', }[params['filetype']]) dir_ = os.path.join(settings['pyshop.repository'], filename[0].lower()) if not os.path.exists(dir_): os.mkdir(dir_, 0750) filepath = os.path.join(dir_, filename) while os.path.exists(filepath): log.warn('File %s exists but new upload self.request, deleting' % filepath) os.unlink(filepath) size = 0 with open(filepath, 'wb') as output_file: input_file.seek(0) while True: data = input_file.read(2<<16) if not data: break size += len(data) output_file.write(data) release = Release.by_version(self.session, pkg.name, params['version']) if not release: release = Release(package=pkg, version=params['version'], summary=params.get('summary'), author=remote_user, home_page=params.get('home_page'), license=params.get('license'), description=params.get('description'), keywords=params.get('keywords'), platform=params.get('platform'), download_url=params.get('download_url'), docs_url=params.get('docs_url'), ) classifiers = params.getall('classifiers') for name in classifiers: classifier = Classifier.by_name(self.session, name) while classifier: if classifier not in release.classifiers: release.classifiers.append(classifier) if classifier not in pkg.classifiers: pkg.classifiers.append(classifier) classifier = classifier.parent rfile = ReleaseFile.by_filename(self.session, release, filename) if not rfile: rfile = ReleaseFile(release=release, filename=filename, size=size, md5_digest=params.get('md5_digest'), package_type=params['filetype'], python_version=params.get('pyversion'), comment_text=params.get('comment'), ) self.session.add(rfile) self.session.add(release) pkg.update_at = func.now() self.session.add(pkg) return {'release_file': rfile}
def render(self): api = pypi.proxy settings = self.request.registry.settings satanize = asbool(settings['pyshop.mirror.satanize']) package_name = self.request.matchdict['package_name'] pkg = Package.by_name(self.session, package_name) refresh = True if pkg: if pkg.local: refresh = False else: if pkg.update_at: td = datetime.now() - pkg.update_at refresh = td.days > 0 or td.seconds > 10800 if refresh: pypi_versions = api.package_releases(package_name, True) # XXX package_releases is case sensitive # but dependancies declaration not... if not pypi_versions: package_name = package_name.lower() search_result = api.search({'name': package_name}, True) search_result = [p for p in search_result if p['name'].lower() == package_name] if search_result: package_name = search_result[0]['name'] pypi_versions = api.package_releases(package_name, True) else: pypi_versions = [] if not pkg: if not pypi_versions: log.info('package %s has no versions' % package_name) return {'package': None, 'package_name': package_name} if satanize: re_satanize = re.compile(settings['pyshop.mirror.' 'satanize.regex']) pypi_versions = [v for v in pypi_versions if re_satanize.match(v)] # mirror the package now log.info('mirror package %s now' % package_name) pkg = Package(name=package_name, local=False) roles = api.package_roles(package_name) for role, login in roles: user = User.by_login(self.session, login, local=False) if not user: user = User(login=login, local=False) self.session.add(user) if role == 'Owner': pkg.owners.append(user) elif role == 'Maintainer': pkg.maintainers.append(user) self.session.flush() refresh = True if not pkg.local and refresh: pkg_versions = pkg.versions for version in pypi_versions: if version not in pkg_versions: release_data = api.release_data(package_name, version) release = self._create_release(pkg, release_data) release_files = api.release_urls(package_name, version) for data in release_files: rf = ReleaseFile.by_filename(self.session, release, data['filename']) if not rf: rf = self._create_release_file(release, data) pkg.update_at = func.now() self.session.add(pkg) log.info('package %s mirrored' % package_name) return {'package': pkg}
def render(self): api = pypi.proxy settings = self.request.registry.settings sanitize = asbool(settings['pyshop.mirror.sanitize']) package_name = self.request.matchdict['package_name'] pkg = Package.by_name(self.session, package_name) refresh = True if pkg: if pkg.local: refresh = False else: if pkg.update_at: current_td = datetime.now() - pkg.update_at max_td = timedelta(hours=int( settings.get('pyshop.mirror.cache.ttl', '24'))) refresh = current_td > max_td log.debug('"{cdt}" > "{max}": {refr}'.format( cdt=current_td, max=max_td, refr=refresh)) if refresh: log.info('refresh package {pkg}'.format(pkg=package_name)) pypi_versions = api.package_releases(package_name, True) # XXX package_releases is case sensitive # but dependancies declaration not... if not pypi_versions: pkg_info = self._search_package(package_name) if not pkg_info and '-' in package_name: tmp_name = package_name.replace('-', '_') pkg_info = self._search_package(tmp_name) if not pkg_info and '_' in package_name: tmp_name = package_name.replace('_', '-') pkg_info = self._search_package(tmp_name) if pkg_info: package_name, pypi_versions = pkg_info else: pypi_versions = [] if not pkg: if not pypi_versions: log.info('package %s has no versions' % package_name) return {'package': None, 'package_name': package_name} if sanitize: re_sanitize = re.compile(settings['pyshop.mirror.' 'sanitize.regex']) pypi_versions = [ v for v in pypi_versions if re_sanitize.match(v) ] # mirror the package now log.info('mirror package %s now' % package_name) pkg = Package.by_name(self.session, package_name) if not pkg: pkg = Package(name=package_name, local=False) self.session.add(pkg) self.session.flush() roles = api.package_roles(package_name) for role, login in roles: login = login.decode('utf-8') # XMLRPC should return utf-8 user = User.by_login(self.session, login, local=False) if not user: user = User(login=login, local=False) self.session.add(user) if role == 'Owner': pkg.owners.append(user) elif role == 'Maintainer': pkg.maintainers.append(user) self.session.flush() refresh = True if not pkg.local and refresh: pkg_versions = pkg.versions for version in pypi_versions: if version not in pkg_versions: release_data = api.release_data(package_name, version) release = self._create_release(pkg, release_data) release_files = api.release_urls(package_name, version) for data in release_files: filename = data['filename'].decode('utf-8') rf = ReleaseFile.by_filename(self.session, release, filename) if not rf: rf = self._create_release_file(release, data) pkg.update_at = func.now() self.session.add(pkg) log.info('package %s mirrored' % package_name) return { 'package': pkg, 'whlify': asbool(settings.get('pyshop.mirror.wheelify', '0')) }
def test_by_credentials_ko_unexists(self): from pyshop.models import User user = User.by_credentials(self.session, u'u404', u"' OR 1 = 1 #") self.assertEqual(user, None)
def test_by_credentials_ko_password(self): from pyshop.models import User user = User.by_credentials(self.session, u'admin', 'CHANGEME') self.assertIsNone(user)
def test_hash_password(self): from pyshop.models import User u = User(login=u'test_password', password=u'secret') self.assertNotEqual(u.password, u'secret', 'password must be hashed')
def _create_release(self, package, data, session_users): log.info('Create release %s for package %s', data.get('version'), package.name) data = self._to_unicode(data) release = Release(package=package, summary=data.get('summary'), version=data.get('version'), stable_version=data.get('stable_version'), home_page=data.get('home_page'), license=data.get('license'), description=data.get('description'), keywords=data.get('keywords'), platform=data.get('platform'), download_url=data.get('download_url'), bugtrack_url=data.get('bugtrack_url'), docs_url=data.get('docs_url'), ) if data.get('author'): log.info('Looking for author %s', data['author']) if _sanitize(data['author']) in session_users: author = session_users[_sanitize(data['author'])] else: author = User.by_login(self.session, data['author'], local=False) if not author: log.info('Author %s not found, creating', data['author']) author = User(login=data['author'], local=False, email=data.get('author_email')) self.session.add(author) session_users[_sanitize(data['author'])] = author release.author = author self.session.flush() if data.get('maintainer'): log.info('Looking for maintainer {0}'.format(data['maintainer'])) if _sanitize(data['maintainer']) in session_users: maintainer = session_users[_sanitize(data['maintainer'])] else: maintainer = User.by_login(self.session, data['maintainer'], local=False) if not maintainer: log.info('Maintainer not found, creating user {0}' ''.format(data['maintainer'])) maintainer = User(login=data['maintainer'], local=False, email=data.get('maintainer_email')) self.session.add(maintainer) session_users[_sanitize(data['maintainer'])] = maintainer release.maintainer = maintainer self.session.flush() for name in data.get('classifiers', []): classifier = Classifier.by_name(self.session, name.decode('utf-8'), create_if_not_exists=True) while classifier: if classifier not in release.classifiers: release.classifiers.append(classifier) if classifier not in package.classifiers: package.classifiers.append(classifier) classifier = classifier.parent self.session.flush() return release
def authbasic(request): """ Authentification basic, Upload pyshop repository access """ if len(request.environ.get('HTTP_AUTHORIZATION', '')) > 0: transaction.manager auth = request.environ.get('HTTP_AUTHORIZATION') scheme, data = auth.split(None, 1) assert scheme.lower() == 'basic' data = base64.b64decode(data) if not isinstance(data, unicode): data = data.decode('utf-8') username, password = data.split(':', 1) # if User.by_ldap_credentials( # DBSession(), username, password, request.registry.settings): # return HTTPFound(location=request.url) # if User.by_credentials(DBSession(), username, password): # return HTTPFound(location=request.url) # if user: # return HTTPFound(location=request.url) user = None session = DBSession() if request.registry.settings["pyshop.ldap.use_for_auth"]: user = User.by_ldap_credentials(session, username, password, request.registry.settings) if user: user = User.by_login(session, username) else: user = User.by_login(session, username) if user: session.delete(user) user = None else: user = User.by_credentials(session, username, password) # if user: # return HTTPFound(location=request.url) if user: group_names = [] for group in user.groups: group_names.append(group.name) transaction.commit() if request.matched_route: print("*" * 200) print(request.matched_route.name) if request.matched_route.name in ["upload_releasefile"]: if not "developer" in group_names: return Response( status=401, headerlist=[ (b'WWW-Authenticate', b'Basic realm="pyshop repository access"') ], ) return HTTPFound(location=request.url) else: return Response( status=402, headerlist=[(b'WWW-Authenticate', b'Basic realm="pyshop repository access"')], ) return Response( status=401, headerlist=[(b'WWW-Authenticate', b'Basic realm="pyshop repository access"')], )
def render(self): api = pypi.proxy settings = self.request.registry.settings sanitize = asbool(settings['pyshop.mirror.sanitize']) package_name = self.request.matchdict['package_name'] pkg = Package.by_name(self.session, package_name) refresh = True if pkg: if pkg.local: refresh = False else: if pkg.update_at: td = datetime.now() - pkg.update_at # refresh if the package has not been update today # XXX should be configurable refresh = td.days > 0 if refresh: pypi_versions = api.package_releases(package_name, True) # XXX package_releases is case sensitive # but dependancies declaration not... if not pypi_versions: search_result = api.search({'name': package_name}, True) search_count = len(search_result) search_result = [p for p in search_result if p['name'].lower() == package_name or p['name'].lower().replace('-', '_') == package_name] log.debug('Found {sc}, matched {mc}'.format(sc=search_count, mc=len(search_result))) if search_result: package_name = search_result[0]['name'] pypi_versions = api.package_releases(package_name, True) else: pypi_versions = [] if not pkg: if not pypi_versions: log.info('package %s has no versions' % package_name) return {'package': None, 'package_name': package_name} if sanitize: re_sanitize = re.compile(settings['pyshop.mirror.' 'sanitize.regex']) pypi_versions = [v for v in pypi_versions if re_sanitize.match(v)] # mirror the package now log.info('mirror package %s now' % package_name) pkg = Package(name=package_name, local=False) roles = api.package_roles(package_name) for role, login in roles: login = login.decode('utf-8') # XMLRPC should return utf-8 user = User.by_login(self.session, login, local=False) if not user: user = User(login=login, local=False) self.session.add(user) if role == 'Owner': pkg.owners.append(user) elif role == 'Maintainer': pkg.maintainers.append(user) self.session.flush() refresh = True if not pkg.local and refresh: pkg_versions = pkg.versions for version in pypi_versions: if version not in pkg_versions: release_data = api.release_data(package_name, version) release = self._create_release(pkg, release_data) release_files = api.release_urls(package_name, version) for data in release_files: filename = data['filename'].decode('utf-8') rf = ReleaseFile.by_filename(self.session, release, filename) if not rf: rf = self._create_release_file(release, data) pkg.update_at = func.now() self.session.add(pkg) log.info('package %s mirrored' % package_name) return {'package': pkg}