Newer
Older
Eliot Berriot
committed
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
Eliot Berriot
committed
import binascii
import os
Eliot Berriot
committed
import uuid
from django.conf import settings
from django.contrib.auth.models import AbstractUser
Eliot Berriot
committed
from django.db import models
Eliot Berriot
committed
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from funkwhale_api.common import fields, preferences
Eliot Berriot
committed
def get_token():
PERMISSIONS_CONFIGURATION = {
"federation": {
"label": "Manage library federation",
"help_text": "Follow other instances, accept/deny library follow requests...",
"library": {
"label": "Manage library",
"help_text": "Manage library, delete files, tracks, artists, albums...",
"settings": {"label": "Manage instance-level settings", "help_text": ""},
"upload": {"label": "Upload new content to the library", "help_text": ""},
}
PERMISSIONS = sorted(PERMISSIONS_CONFIGURATION.keys())
Eliot Berriot
committed
Eliot Berriot
committed
@python_2_unicode_compatible
class User(AbstractUser):
# First Name and Last Name do not cover name patterns
# around the globe.
name = models.CharField(_("Name of User"), blank=True, max_length=255)
Eliot Berriot
committed
# updated on logout or password change, to invalidate JWT
secret_key = models.UUIDField(default=uuid.uuid4, null=True)
privacy_level = fields.get_privacy_field()
# Unfortunately, Subsonic API assumes a MD5/password authentication
# scheme, which is weak in terms of security, and not achievable
# anyway since django use stronger schemes for storing passwords.
# Users that want to use the subsonic API from external client
# should set this token and use it as their password in such clients
subsonic_api_token = models.CharField(blank=True, null=True, max_length=255)
Eliot Berriot
committed
# permissions
permission_federation = models.BooleanField(
PERMISSIONS_CONFIGURATION["federation"]["label"],
help_text=PERMISSIONS_CONFIGURATION["federation"]["help_text"],
default=False,
)
permission_library = models.BooleanField(
PERMISSIONS_CONFIGURATION["library"]["label"],
help_text=PERMISSIONS_CONFIGURATION["library"]["help_text"],
default=False,
)
permission_settings = models.BooleanField(
PERMISSIONS_CONFIGURATION["settings"]["label"],
help_text=PERMISSIONS_CONFIGURATION["settings"]["help_text"],
default=False,
)
permission_upload = models.BooleanField(
PERMISSIONS_CONFIGURATION["upload"]["label"],
help_text=PERMISSIONS_CONFIGURATION["upload"]["help_text"],
default=False,
)
Eliot Berriot
committed
Eliot Berriot
committed
def __str__(self):
return self.username
Eliot Berriot
committed
def get_permissions(self):
defaults = preferences.get("users__default_permissions")
Eliot Berriot
committed
perms = {}
for p in PERMISSIONS:
self.is_superuser
or getattr(self, "permission_{}".format(p))
or p in defaults
Eliot Berriot
committed
perms[p] = v
return perms
def has_permissions(self, *perms, operator="and"):
if operator not in ["and", "or"]:
raise ValueError("Invalid operator {}".format(operator))
Eliot Berriot
committed
permissions = self.get_permissions()
return checker([permissions[p] for p in perms])
Eliot Berriot
committed
def get_absolute_url(self):
return reverse("users:detail", kwargs={"username": self.username})
Eliot Berriot
committed
def update_secret_key(self):
self.secret_key = uuid.uuid4()
return self.secret_key
def update_subsonic_api_token(self):
self.subsonic_api_token = get_token()
return self.subsonic_api_token
Eliot Berriot
committed
def set_password(self, raw_password):
super().set_password(raw_password)
self.update_secret_key()
if self.subsonic_api_token:
self.update_subsonic_api_token()
def get_activity_url(self):
return settings.FUNKWHALE_URL + "/@{}".format(self.username)