Skip to content
This repository has been archived by the owner on Aug 27, 2023. It is now read-only.

Commit

Permalink
fix: broken links for web interface login (#307)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevearc committed Jul 14, 2022
1 parent b123b47 commit 2feaf06
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 36 deletions.
12 changes: 12 additions & 0 deletions pypicloud/route.py
Expand Up @@ -120,6 +120,17 @@ class PackagesResource(IStaticResource):
"""Resource for cleaner buildout config"""


class AccountResource(object):

"""Resource for login/logout endpoints"""

__name__ = ""
__parent__ = None

def __init__(self, request):
self.request = request


class Root(IStaticResource):

"""Root context for PyPI Cloud"""
Expand All @@ -130,6 +141,7 @@ class Root(IStaticResource):
"simple": SimpleResource,
"pypi": SimpleResource,
"packages": PackagesResource,
"acct": AccountResource,
}

def __init__(self, request):
Expand Down
8 changes: 4 additions & 4 deletions pypicloud/static/js/pypicloud.js
Expand Up @@ -282,7 +282,7 @@ angular
password: password,
};
$http
.post(ROOT + "login", data)
.post(ROOT + "acct/login", data)
.success(function (data, status, headers, config) {
$scope.loggingIn = false;
$scope.error = false;
Expand All @@ -301,7 +301,7 @@ angular
password: password,
};
$http
.put(ROOT + "login", data)
.put(ROOT + "acct/login", data)
.success(function (data, status, headers, config) {
$scope.error = false;
$scope.registered = username;
Expand All @@ -328,7 +328,7 @@ angular
};
$scope.registering = true;
$http
.put(ROOT + "tokenRegister", data)
.put(ROOT + "acct/tokenRegister", data)
.success(function (data, status, headers, config) {
$scope.error = false;
$scope.registering = false;
Expand Down Expand Up @@ -519,7 +519,7 @@ angular
password: password,
};
$http
.put(ROOT + "login", data)
.put(ROOT + "acct/login", data)
.success(function (data, status, headers, config) {
window.location = ROOT;
})
Expand Down
58 changes: 45 additions & 13 deletions pypicloud/static/partial/index.html
@@ -1,12 +1,12 @@
<div ng-controller="IndexCtrl">

<!-- Helper text to tell people how to use this server with pip -->
<div class="row hidden-xs hidden-sm" ng-show="!$cookies.seenPipHelp && packages && packages.length > 0">
<div
class="row hidden-xs hidden-sm"
ng-show="!$cookies.seenPipHelp && packages && packages.length > 0"
>
<div class="col-xs-12 col-md-offset-2 col-md-8">
<alert type="'success'" close="closePipHelp()">
<p>
You can install packages using:
</p>
<p>You can install packages using:</p>
<div class="text-center">
<code>
pip install -i {{ DOWNLOAD_URL }}simple/ PACKAGE1 [PACKAGE2 ...]
Expand All @@ -16,23 +16,43 @@
</div>
</div>

<div class="row" ng-show="USER === null && packages !== null && packages.length === 0">
<div
class="row"
ng-show="USER === null && packages !== null && packages.length === 0"
>
<div class="col-xs-12 col-md-offset-3 col-md-6">
<h4>Hmmmm...Looks pretty empty in here. Try <a ng-href="{{ ROOT }}login">logging in?</a></h4>
<h4>
Hmmmm...Looks pretty empty in here. Try
<a ng-href="{{ ROOT }}acct/login">logging in?</a>
</h4>
</div>
</div>

<!-- Search header and toggle buttons -->
<div class="row" style="margin-top: 10px; margin-bottom: 10px;" ng-show="packages !== null">
<div
class="row"
style="margin-top: 10px; margin-bottom: 10px"
ng-show="packages !== null"
>
<div class="col-xs-12 col-md-offset-3 col-md-4">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
<input class="form-control" ng-model="searchText" ng-change="currentPage = 1" type="text" placeholder="Search" autofocus>
<input
class="form-control"
ng-model="searchText"
ng-change="currentPage = 1"
type="text"
placeholder="Search"
autofocus
/>
</div>
</div>
<div class="col-xs-12 col-md-2 hidden-xs hidden-sm">
<div ng-show="showUpload">
<button class="btn btn-sm btn-default pull-right" ng-click="toggleUpload()">
<button
class="btn btn-sm btn-default pull-right"
ng-click="toggleUpload()"
>
{{ uploadCollapsed ? 'Upload' : 'Cancel' }}
<i class="fa fa-caret-up" ng-show="!uploadCollapsed"></i>
</button>
Expand Down Expand Up @@ -61,15 +81,27 @@ <h4>Hmmmm...Looks pretty empty in here. Try <a ng-href="{{ ROOT }}login">logging
</tr>
</thead>
<tbody>
<tr ng-repeat="package in filtered = (packages | filter:searchText) | orderBy:'name' | startFrom:(currentPage - 1)*pageSize | limitTo:pageSize" ng-click="showPackage(package.name)">
<tr
ng-repeat="package in filtered = (packages | filter:searchText) | orderBy:'name' | startFrom:(currentPage - 1)*pageSize | limitTo:pageSize"
ng-click="showPackage(package.name)"
>
<td>{{ package.name }}</td>
<td>{{ package.summary }}</td>
<td>{{ package.last_modified * 1000 | date:'yyyy-MM-dd HH:mm' }}</td>
<td>
{{ package.last_modified * 1000 | date:'yyyy-MM-dd HH:mm' }}
</td>
</tr>
</tbody>
</table>
<div class="text-center" ng-show="filtered.length > pageSize">
<pagination direction-links="true" total-items="filtered.length" rotate="false" max-size="maxSize" items-per-page="pageSize" page="currentPage"></pagination>
<pagination
direction-links="true"
total-items="filtered.length"
rotate="false"
max-size="maxSize"
items-per-page="pageSize"
page="currentPage"
></pagination>
</div>
</div>
</div>
Expand Down
22 changes: 14 additions & 8 deletions pypicloud/static/partial/navbar.html
@@ -1,6 +1,10 @@
<div class="container" ng-controller="NavbarCtrl">
<div class="navbar-header">
<button type="button" class="navbar-toggle" ng-click="navCollapsed = !navCollapsed">
<button
type="button"
class="navbar-toggle"
ng-click="navCollapsed = !navCollapsed"
>
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
Expand All @@ -14,11 +18,14 @@

<div class="nav-collapse" collapse="navCollapsed" style="font-size: 130%">
<ul class="nav navbar-nav">
<li ng-repeat="option in options" ng-class="location.path === option.path ? 'active' : ''">
<li
ng-repeat="option in options"
ng-class="location.path === option.path ? 'active' : ''"
>
<a ng-href="#{{ option.path }}">{{ option.title }}</a>
</li>
<li ng-if="IS_ADMIN">
<a href="#/admin">Admin</a>
<a href="#/admin">Admin</a>
</li>
<li>
<a ng-href="{{ ROOT }}simple/">Simple</a>
Expand All @@ -29,13 +36,12 @@
<div ng-switch-when="null">
<ul class="nav navbar-nav navbar-right">
<li>
<a ng-href="{{ ROOT }}login">Log in</a>
<a ng-href="{{ ROOT }}acct/login">Log in</a>
</li>
</ul>
</div>
<div ng-switch-default>
<ul class="nav navbar-nav navbar-right hidden-xs">

<!-- Destop has a dropdown -->
<li class="dropdown">
<a class="btn dropdown-toggle">
Expand All @@ -47,19 +53,19 @@
</li>
<li class="divider" ng-show="ACCESS_MUTABLE"></li>
<li style="opacity: 0.6">
<a ng-href="{{ ROOT }}logout">Log out</a>
<a ng-href="{{ ROOT }}acct/logout">Log out</a>
</li>
</ul>
</li>
</ul>

<!-- Mobile puts it inline for the collapsed nav menu -->
<!-- Mobile puts it inline for the collapsed nav menu -->
<ul class="nav navbar-nav navbar-right visible-xs">
<li ng-show="ACCESS_MUTABLE">
<a href="#/account">Account</a>
</li>
<li style="opacity: 0.6">
<a ng-href="{{ ROOT }}logout">Log out</a>
<a ng-href="{{ ROOT }}acct/logout">Log out</a>
</li>
</ul>
</div>
Expand Down
2 changes: 1 addition & 1 deletion pypicloud/views/admin.py
Expand Up @@ -176,7 +176,7 @@ def generate_token(self):
"""Create a signup token for a user"""
username = self.request.named_subpaths["username"]
token = self.request.access.get_signup_token(username)
token_url = self.request.app_url("login") + "#/?token=" + token
token_url = self.request.app_url("acct", "login") + "#/?token=" + token
return {"token": token, "token_url": token_url}

@view_config(name="acl.json.gz", request_method="GET")
Expand Down
14 changes: 7 additions & 7 deletions pypicloud/views/login.py
Expand Up @@ -4,11 +4,11 @@
from pyramid.view import view_config
from pyramid_duh import argify

from pypicloud.route import Root
from pypicloud.route import AccountResource


@view_config(
context=Root,
context=AccountResource,
name="login",
request_method="GET",
permission=NO_PERMISSION_REQUIRED,
Expand All @@ -18,7 +18,7 @@
def get_login_page(request):
"""Catch login and redirect to login wall"""
if request.authenticated_userid is not None:
# User is logged in and fetching /login, so redirect to /
# User is logged in and fetching /acct/login, so redirect to /
return HTTPFound(location=request.app_url())
return {}

Expand All @@ -32,7 +32,7 @@ def do_forbidden(request):


@view_config(
context=Root,
context=AccountResource,
name="login",
request_method="POST",
subpath=(),
Expand Down Expand Up @@ -82,7 +82,7 @@ def handle_register_request(request, username, password):


@view_config(
context=Root,
context=AccountResource,
name="tokenRegister",
request_method="PUT",
subpath=(),
Expand All @@ -104,7 +104,7 @@ def do_token_register(request, token, password):


@view_config(
context=Root,
context=AccountResource,
name="login",
request_method="PUT",
subpath=(),
Expand All @@ -117,7 +117,7 @@ def register(request, username, password):
return handle_register_request(request, username, password)


@view_config(context=Root, name="logout", subpath=())
@view_config(context=AccountResource, name="logout", subpath=())
def logout(request):
"""Delete the user session"""
request.response.headers.extend(forget(request))
Expand Down
6 changes: 3 additions & 3 deletions tests/test_login.py
Expand Up @@ -21,14 +21,14 @@ def test_user_fetch_login(self):
DummyRequest, "authenticated_userid", new_callable=PropertyMock
) as auid:
auid.return_value = "dsa"
self.request.url = "/login"
self.request.url = "/acct/login"
ret = login.get_login_page(self.request)
self.assertEqual(ret.status_code, 302)
self.assertEqual(ret.location, "/")

def test_anon_fetch_login(self):
"""Anonymous user fetching /login renders login page"""
self.request.url = "/login"
"""Anonymous user fetching /acct/login renders login page"""
self.request.url = "/acct/login"
ret = login.get_login_page(self.request)
self.assertEqual(ret, {})

Expand Down

0 comments on commit 2feaf06

Please sign in to comment.