Commit ba5e674c authored by Valentin Samir's avatar Valentin Samir

[tv] Gestion de la réauthentification et commentaires

parent 4eabd056
......@@ -37,7 +37,15 @@ BASE_IMAGE_URL = gestion.config.tv.BASE_IMAGE_URL
IMAGE_SUFFIX = gestion.config.tv.IMAGE_SUFFIX
SMALL_IMAGE_SUFFIX = gestion.config.tv.SMALL_IMAGE_SUFFIX
def radio_password(user, radio=""):
"""Génère (de façon déterministe) un mot de passe pour un (utilisateur, station radio"""
if radio.startswith("/"):
radio = radio[1:]
hash = hashlib.md5("%s~%s~%s~%s" % (user.username, datetime.datetime.now().date(), settings.SECRET_KEY, radio))
return hash.hexdigest()
def get_client_ip(request):
"""Retourne l'ip source d'une requête"""
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
......@@ -52,6 +60,7 @@ def image_url_for_channel(channel_ip, small=0 ):
return BASE_IMAGE_URL + str(channel_ip) + SMALL_IMAGE_SUFFIX
def chaines():
"""Retourne le dico des chaines disponibles en multicast"""
try:
multicast=pickle.load(open(SAP_FILE_URL))
for group in multicast.keys():
......@@ -61,15 +70,25 @@ def chaines():
return {}
def check_local(request):
"""Vérifie si une ip est locale au réseaux crans"""
ip=ipaddr.IPAddress(get_client_ip(request))
return True in [ip in net for net in net_crans]
def check_local_or_logged(request):
ip=ipaddr.IPAddress(get_client_ip(request))
return True in [ip in net for net in net_crans] or request.user.is_authenticated()
"""ip locale ou user authentifié"""
return check_local(request) or request.user.is_authenticated()
@request_passes_test(check_local_or_logged)
def tv(request):
def tv(request, autoplay_type=None, autoplay_url=None):
"""Page d'index du module TV : affiches les chaines et stations radios disponibles"""
# Si rediriger avec de l'autoplay, on mémorise et cleanup l'url
if request.GET.get('autoplay_type', None) and request.GET.get('autoplay_url', None):
request.session['autoplay_type'] = request.GET['autoplay_type']
request.session['autoplay_url'] = request.GET['autoplay_url']
request.session['autoplay_volume'] = request.GET.get('autoplay_volume', '100')
return redirect("tv:index")
# TV uniquement en filaire
ip=ipaddr.IPAddress(get_client_ip(request))
if not True in [ip in net for net in net_tv]:
messages.warning(request, "Vous devez être connecté en filaire au réseau du Cr@ns pour pouvoir regarder la télévision.")
......@@ -88,7 +107,8 @@ def tv(request):
image_url_for_channel(ip),
reverse("tv:tv_playlist", kwargs={'tv': name})
) for (name, ip) in chaines().get('SAT', {}).items()]
# radio=[(name, "udp://@%s:1234" % tv_dns.idn(name, fqdn=True, charset=None), image_url_for_channel(ip)) for (name, ip) in chaines().get('Radio', {}).items()]
# Radio accessible de partout : ip crans en non connecté seulement
radio = []
user_auth = request.user.is_authenticated()
for (name, params) in tv_config.multicast['Radio'].items():
......@@ -102,15 +122,31 @@ def tv(request):
image_url_for_channel(params[1]),
reverse("tv:radio_playlist", kwargs={'radio': params[0]})),
)
# Tri des chaines case insensitif
key = lambda s: s[0].lower()
tnt.sort(key=key)
sat.sort(key=key)
radio.sort(key=key)
params={ 'tnt' : tnt, 'sat': sat, 'radio': radio, 'user': request.user }
# dico de params pour générer la page a partir du template
params={ 'tnt' : tnt, 'sat': sat, 'radio': radio, 'user': request.user,
'autoplay_type':request.session.get('autoplay_type', None),
'autoplay_url':request.session.get('autoplay_url', None),
'autoplay_volume':request.session.get('autoplay_volume', None),
}
# On oublie les paramètre autoplay
request.session['autoplay_type'] = None
request.session['autoplay_url'] = None
request.session['autoplay_volume'] = None
# Render de la page
return django.shortcuts.render_to_response("tv/index.html", params, context_instance=RequestContext(request))
@request_passes_test(check_local_or_logged)
def radio_playlist(request, radio):
"""Génère un fichier de playlist pour les stations radios"""
if radio in tv_config.multicast_tag["Radio"]:
if request.user.is_authenticated():
userpass = "%s:%s@" % (request.user.username, radio_password(request.user, radio))
......@@ -121,18 +157,14 @@ def radio_playlist(request, radio):
return redirect("tv:index")
def tv_playlist(request, tv):
"""Génère un fichier de playlist avec l'adresse multicast de la chaine"""
if check_local(request):
return HttpResponse("udp://@%s:1234\n" % tv_dns.idn(tv, fqdn=True, charset=None), content_type="audio/x-mpegurl")
else:
return redirect("tv:index")
def radio_password(user, radio=""):
if radio.startswith("/"):
radio = radio[1:]
hash = hashlib.md5("%s~%s~%s~%s" % (user.username, datetime.datetime.now().date(), settings.SECRET_KEY, radio))
return hash.hexdigest()
def get_radio_password(request, radio=""):
"""Transmet son mot de passe radio à l'utilisateur (en ajax)"""
if not request.user.is_authenticated():
return HttpResponseForbidden()
elif radio in tv_config.multicast_tag["Radio"]:
......@@ -142,6 +174,7 @@ def get_radio_password(request, radio=""):
@csrf_exempt
def icecast_auth(request):
"""API appelé par icecast pour vérifier les mots de passes"""
actions = ["mount_add", "mount_remove", "listener_add", "listener_remove"]
response = HttpResponse()
response["icecast-auth-user"]=1
......@@ -150,13 +183,18 @@ def icecast_auth(request):
POST = request.POST
if not POST["action"] in actions:
return HttpResponseForbidden()
# Un client tente d'accéder a un flux radio
if POST["action"] == "listener_add":
ip=ipaddr.IPAddress(POST["ip"])
# Si 127.0.0.1, l'ip viens du proxy local
if str(ip) == "127.0.0.1":
# On authentifie le proxy
if POST.get('ClientHeader.x-auth', '') != secrets.get("icecast-token"):
# untrust proxy
return HttpResponseForbidden()
else:
# Le proxy est authentifié, on lui fait confiance pour l'ip du client
ip = ipaddr.IPAddress(POST['ClientHeader.x-real-ip'])
# Si ip crans on accepte
if True in [ip in net for net in net_crans]:
......@@ -170,6 +208,7 @@ def icecast_auth(request):
return response
except User.DoesNotExist:
return HttpResponseForbidden()
# Pour les autres actions, toujours ok
else:
return response
return HttpResponseForbidden()
......@@ -75,7 +75,12 @@ function unwarn_vlc_plugin(){
}
}
function get_radio_password(radio) {
function redirect_autoplay_url(typ, url){
window.location.href = window.location.href.replace( /[\?#].*|$/, "" ) +
"?autoplay_type=" + typ + "&autoplay_url=" + encodeURIComponent(url) +
"&autoplay_volume=" + document.getElementById("volume_slide").value;
}
function get_radio_password(radio, url) {
password = "";
jQuery.ajax({
url: '/tv/radio/password/'
......@@ -93,7 +98,7 @@ function get_radio_password(radio) {
// 403 sir l'utilisateur n'est pas connecté
// on rafraîchissant la page, on va le rediriger vers la page de login
403: function(data) {
location.reload();
redirect_autoplay_url("radio", url)
},
},
async: false
......@@ -104,7 +109,7 @@ function get_radio_password(radio) {
function radio_url(url){
var a = $('<a>', { href:url } )[0];
if(a.username){
url = a.protocol + "//" + a.username + ":" + get_radio_password(a.pathname) + "@" + a.hostname + a.pathname;
url = a.protocol + "//" + a.username + ":" + get_radio_password(a.pathname, url) + "@" + a.hostname + a.pathname;
}
return url;
}
......
......@@ -67,6 +67,15 @@
</div>
<script language="Javascript">
init();
{% if autoplay_type == "radio" %}
play_radio('{{autoplay_url}}');
{% endif %}
{% if autoplay_type == "tv" %}
play('{{autoplay_url}}');
{% endif %}
{% if autoplay_volume %}
volume({{autoplay_volume}});
{% endif %}
</script>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment