network: Cleanup, minor fixes and refactoring

- Make network-manager package get installed when accessing the index page of
  networks.  Also freedombox-setup shold actually pull network-manager package
  as dependency and use it for configuring the initial networks.

- Remove the /connect page and re-use the /add_wifi page for that purpose.

- Fix add connection page titles.

- Handle the case when network-manager returned empty string for SSID.

- Don't explictly URL encode the Wi-Fi SSID when adding a new Wi-Fi network.
  Django automatically handles this in 'url' tag and decodes before url
  routing.  Relax the regex that matches SSID as part of the URL to handle all
  possible SSIDs.
This commit is contained in:
Sunil Mohan Adapa 2015-04-06 22:15:11 +05:30
parent fc6b59d59b
commit 0cb8b4a5fc
5 changed files with 111 additions and 146 deletions

View File

@ -24,9 +24,10 @@ from plinth import network
class ConnectionTypeSelectForm(forms.Form):
"""Form to select type for new connection."""
conn_type = forms.ChoiceField(
connection_type = forms.ChoiceField(
label=_('Connection Type'),
choices=[(k, v) for k, v in network.CONNECTION_TYPE_NAMES.items()])
choices=[(key, value)
for key, value in network.CONNECTION_TYPE_NAMES.items()])
class AddEthernetForm(forms.Form):

View File

@ -21,11 +21,11 @@ from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from gettext import gettext as _
import urllib
from .forms import ConnectionTypeSelectForm, AddEthernetForm, AddWifiForm
from plinth import cfg
from plinth import network
from plinth import package
subsubmenu = [{'url': reverse_lazy('networks:index'),
@ -43,6 +43,7 @@ def init():
@login_required
@package.required(['network-manager'])
def index(request):
"""Show connection list."""
connections = network.get_connection_list()
@ -72,6 +73,7 @@ def edit(request, uuid):
form = AddWifiForm(request.POST)
else:
form = AddEthernetForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
zone = form.cleaned_data['zone']
@ -93,11 +95,7 @@ def edit(request, uuid):
connection, name, zone,
ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address)
else:
messages.error(
request,
_('Cannot edit connection %s: '
'Connection type not supported.') % name)
return redirect(reverse_lazy('networks:index'))
else:
return TemplateResponse(request, 'connections_edit.html',
@ -176,50 +174,12 @@ def deactivate(request, uuid):
@login_required
def scan(request):
"""Show a list of nearby visible wifi APs."""
aps = network.wifi_scan()
"""Show a list of nearby visible Wi-Fi access points."""
access_points = network.wifi_scan()
return TemplateResponse(request, 'wifi_scan.html',
{'title': _('Nearby Wi-Fi Networks'),
'subsubmenu': subsubmenu,
'aps': aps})
@login_required
def connect(request, connect_path):
"""Create a new wifi connection to an existing AP."""
form = None
ssid = urllib.parse.unquote_plus(connect_path)
form_data = {'name': ssid,
'zone': 'external',
'ssid': ssid,
'mode': 'infrastructure',
'auth_mode': 'wpa',
'ipv4_method': 'auto'}
if request.method == 'POST':
form = AddWifiForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
zone = form.cleaned_data['zone']
ssid = form.cleaned_data['ssid']
mode = form.cleaned_data['mode']
auth_mode = form.cleaned_data['auth_mode']
passphrase = form.cleaned_data['passphrase']
ipv4_method = form.cleaned_data['ipv4_method']
ipv4_address = form.cleaned_data['ipv4_address']
network.add_wifi_connection(
name, zone,
ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address)
return redirect(reverse_lazy('networks:index'))
else:
form = AddWifiForm(form_data)
return TemplateResponse(request, 'connections_create.html',
{'title': _('Connect to Wi-Fi Network'),
'subsubmenu': subsubmenu,
'form': form})
'access_points': access_points})
@login_required
@ -230,10 +190,10 @@ def add(request):
if request.method == 'POST':
form = ConnectionTypeSelectForm(request.POST)
if form.is_valid():
conn_type = form.cleaned_data['conn_type']
if conn_type == '802-3-ethernet':
connection_type = form.cleaned_data['connection_type']
if connection_type == '802-3-ethernet':
return redirect(reverse_lazy('networks:add_ethernet'))
elif conn_type == '802-11-wireless':
elif connection_type == '802-11-wireless':
return redirect(reverse_lazy('networks:add_wifi'))
else:
form = ConnectionTypeSelectForm()
@ -264,15 +224,24 @@ def add_ethernet(request):
form = AddEthernetForm()
return TemplateResponse(request, 'connections_create.html',
{'title': _('Editing New Ethernet Connection'),
{'title': _('Adding New Ethernet Connection'),
'subsubmenu': subsubmenu,
'form': form})
@login_required
def add_wifi(request):
def add_wifi(request, ssid=None):
"""Serve wifi connection create form."""
form = None
form_data = None
if ssid:
form_data = {'name': ssid,
'zone': 'external',
'ssid': ssid,
'mode': 'infrastructure',
'auth_mode': 'wpa',
'ipv4_method': 'auto'}
if request.method == 'POST':
form = AddWifiForm(request.POST)
@ -292,10 +261,13 @@ def add_wifi(request):
ipv4_method, ipv4_address)
return redirect(reverse_lazy('networks:index'))
else:
form = AddWifiForm()
if form_data:
form = AddWifiForm(form_data)
else:
form = AddWifiForm()
return TemplateResponse(request, 'connections_create.html',
{'title': _('Editing New Wi-Fi Connection'),
{'title': _('Adding New Wi-Fi Connection'),
'subsubmenu': subsubmenu,
'form': form})

View File

@ -25,14 +25,18 @@
<div class="row">
<div class="col-sm-6">
<div class="list-group">
{% for ap in aps %}
{% for access_point in access_points %}
<div class="list-group-item clearfix">
{% if access_point.ssid %}
<a display="inline-block" width="40%"
href="{% url 'networks:connect' ap.connect_path %}">
{{ ap.ssid }}
href="{% url 'networks:add_wifi' access_point.ssid %}">
{{ access_point.ssid }}
</a>
{% else %}
--
{% endif %}
<span class="btn btn-primary btn-xs pull-right">
{{ ap.strength }}%
{{ access_point.strength }}%
</span>
</div>
{% endfor %}

View File

@ -32,11 +32,10 @@ urlpatterns = patterns(
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/deactivate/$',
'deactivate', name='deactivate'),
url(r'^sys/networks/scan/$', 'scan', name='scan'),
url(r'^sys/networks/connect/(?P<connect_path>[\w.@+-]+)/$',
'connect', name='connect'),
url(r'^sys/networks/add/$', 'add', name='add'),
url(r'^sys/networks/add/ethernet/$', 'add_ethernet', name='add_ethernet'),
url(r'^sys/networks/add/wifi/$', 'add_wifi', name='add_wifi'),
url(r'^sys/networks/add/wifi/(?:(?P<ssid>[^/]+)/)?$', 'add_wifi',
name='add_wifi'),
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/delete/$',
'delete', name='delete'),
)

View File

@ -23,7 +23,6 @@ from dbus.exceptions import DBusException
import logging
import NetworkManager
import uuid
import urllib
logger = logging.getLogger(__name__)
@ -102,39 +101,54 @@ def get_active_connection(uuid):
raise ConnectionNotFound(uuid)
def edit_ethernet_connection(conn, name, zone, ipv4_method, ipv4_address):
settings = conn.GetSettings()
new_settings = {
def _create_ethernet_settings(uuid, name, zone, ipv4_method, ipv4_address):
"""Create an Ethernet setting structure in network manager format."""
settings = {
'connection': {
'id': name,
'type': settings['connection']['type'],
'type': '802-3-ethernet',
'zone': zone,
'uuid': settings['connection']['uuid'],
'uuid': uuid,
},
'802-3-ethernet': {},
'ipv4': {'method': ipv4_method},
}
if ipv4_method == 'manual' and ipv4_address:
new_settings['ipv4']['addresses'] = [
settings['ipv4']['addresses'] = [
(ipv4_address,
24, # CIDR prefix length
'0.0.0.0')] # gateway
conn.Update(new_settings)
return settings
def edit_wifi_connection(conn, name, zone,
ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address):
settings = conn.GetSettings()
def add_ethernet_connection(name, zone, ipv4_method, ipv4_address):
"""Add an automatic ethernet connection in network manager."""
settings = _create_ethernet_settings(
str(uuid.uuid4()), name, zone, ipv4_method, ipv4_address)
NetworkManager.Settings.AddConnection(settings)
return settings
new_settings = {
def edit_ethernet_connection(connection, name, zone, ipv4_method,
ipv4_address):
"""Edit an existing ethernet connection in network manager."""
settings = connection.GetSettings()
new_settings = _create_ethernet_settings(
settings['connection']['uuid'], name, zone, ipv4_method, ipv4_address)
connection.Update(new_settings)
def _create_wifi_settings(uuid, name, zone, ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address):
"""Create a Wi-Fi settings structure in network manager format."""
settings = {
'connection': {
'id': name,
'type': settings['connection']['type'],
'type': '802-11-wireless',
'zone': zone,
'uuid': settings['connection']['uuid'],
'uuid': uuid,
},
'802-11-wireless': {
'ssid': ssid,
@ -144,19 +158,41 @@ def edit_wifi_connection(conn, name, zone,
}
if auth_mode == 'wpa' and passphrase:
new_settings['connection']['security'] = '802-11-wireless-security'
new_settings['802-11-wireless-security'] = {
settings['connection']['security'] = '802-11-wireless-security'
settings['802-11-wireless-security'] = {
'key-mgmt': 'wpa-psk',
'psk': passphrase,
}
if ipv4_method == 'manual' and ipv4_address:
new_settings['ipv4']['addresses'] = [
settings['ipv4']['addresses'] = [
(ipv4_address,
24, # CIDR prefix length
'0.0.0.0')] # gateway
conn.Update(new_settings)
return settings
def add_wifi_connection(name, zone,
ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address):
"""Add an automatic Wi-Fi connection in network manager."""
settings = _create_wifi_settings(
str(uuid.uuid4()), name, zone, ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address)
NetworkManager.Settings.AddConnection(settings)
return settings
def edit_wifi_connection(connection, name, zone,
ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address):
"""Edit an existing wifi connection in network manager."""
settings = connection.GetSettings()
new_settings = _create_wifi_settings(
settings['connection']['uuid'], name, zone, ssid, mode, auth_mode,
passphrase, ipv4_method, ipv4_address)
connection.Update(new_settings)
def activate_connection(uuid):
@ -198,74 +234,27 @@ def deactivate_connection(name):
return active_connection
def add_ethernet_connection(name, zone, ipv4_method, ipv4_address):
conn = {
'connection': {
'id': name,
'type': '802-3-ethernet',
'zone': zone,
'uuid': str(uuid.uuid4()),
},
'802-3-ethernet': {},
'ipv4': {'method': ipv4_method},
}
def delete_connection(uuid):
"""Delete an exiting connection from network manager.
if ipv4_method == 'manual' and ipv4_address:
conn['ipv4']['addresses'] = [
(ipv4_address,
24, # CIDR prefix length
'0.0.0.0')] # gateway
NetworkManager.Settings.AddConnection(conn)
def add_wifi_connection(name, zone,
ssid, mode, auth_mode, passphrase,
ipv4_method, ipv4_address):
conn = {
'connection': {
'id': name,
'type': '802-11-wireless',
'zone': zone,
'uuid': str(uuid.uuid4()),
},
'802-11-wireless': {
'ssid': ssid,
'mode': mode,
},
'ipv4': {'method': ipv4_method},
}
if auth_mode == 'wpa' and passphrase:
conn['connection']['security'] = '802-11-wireless-security'
conn['802-11-wireless-security'] = {
'key-mgmt': 'wpa-psk',
'psk': passphrase,
}
if ipv4_method == 'manual' and ipv4_address:
conn['ipv4']['addresses'] = [
(ipv4_address,
24, # CIDR prefix length
'0.0.0.0')] # gateway
NetworkManager.Settings.AddConnection(conn)
def delete_connection(name):
connection = get_connection(name)
Raise ConnectionNotFound if connection does not exist.
"""
connection = get_connection(uuid)
name = connection.GetSettings()['connection']['id']
connection.Delete()
return name
def wifi_scan():
aps = []
for dev in NetworkManager.NetworkManager.GetDevices():
if dev.DeviceType != NetworkManager.NM_DEVICE_TYPE_WIFI:
"""Scan for available access points across all Wi-Fi devices."""
access_points = []
for device in NetworkManager.NetworkManager.GetDevices():
if device.DeviceType != NetworkManager.NM_DEVICE_TYPE_WIFI:
continue
for ap in dev.SpecificDevice().GetAccessPoints():
aps.append({'ssid': ap.Ssid,
'connect_path': urllib.parse.quote_plus(ap.Ssid),
'strength': ord(ap.Strength)})
return aps
for access_point in device.SpecificDevice().GetAllAccessPoints():
access_points.append({
'ssid': access_point.Ssid,
'strength': access_point.Strength})
return access_points