[Update] 修改get_current_org 为 proxy对象 current_org

pull/1571/head
ibuler 2018-07-20 17:49:47 +08:00
parent b5f6f80ae6
commit e3aa18ff2d
18 changed files with 171 additions and 34 deletions

View File

@ -22,7 +22,6 @@ from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from common.utils import get_logger, get_object_or_none from common.utils import get_logger, get_object_or_none
from orgs.utils import get_current_org
from ..hands import IsSuperUser from ..hands import IsSuperUser
from ..models import Node from ..models import Node
from ..tasks import update_assets_hardware_info_util, test_asset_connectability_util from ..tasks import update_assets_hardware_info_util, test_asset_connectability_util

View File

@ -7,7 +7,7 @@ from django.db.models import Q
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orgs.mixins import OrgModelMixin from orgs.mixins import OrgModelMixin
from orgs.utils import get_current_org, set_current_org from orgs.utils import current_org, set_current_org
from orgs.models import Organization from orgs.models import Organization
__all__ = ['Node'] __all__ = ['Node']
@ -170,13 +170,12 @@ class Node(OrgModelMixin):
@classmethod @classmethod
def create_root_node(cls): def create_root_node(cls):
with transaction.atomic(): with transaction.atomic():
org = get_current_org()
set_current_org(Organization.root()) set_current_org(Organization.root())
org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$') org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$')
org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True) org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True)
max_value = max([int(k) for k in org_nodes_roots_keys]) if org_nodes_roots_keys else 0 max_value = max([int(k) for k in org_nodes_roots_keys]) if org_nodes_roots_keys else 0
set_current_org(org) set_current_org(current_org)
root = cls.objects.create(key=max_value+1, value=org.name) root = cls.objects.create(key=max_value+1, value=current_org.name)
return root return root
@classmethod @classmethod

View File

@ -721,9 +721,7 @@ $(document).ready(function(){
return return
} }
var data = { var data = {'assets': assets_selected};
'assets': assets_selected
};
var success = function () { var success = function () {
asset_table2.selected = []; asset_table2.selected = [];
asset_table2.ajax.reload() asset_table2.ajax.reload()

View File

@ -211,7 +211,7 @@ class AssetExportView(View):
fields = [ fields = [
field for field in Asset._meta.fields field for field in Asset._meta.fields
if field.name not in [ if field.name not in [
'date_created' 'date_created', 'org_id'
] ]
] ]
filename = 'assets-{}.csv'.format( filename = 'assets-{}.csv'.format(

View File

@ -17,6 +17,7 @@ import threading
from io import StringIO from io import StringIO
import uuid import uuid
from functools import wraps from functools import wraps
import copy
import paramiko import paramiko
import sshpubkeys import sshpubkeys
@ -410,3 +411,122 @@ def with_cache(func):
cache[key] = res cache[key] = res
return res return res
return wrapper return wrapper
class LocalProxy(object):
"""
Copy from werkzeug.local.LocalProxy
"""
__slots__ = ('__local', '__dict__', '__name__', '__wrapped__')
def __init__(self, local, name=None):
object.__setattr__(self, '_LocalProxy__local', local)
object.__setattr__(self, '__name__', name)
if callable(local) and not hasattr(local, '__release_local__'):
# "local" is a callable that is not an instance of Local or
# LocalManager: mark it as a wrapped function.
object.__setattr__(self, '__wrapped__', local)
def _get_current_object(self):
"""Return the current object. This is useful if you want the real
object behind the proxy at a time for performance reasons or because
you want to pass the object into a different context.
"""
if not hasattr(self.__local, '__release_local__'):
return self.__local()
try:
return getattr(self.__local, self.__name__)
except AttributeError:
raise RuntimeError('no object bound to %s' % self.__name__)
@property
def __dict__(self):
try:
return self._get_current_object().__dict__
except RuntimeError:
raise AttributeError('__dict__')
def __repr__(self):
try:
obj = self._get_current_object()
except RuntimeError:
return '<%s unbound>' % self.__class__.__name__
return repr(obj)
def __bool__(self):
try:
return bool(self._get_current_object())
except RuntimeError:
return False
def __dir__(self):
try:
return dir(self._get_current_object())
except RuntimeError:
return []
def __getattr__(self, name):
if name == '__members__':
return dir(self._get_current_object())
return getattr(self._get_current_object(), name)
def __setitem__(self, key, value):
self._get_current_object()[key] = value
def __delitem__(self, key):
del self._get_current_object()[key]
__setattr__ = lambda x, n, v: setattr(x._get_current_object(), n, v)
__delattr__ = lambda x, n: delattr(x._get_current_object(), n)
__str__ = lambda x: str(x._get_current_object())
__lt__ = lambda x, o: x._get_current_object() < o
__le__ = lambda x, o: x._get_current_object() <= o
__eq__ = lambda x, o: x._get_current_object() == o
__ne__ = lambda x, o: x._get_current_object() != o
__gt__ = lambda x, o: x._get_current_object() > o
__ge__ = lambda x, o: x._get_current_object() >= o
__cmp__ = lambda x, o: cmp(x._get_current_object(), o) # noqa
__hash__ = lambda x: hash(x._get_current_object())
__call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw)
__len__ = lambda x: len(x._get_current_object())
__getitem__ = lambda x, i: x._get_current_object()[i]
__iter__ = lambda x: iter(x._get_current_object())
__contains__ = lambda x, i: i in x._get_current_object()
__add__ = lambda x, o: x._get_current_object() + o
__sub__ = lambda x, o: x._get_current_object() - o
__mul__ = lambda x, o: x._get_current_object() * o
__floordiv__ = lambda x, o: x._get_current_object() // o
__mod__ = lambda x, o: x._get_current_object() % o
__divmod__ = lambda x, o: x._get_current_object().__divmod__(o)
__pow__ = lambda x, o: x._get_current_object() ** o
__lshift__ = lambda x, o: x._get_current_object() << o
__rshift__ = lambda x, o: x._get_current_object() >> o
__and__ = lambda x, o: x._get_current_object() & o
__xor__ = lambda x, o: x._get_current_object() ^ o
__or__ = lambda x, o: x._get_current_object() | o
__div__ = lambda x, o: x._get_current_object().__div__(o)
__truediv__ = lambda x, o: x._get_current_object().__truediv__(o)
__neg__ = lambda x: -(x._get_current_object())
__pos__ = lambda x: +(x._get_current_object())
__abs__ = lambda x: abs(x._get_current_object())
__invert__ = lambda x: ~(x._get_current_object())
__complex__ = lambda x: complex(x._get_current_object())
__int__ = lambda x: int(x._get_current_object())
__float__ = lambda x: float(x._get_current_object())
__oct__ = lambda x: oct(x._get_current_object())
__hex__ = lambda x: hex(x._get_current_object())
__index__ = lambda x: x._get_current_object().__index__()
__coerce__ = lambda x, o: x._get_current_object().__coerce__(x, o)
__enter__ = lambda x: x._get_current_object().__enter__()
__exit__ = lambda x, *a, **kw: x._get_current_object().__exit__(*a, **kw)
__radd__ = lambda x, o: o + x._get_current_object()
__rsub__ = lambda x, o: o - x._get_current_object()
__rmul__ = lambda x, o: o * x._get_current_object()
__rdiv__ = lambda x, o: o / x._get_current_object()
__rtruediv__ = __rdiv__
__rfloordiv__ = lambda x, o: o // x._get_current_object()
__rmod__ = lambda x, o: o % x._get_current_object()
__rdivmod__ = lambda x, o: x._get_current_object().__rdivmod__(o)
__copy__ = lambda x: copy.copy(x._get_current_object())
__deepcopy__ = lambda x, memo: copy.deepcopy(x._get_current_object(), memo)

View File

@ -22,7 +22,7 @@ class IndexView(LoginRequiredMixin, OrgViewGenericMixin, TemplateView):
session_month_dates_archive = [] session_month_dates_archive = []
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if not request.user.is_superuser: if not request.user.is_org_admin:
return redirect('assets:user-asset-list') return redirect('assets:user-asset-list')
return super(IndexView, self).get(request, *args, **kwargs) return super(IndexView, self).get(request, *args, **kwargs)

View File

@ -1,14 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .utils import get_current_org from .utils import current_org, get_current_org
from .models import Organization from .models import Organization
def org_processor(request): def org_processor(request):
print('Crernt Org', current_org.name)
context = { context = {
'ADMIN_ORGS': Organization.get_user_admin_orgs(request.user), 'ADMIN_ORGS': Organization.get_user_admin_orgs(request.user),
'CURRENT_ORG': get_current_org(), 'CURRENT_ORG': get_current_org(),
'HAS_ORG_PERM': current_org.can_admin_by(request.user),
} }
return context return context

View File

@ -4,9 +4,10 @@ from django.db import models
from django.shortcuts import redirect from django.shortcuts import redirect
import warnings import warnings
from django.forms import ModelForm from django.forms import ModelForm
from django.http.response import HttpResponseForbidden
from common.utils import get_logger from common.utils import get_logger
from .utils import get_current_org, set_current_org from .utils import current_org, set_current_org
from .models import Organization from .models import Organization
logger = get_logger(__file__) logger = get_logger(__file__)
@ -23,7 +24,6 @@ __all__ = [
class OrgManager(models.Manager): class OrgManager(models.Manager):
def get_queryset(self): def get_queryset(self):
current_org = get_current_org()
kwargs = {} kwargs = {}
if not hasattr(tl, 'times'): if not hasattr(tl, 'times'):
tl.times = 0 tl.times = 0
@ -44,7 +44,6 @@ class OrgManager(models.Manager):
return queryset return queryset
def all(self): def all(self):
current_org = get_current_org()
if not current_org: if not current_org:
msg = 'You can `objects.set_current_org(org).all()` then run it' msg = 'You can `objects.set_current_org(org).all()` then run it'
warnings.warn(msg) warnings.warn(msg)
@ -64,7 +63,6 @@ class OrgModelMixin(models.Model):
objects = OrgManager() objects = OrgManager()
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
current_org = get_current_org()
if current_org and current_org.is_real(): if current_org and current_org.is_real():
self.org_id = current_org.id self.org_id = current_org.id
return super(OrgModelMixin, self).save(*args, **kwargs) return super(OrgModelMixin, self).save(*args, **kwargs)
@ -75,9 +73,16 @@ class OrgModelMixin(models.Model):
class OrgViewGenericMixin: class OrgViewGenericMixin:
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
current_org = get_current_org() print("Crrent org: {}".format(current_org))
if not current_org: if not current_org:
return redirect('orgs:switch-a-org') return redirect('orgs:switch-a-org')
if not current_org.can_admin_by(request.user):
print("{} cannot admin {}".format(request.user, current_org))
if request.user.is_org_admin:
print("Is org admin")
return redirect('orgs:switch-a-org')
return HttpResponseForbidden()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)

View File

@ -60,7 +60,16 @@ class Organization(models.Model):
return self.users.all() return self.users.all()
def get_org_admins(self): def get_org_admins(self):
pass if self.is_real():
return self.admins.all()
return []
def can_admin_by(self, user):
if user.is_superuser:
return True
if user in list(self.get_org_admins()):
return True
return False
def is_real(self): def is_real(self):
return len(str(self.id)) == 36 return len(str(self.id)) == 36

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import re
from django.apps import apps
from functools import partial
from common.utils import LocalProxy
from .models import Organization from .models import Organization
try: try:
@ -42,3 +43,13 @@ def set_to_default_org():
def set_to_root_org(): def set_to_root_org():
set_current_org(Organization.root()) set_current_org(Organization.root())
def _find(attr):
if hasattr(_thread_locals, attr):
return getattr(_thread_locals, attr)
return None
current_org = LocalProxy(get_current_org)

View File

@ -5,7 +5,7 @@ from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orgs.mixins import OrgModelForm from orgs.mixins import OrgModelForm
from orgs.utils import get_current_org from orgs.utils import current_org
from .hands import User from .hands import User
from .models import AssetPermission from .models import AssetPermission
@ -29,7 +29,6 @@ class AssetPermissionForm(OrgModelForm):
return return
users_field = self.fields.get('users') users_field = self.fields.get('users')
if hasattr(users_field, 'queryset'): if hasattr(users_field, 'queryset'):
current_org = get_current_org()
users_field.queryset = User.objects.filter(orgs=current_org) users_field.queryset = User.objects.filter(orgs=current_org)
class Meta: class Meta:

View File

@ -35,7 +35,7 @@
</a> </a>
<ul class="dropdown-menu animated fadeInRight m-t-xs profile-dropdown"> <ul class="dropdown-menu animated fadeInRight m-t-xs profile-dropdown">
<li><a href="{% url 'users:user-profile' %}"><i class="fa fa-cogs"> </i><span> {% trans 'Profile' %}</span></a></li> <li><a href="{% url 'users:user-profile' %}"><i class="fa fa-cogs"> </i><span> {% trans 'Profile' %}</span></a></li>
{% if request.user.is_superuser %} {% if request.user.is_org_admin %}
{% if request.COOKIES.IN_ADMIN_PAGE == 'No' %} {% if request.COOKIES.IN_ADMIN_PAGE == 'No' %}
<li><a id="switch_admin"><i class="fa fa-exchange"></i><span> {% trans 'Admin page' %}</span></a></li> <li><a id="switch_admin"><i class="fa fa-exchange"></i><span> {% trans 'Admin page' %}</span></a></li>
{% else %} {% else %}

View File

@ -2,7 +2,7 @@
<div class="sidebar-collapse"> <div class="sidebar-collapse">
<ul class="nav" id="side-menu"> <ul class="nav" id="side-menu">
{% include '_user_profile.html' %} {% include '_user_profile.html' %}
{% if request.user.is_superuser and request.COOKIES.IN_ADMIN_PAGE != "No" %} {% if request.user.is_org_admin and request.COOKIES.IN_ADMIN_PAGE != "No" %}
{% include '_nav.html' %} {% include '_nav.html' %}
{% else %} {% else %}
{% include '_nav_user.html' %} {% include '_nav_user.html' %}

View File

@ -20,7 +20,7 @@ from .permissions import IsSuperUser, IsValidUser, IsCurrentUserOrReadOnly, \
IsSuperUserOrAppUser IsSuperUserOrAppUser
from .utils import check_user_valid, generate_token, get_login_ip, \ from .utils import check_user_valid, generate_token, get_login_ip, \
check_otp_code, set_user_login_failed_count_to_cache, is_block_login check_otp_code, set_user_login_failed_count_to_cache, is_block_login
from orgs.utils import get_current_org from orgs.utils import current_org
from orgs.mixins import OrgViewGenericMixin from orgs.mixins import OrgViewGenericMixin
from common.mixins import IDInFilterMixin from common.mixins import IDInFilterMixin
from common.utils import get_logger from common.utils import get_logger
@ -37,7 +37,6 @@ class UserViewSet(IDInFilterMixin, BulkModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset() queryset = super().get_queryset()
current_org = get_current_org()
org_users = current_org.get_org_users().values_list('id', flat=True) org_users = current_org.get_org_users().values_list('id', flat=True)
queryset = queryset.filter(id__in=org_users) queryset = queryset.filter(id__in=org_users)
return queryset return queryset

View File

@ -7,7 +7,7 @@ from captcha.fields import CaptchaField
from common.utils import validate_ssh_public_key from common.utils import validate_ssh_public_key
from orgs.mixins import OrgModelForm from orgs.mixins import OrgModelForm
from orgs.utils import get_current_org from orgs.utils import current_org
from .models import User, UserGroup from .models import User, UserGroup
@ -279,8 +279,7 @@ class UserBulkUpdateForm(forms.ModelForm):
def user_limit_to(): def user_limit_to():
org = get_current_org() return {"orgs": current_org}
return {"orgs": org}
class UserGroupForm(forms.ModelForm): class UserGroupForm(forms.ModelForm):
@ -308,7 +307,6 @@ class UserGroupForm(forms.ModelForm):
return return
users_field = self.fields.get('users') users_field = self.fields.get('users')
if hasattr(users_field, 'queryset'): if hasattr(users_field, 'queryset'):
current_org = get_current_org()
users_field.queryset = current_org.get_org_users() users_field.queryset = current_org.get_org_users()
def save(self, commit=True): def save(self, commit=True):

View File

@ -16,7 +16,7 @@ from django.shortcuts import reverse
from common.utils import get_signer, date_expired_default from common.utils import get_signer, date_expired_default
from common.models import Setting from common.models import Setting
from orgs.mixins import OrgManager from orgs.mixins import OrgManager
from orgs.utils import get_current_org from orgs.utils import current_org
__all__ = ['User'] __all__ = ['User']
@ -222,7 +222,6 @@ class User(AbstractUser):
self.role = 'Admin' self.role = 'Admin'
self.is_active = True self.is_active = True
super().save(*args, **kwargs) super().save(*args, **kwargs)
current_org = get_current_org()
if current_org and current_org.is_real(): if current_org and current_org.is_real():
self.orgs.add(current_org) self.orgs.add(current_org)

View File

@ -23,7 +23,7 @@ from django.conf import settings
from common.utils import get_object_or_none from common.utils import get_object_or_none
from common.mixins import DatetimeSearchMixin, AdminUserRequiredMixin from common.mixins import DatetimeSearchMixin, AdminUserRequiredMixin
from orgs.utils import get_current_org from orgs.utils import current_org
from ..models import User, LoginLog from ..models import User, LoginLog
from ..utils import send_reset_password_mail, check_otp_code, get_login_ip, \ from ..utils import send_reset_password_mail, check_otp_code, get_login_ip, \
redirect_user_first_login_or_index, get_user_or_tmp_user, \ redirect_user_first_login_or_index, get_user_or_tmp_user, \
@ -367,7 +367,6 @@ class LoginLogListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView):
@staticmethod @staticmethod
def get_org_users(): def get_org_users():
current_org = get_current_org()
users = current_org.get_org_users().values_list('username', flat=True) users = current_org.get_org_users().values_list('username', flat=True)
return users return users

View File

@ -56,7 +56,7 @@ __all__ = [
logger = get_logger(__name__) logger = get_logger(__name__)
class UserListView(AdminUserRequiredMixin, TemplateView): class UserListView(TemplateView):
template_name = 'users/user_list.html' template_name = 'users/user_list.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):