Skip to content

Remove privacy app #2954

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions readthedocs/builds/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""Build and Version class model Managers"""

from __future__ import absolute_import

from django.db import models

from .constants import (BRANCH, TAG, LATEST, LATEST_VERBOSE_NAME, STABLE,
STABLE_VERBOSE_NAME)
from .querysets import VersionQuerySet
from readthedocs.core.utils.extend import (SettingsOverrideObject,
get_override_class)


__all__ = ['VersionManager']


class VersionManagerBase(models.Manager):

"""Version manager for manager only queries

For queries not suitable for the :py:cls:`VersionQuerySet`, such as create
queries.
"""

@classmethod
def from_queryset(cls, queryset_class, class_name=None):
# This is overridden because :py:meth:`models.Manager.from_queryset`
# uses `inspect` to retrieve the class methods, and the proxy class has
# no direct members.
queryset_class = get_override_class(
VersionQuerySet,
VersionQuerySet._default_class # pylint: disable=protected-access
)
return super(VersionManagerBase, cls).from_queryset(queryset_class, class_name)

def create_stable(self, **kwargs):
defaults = {
'slug': STABLE,
'verbose_name': STABLE_VERBOSE_NAME,
'machine': True,
'active': True,
'identifier': STABLE,
'type': TAG,
}
defaults.update(kwargs)
return self.create(**defaults)

def create_latest(self, **kwargs):
defaults = {
'slug': LATEST,
'verbose_name': LATEST_VERBOSE_NAME,
'machine': True,
'active': True,
'identifier': LATEST,
'type': BRANCH,
}
defaults.update(kwargs)
return self.create(**defaults)


class VersionManager(SettingsOverrideObject):
_default_class = VersionManagerBase
_override_setting = 'VERSION_MANAGER'
23 changes: 11 additions & 12 deletions readthedocs/builds/models.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
"""Models for the builds app."""

from __future__ import absolute_import
from builtins import object

import logging
import re
import os.path
import re
from shutil import rmtree

from django.core.urlresolvers import reverse
from builtins import object
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _, ugettext

from guardian.shortcuts import assign
from taggit.managers import TaggableManager

from readthedocs.core.utils import broadcast
from readthedocs.privacy.backend import VersionQuerySet, VersionManager
from readthedocs.privacy.loader import RelatedBuildQuerySet, BuildQuerySet
from readthedocs.projects.models import Project
from readthedocs.projects.constants import (PRIVACY_CHOICES, GITHUB_URL,
GITHUB_REGEXS, BITBUCKET_URL,
BITBUCKET_REGEXS, PRIVATE)

from .constants import (BUILD_STATE, BUILD_TYPES, VERSION_TYPES,
LATEST, NON_REPOSITORY_VERSIONS, STABLE,
BUILD_STATE_FINISHED, BRANCH, TAG)
from .managers import VersionManager
from .querysets import BuildQuerySet, RelatedBuildQuerySet, VersionQuerySet
from .version_slug import VersionSlugField
from readthedocs.core.utils import broadcast
from readthedocs.projects.constants import (PRIVACY_CHOICES, GITHUB_URL,
GITHUB_REGEXS, BITBUCKET_URL,
BITBUCKET_REGEXS, PRIVATE)
from readthedocs.projects.models import Project


DEFAULT_VERSION_PRIVACY_LEVEL = getattr(settings, 'DEFAULT_VERSION_PRIVACY_LEVEL', 'public')
Expand Down
140 changes: 140 additions & 0 deletions readthedocs/builds/querysets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""Build and Version QuerySet classes"""

from __future__ import absolute_import

from django.db import models
from guardian.shortcuts import get_objects_for_user

from readthedocs.core.utils.extend import SettingsOverrideObject
from readthedocs.projects import constants


__all__ = ['VersionQuerySet', 'BuildQuerySet', 'RelatedBuildQuerySet']


class VersionQuerySetBase(models.QuerySet):

"""Versions take into account their own privacy_level setting."""

use_for_related_fields = True

def _add_user_repos(self, queryset, user):
if user.has_perm('builds.view_version'):
return self.all().distinct()
if user.is_authenticated():
user_queryset = get_objects_for_user(user, 'builds.view_version')
queryset = user_queryset | queryset
return queryset.distinct()

def public(self, user=None, project=None, only_active=True):
queryset = self.filter(privacy_level=constants.PUBLIC)
if user:
queryset = self._add_user_repos(queryset, user)
if project:
queryset = queryset.filter(project=project)
if only_active:
queryset = queryset.filter(active=True)
return queryset

def protected(self, user=None, project=None, only_active=True):
queryset = self.filter(privacy_level__in=[constants.PUBLIC, constants.PROTECTED])
if user:
queryset = self._add_user_repos(queryset, user)
if project:
queryset = queryset.filter(project=project)
if only_active:
queryset = queryset.filter(active=True)
return queryset

def private(self, user=None, project=None, only_active=True):
queryset = self.filter(privacy_level__in=[constants.PRIVATE])
if user:
queryset = self._add_user_repos(queryset, user)
if project:
queryset = queryset.filter(project=project)
if only_active:
queryset = queryset.filter(active=True)
return queryset

def api(self, user=None):
return self.public(user, only_active=False)

def for_project(self, project):
"""Return all versions for a project, including translations"""
return self.filter(
models.Q(project=project) |
models.Q(project__main_language_project=project)
)


class VersionQuerySet(SettingsOverrideObject):
_default_class = VersionQuerySetBase


class BuildQuerySetBase(models.QuerySet):

"""
Build objects that are privacy aware.

i.e. they take into account the privacy of the Version that they relate to.
"""

use_for_related_fields = True

def _add_user_repos(self, queryset, user=None):
if user.has_perm('builds.view_version'):
return self.all().distinct()
if user.is_authenticated():
user_queryset = get_objects_for_user(user, 'builds.view_version')
pks = [p.pk for p in user_queryset]
queryset = self.filter(version__pk__in=pks) | queryset
return queryset.distinct()

def public(self, user=None, project=None):
queryset = self.filter(version__privacy_level=constants.PUBLIC)
if user:
queryset = self._add_user_repos(queryset, user)
if project:
queryset = queryset.filter(project=project)
return queryset

def api(self, user=None):
return self.public(user)


class BuildQuerySet(SettingsOverrideObject):
_default_class = BuildQuerySetBase
_override_setting = 'BUILD_MANAGER'


class RelatedBuildQuerySetBase(models.QuerySet):

"""For models with association to a project through :py:class:`Build`"""

use_for_related_fields = True

def _add_user_repos(self, queryset, user=None):
if user.has_perm('builds.view_version'):
return self.all().distinct()
if user.is_authenticated():
user_queryset = get_objects_for_user(user, 'builds.view_version')
pks = [p.pk for p in user_queryset]
queryset = self.filter(
build__version__pk__in=pks) | queryset
return queryset.distinct()

def public(self, user=None, project=None):
queryset = self.filter(build__version__privacy_level=constants.PUBLIC)
if user:
queryset = self._add_user_repos(queryset, user)
if project:
queryset = queryset.filter(build__project=project)
return queryset

def api(self, user=None):
return self.public(user)


class RelatedBuildQuerySet(SettingsOverrideObject):
_default_class = RelatedBuildQuerySetBase
_override_setting = 'RELATED_BUILD_MANAGER'
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
"""Classes allowing copying files around.
"""Classes to copy files between build and web servers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Believe this file rename will need to change in our prod settings too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup! I got a PR on ops, but it needs to be updated as it's conflicting with the other PR you opened around Syncers


"Syncers" copy files from the local machine, while "Pullers" copy files to
the local machine.

"""

from __future__ import absolute_import
from builtins import object

import getpass
import logging
import os
import shutil

from builtins import object
from django.conf import settings

from readthedocs.core.utils.extend import SettingsOverrideObject


log = logging.getLogger(__name__)


Expand Down Expand Up @@ -135,3 +139,8 @@ def copy(cls, path, target, host, is_file=False, **__):
ret = os.system(sync_cmd)
if ret != 0:
log.info("COPY ERROR to app servers.")


class Syncer(SettingsOverrideObject):
_default_class = LocalSyncer
_override_setting = 'FILE_SYNCER'
21 changes: 21 additions & 0 deletions readthedocs/core/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Objects for User permission checks"""

from __future__ import absolute_import

from readthedocs.core.utils.extend import SettingsOverrideObject


class AdminPermissionBase(object):

@classmethod
def is_admin(cls, user, project):
return user in project.users.all()

@classmethod
def is_member(cls, user, obj):
return user in obj.users.all()


class AdminPermission(SettingsOverrideObject):
_default_class = AdminPermissionBase
_override_setting = 'ADMIN_PERMISSION'
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""Template tags to query projects by privacy."""

from __future__ import absolute_import
from django import template

from ..loader import AdminPermission
from django import template

from readthedocs.core.permissions import AdminPermission
from readthedocs.projects.models import Project


register = template.Library()


Expand Down
4 changes: 2 additions & 2 deletions readthedocs/core/views/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
from readthedocs.builds.models import Version
from readthedocs.projects import constants
from readthedocs.projects.models import Project, ProjectRelationship
from readthedocs.core.symlink import PrivateSymlink, PublicSymlink
from readthedocs.core.permissions import AdminPermission
from readthedocs.core.resolver import resolve, resolve_path
from readthedocs.privacy.loader import AdminPermission
from readthedocs.core.symlink import PrivateSymlink, PublicSymlink

import mimetypes
import os
Expand Down
12 changes: 0 additions & 12 deletions readthedocs/oauth/managers.py

This file was deleted.

2 changes: 1 addition & 1 deletion readthedocs/oauth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from readthedocs.projects.constants import REPO_CHOICES
from readthedocs.projects.models import Project

from .managers import RemoteRepositoryQuerySet, RemoteOrganizationQuerySet
from .querysets import RemoteRepositoryQuerySet, RemoteOrganizationQuerySet


DEFAULT_PRIVACY_LEVEL = getattr(settings, 'DEFAULT_PRIVACY_LEVEL', 'public')
Expand Down
31 changes: 31 additions & 0 deletions readthedocs/oauth/querysets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Managers for OAuth models"""

from __future__ import absolute_import

from django.db import models

from readthedocs.core.utils.extend import SettingsOverrideObject


class RelatedUserQuerySetBase(models.QuerySet):

"""For models with relations through :py:class:`User`"""

def api(self, user=None):
"""Return objects for user"""
if not user.is_authenticated():
return self.none()
return self.filter(users=user)


class RelatedUserQuerySet(SettingsOverrideObject):
_default_class = RelatedUserQuerySetBase
_override_setting = 'RELATED_USER_MANAGER'


class RemoteRepositoryQuerySet(RelatedUserQuerySet):
pass


class RemoteOrganizationQuerySet(RelatedUserQuerySet):
pass
Empty file removed readthedocs/privacy/__init__.py
Empty file.
Loading