Skip to content
Snippets Groups Projects
Verified Commit 20eaa5e6 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Merge branch 'release/0.2.5'

parents 142a8050 5ac9d261
No related branches found
No related tags found
No related merge requests found
Showing
with 100 additions and 37 deletions
......@@ -13,14 +13,22 @@ stages:
test_api:
stage: test
image: funkwhale/funkwhale:base
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/pip-cache"
DATABASE_URL: "sqlite://"
before_script:
- python3 -m venv --copies virtualenv
- source virtualenv/bin/activate
- cd api
- pip install -r requirements/base.txt
- pip install -r requirements/local.txt
- pip install -r requirements/test.txt
script:
- pytest
variables:
DATABASE_URL: "sqlite://"
cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
paths:
- "$CI_PROJECT_DIR/pip-cache"
tags:
- docker
......
......@@ -2,10 +2,30 @@ Changelog
=========
0.2.5 (unreleased)
0.2.6 (Unreleased)
------------------
0.2.5 (2017-12-15)
------------------
Features:
- Import: can now specify search template when querying import sources (#45)
- Login form: now redirect to previous page after login (#2)
- 404: a decent 404 template, at least (#48)
Bugfixes:
- Player: better handling of errors when fetching the audio file (#46)
- Csrf: default CSRF_TRUSTED_ORIGINS to ALLOWED_HOSTS to avoid Csrf issues on admin (#49)
Tech:
- Django 2 compatibility, lot of packages upgrades (#47)
0.2.4 (2017-12-14)
------------------
......
......@@ -8,7 +8,9 @@ COPY ./requirements.apt /requirements.apt
RUN apt-get update -qq && grep "^[^#;]" requirements.apt | xargs apt-get install -y
COPY ./requirements /requirements
COPY ./requirements/base.txt /requirements
RUN pip install -r /requirements/base.txt
COPY ./requirements/production.txt /requirements
RUN pip install -r /requirements/production.txt
COPY . /app
......
......@@ -25,22 +25,32 @@ v1_patterns = router.urls
v1_patterns += [
url(r'^providers/',
include('funkwhale_api.providers.urls', namespace='providers')),
include(
('funkwhale_api.providers.urls', 'providers'),
namespace='providers')),
url(r'^favorites/',
include('funkwhale_api.favorites.urls', namespace='favorites')),
include(
('funkwhale_api.favorites.urls', 'favorites'),
namespace='favorites')),
url(r'^search$',
views.Search.as_view(), name='search'),
url(r'^radios/',
include('funkwhale_api.radios.urls', namespace='radios')),
include(
('funkwhale_api.radios.urls', 'radios'),
namespace='radios')),
url(r'^history/',
include('funkwhale_api.history.urls', namespace='history')),
include(
('funkwhale_api.history.urls', 'history'),
namespace='history')),
url(r'^users/',
include('funkwhale_api.users.api_urls', namespace='users')),
include(
('funkwhale_api.users.api_urls', 'users'),
namespace='users')),
url(r'^token/',
jwt_views.obtain_jwt_token),
url(r'^token/refresh/', jwt_views.refresh_jwt_token),
]
urlpatterns = [
url(r'^v1/', include(v1_patterns, namespace='v1'))
url(r'^v1/', include((v1_patterns, 'v1'), namespace='v1'))
]
......@@ -75,7 +75,7 @@ INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
# MIDDLEWARE CONFIGURATION
# ------------------------------------------------------------------------------
MIDDLEWARE_CLASSES = (
MIDDLEWARE = (
# Make sure djangosecure.middleware.SecurityMiddleware is listed first
'django.contrib.sessions.middleware.SessionMiddleware',
'funkwhale_api.users.middleware.AnonymousSessionMiddleware',
......
......@@ -31,7 +31,7 @@ EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND',
# django-debug-toolbar
# ------------------------------------------------------------------------------
MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
MIDDLEWARE += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
# INTERNAL_IPS = ('127.0.0.1', '10.0.2.2',)
......
......@@ -36,7 +36,7 @@ SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
#
#
# # Make sure djangosecure.middleware.SecurityMiddleware is listed first
# MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES
# MIDDLEWARE = SECURITY_MIDDLEWARE + MIDDLEWARE
#
# # set this to 60 seconds and then to 518400 when you can prove it works
# SECURE_HSTS_SECONDS = 60
......@@ -55,6 +55,8 @@ SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Hosts/domain names that are valid for this site
# See https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts
ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS')
CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
# END SITE CONFIGURATION
INSTALLED_APPS += ("gunicorn", )
......
......@@ -22,8 +22,8 @@ CACHES = {
'LOCATION': ''
}
}
INSTALLED_APPS += ('kombu.transport.django',)
BROKER_URL = 'django://'
BROKER_URL = 'memory://'
# TESTING
# ------------------------------------------------------------------------------
......
......@@ -10,9 +10,9 @@ from django.views import defaults as default_views
urlpatterns = [
# Django Admin, use {% url 'admin:index' %}
url(settings.ADMIN_URL, include(admin.site.urls)),
url(settings.ADMIN_URL, admin.site.urls),
url(r'^api/', include("config.api_urls", namespace="api")),
url(r'^api/', include(("config.api_urls", 'api'), namespace="api")),
url(r'^api/auth/', include('rest_auth.urls')),
url(r'^api/auth/registration/', include('funkwhale_api.users.rest_auth_urls')),
url(r'^accounts/', include('allauth.urls')),
......
# -*- coding: utf-8 -*-
__version__ = '0.2.4'
__version__ = '0.2.5'
__version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace('-', '.', 1).split('.')])
......@@ -7,5 +7,5 @@ class ConditionalAuthentication(BasePermission):
def has_permission(self, request, view):
if settings.API_AUTHENTICATION_REQUIRED:
return request.user and request.user.is_authenticated()
return request.user and request.user.is_authenticated
return True
......@@ -25,7 +25,7 @@ class Migration(migrations.Migration):
'ordering': ('domain',),
},
managers=[
(b'objects', django.contrib.sites.models.SiteManager()),
('objects', django.contrib.sites.models.SiteManager()),
],
),
]
......@@ -19,8 +19,8 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('creation_date', models.DateTimeField(default=django.utils.timezone.now)),
('track', models.ForeignKey(related_name='track_favorites', to='music.Track')),
('user', models.ForeignKey(related_name='track_favorites', to=settings.AUTH_USER_MODEL)),
('track', models.ForeignKey(related_name='track_favorites', to='music.Track', on_delete=models.CASCADE)),
('user', models.ForeignKey(related_name='track_favorites', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
options={
'ordering': ('-creation_date',),
......
......@@ -5,8 +5,10 @@ from funkwhale_api.music.models import Track
class TrackFavorite(models.Model):
creation_date = models.DateTimeField(default=timezone.now)
user = models.ForeignKey('users.User', related_name='track_favorites')
track = models.ForeignKey(Track, related_name='track_favorites')
user = models.ForeignKey(
'users.User', related_name='track_favorites', on_delete=models.CASCADE)
track = models.ForeignKey(
Track, related_name='track_favorites', on_delete=models.CASCADE)
class Meta:
unique_together = ('track', 'user')
......
import json
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from django.urls import reverse
from funkwhale_api.music.models import Track, Artist
from funkwhale_api.favorites.models import TrackFavorite
......
......@@ -20,8 +20,8 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
('end_date', models.DateTimeField(null=True, blank=True, default=django.utils.timezone.now)),
('session_key', models.CharField(null=True, blank=True, max_length=100)),
('track', models.ForeignKey(related_name='listenings', to='music.Track')),
('user', models.ForeignKey(blank=True, null=True, related_name='listenings', to=settings.AUTH_USER_MODEL)),
('track', models.ForeignKey(related_name='listenings', to='music.Track', on_delete=models.CASCADE)),
('user', models.ForeignKey(blank=True, null=True, related_name='listenings', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
options={
'ordering': ('-end_date',),
......
......@@ -7,8 +7,14 @@ from funkwhale_api.music.models import Track
class Listening(models.Model):
end_date = models.DateTimeField(default=timezone.now, null=True, blank=True)
track = models.ForeignKey(Track, related_name="listenings")
user = models.ForeignKey('users.User', related_name="listenings", null=True, blank=True)
track = models.ForeignKey(
Track, related_name="listenings", on_delete=models.CASCADE)
user = models.ForeignKey(
'users.User',
related_name="listenings",
null=True,
blank=True,
on_delete=models.CASCADE)
session_key = models.CharField(max_length=100, null=True, blank=True)
class Meta:
......
import factory
from funkwhale_api.music.tests import factories
from funkwhale_api.users.tests.factories import UserFactory
class ListeningFactory(factory.django.DjangoModelFactory):
user = factory.SubFactory(UserFactory)
track = factory.SubFactory(factories.TrackFactory)
class Meta:
model = 'history.Listening'
import random
import json
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.core.exceptions import ValidationError
from django.utils import timezone
from model_mommy import mommy
from funkwhale_api.music.tests.factories import TrackFactory
from funkwhale_api.users.models import User
from funkwhale_api.history import models
class TestHistory(TestCase):
def setUp(self):
......@@ -17,12 +18,12 @@ class TestHistory(TestCase):
self.user = User.objects.create_user(username='test', email='test@test.com', password='test')
def test_can_create_listening(self):
track = mommy.make('music.Track')
track = TrackFactory()
now = timezone.now()
l = models.Listening.objects.create(user=self.user, track=track)
def test_anonymous_user_can_create_listening_via_api(self):
track = mommy.make('music.Track')
track = TrackFactory()
url = self.reverse('api:v1:history:listenings-list')
response = self.client.post(url, {
'track': track.pk,
......@@ -34,7 +35,7 @@ class TestHistory(TestCase):
self.assertIsNotNone(listening.session_key)
def test_logged_in_user_can_create_listening_via_api(self):
track = mommy.make('music.Track')
track = TrackFactory()
self.client.login(username=self.user.username, password='test')
......
......@@ -22,14 +22,14 @@ class ListeningViewSet(mixins.CreateModelMixin,
def get_queryset(self):
queryset = super().get_queryset()
if self.request.user.is_authenticated():
if self.request.user.is_authenticated:
return queryset.filter(user=self.request.user)
else:
return queryset.filter(session_key=self.request.session.session_key)
def get_serializer_context(self):
context = super().get_serializer_context()
if self.request.user.is_authenticated():
if self.request.user.is_authenticated:
context['user'] = self.request.user
else:
context['session_key'] = self.request.session.session_key
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment