Compare commits

...

8 Commits

Author SHA1 Message Date
Jiangjie.Bai
e7296df57c fix: 修复手动登录系统用户连接RemoteApp应用获取不到认证信息的问题 2022-06-16 10:41:12 +08:00
ibuler
36d1493f8e perf: 继续优化一波 2022-06-13 16:47:22 +08:00
ibuler
4b94dc77a9 perf: 优化迁移 rbac 速度
perf: migrate
2022-06-13 15:17:48 +08:00
Jiangjie.Bai
e934c8b903 fix: 修复ldap用户登录时用户组不设置 2022-05-30 16:03:49 +08:00
Jiangjie.Bai
4b9fb4c796 fix: 修改 public settings API公告字段类型为 dict 2022-05-27 17:23:49 +08:00
fit2bot
c30b024f9c fix: 修复获取 city 时可能的报错 (#8295)
Co-authored-by: ibuler <ibuler@qq.com>
2022-05-24 12:30:48 +08:00
feng626
9c14eb5165 fix: 修复用户更新自己密码 url 不准确问题 2022-05-24 11:15:38 +08:00
ibuler
624f32bc6c fix: 修复 Migrations 错误 2022-05-24 11:01:09 +08:00
11 changed files with 167 additions and 61 deletions

View File

@@ -14,7 +14,6 @@ def create_internal_platform(apps, schema_editor):
model.objects.using(db_alias).update_or_create( model.objects.using(db_alias).update_or_create(
name=name, defaults=defaults name=name, defaults=defaults
) )
migrations.RunPython(create_internal_platform)
class Migration(migrations.Migration): class Migration(migrations.Migration):

View File

@@ -133,6 +133,15 @@ class AuthMixin:
self.password = password self.password = password
def load_app_more_auth(self, app_id=None, username=None, user_id=None): def load_app_more_auth(self, app_id=None, username=None, user_id=None):
# 清除认证信息
self._clean_auth_info_if_manual_login_mode()
# 先加载临时认证信息
if self.login_mode == self.LOGIN_MANUAL:
self._load_tmp_auth_if_has(app_id, user_id)
return
# Remote app
from applications.models import Application from applications.models import Application
app = get_object_or_none(Application, pk=app_id) app = get_object_or_none(Application, pk=app_id)
if app and app.category_remote_app: if app and app.category_remote_app:
@@ -141,11 +150,6 @@ class AuthMixin:
return return
# Other app # Other app
self._clean_auth_info_if_manual_login_mode()
# 加载临时认证信息
if self.login_mode == self.LOGIN_MANUAL:
self._load_tmp_auth_if_has(app_id, user_id)
return
# 更新用户名 # 更新用户名
from users.models import User from users.models import User
user = get_object_or_none(User, pk=user_id) if user_id else None user = get_object_or_none(User, pk=user_id) if user_id else None

View File

@@ -157,6 +157,8 @@ class LDAPUser(_LDAPUser):
def _populate_user_from_attributes(self): def _populate_user_from_attributes(self):
for field, attr in self.settings.USER_ATTR_MAP.items(): for field, attr in self.settings.USER_ATTR_MAP.items():
if field in ['groups']:
continue
try: try:
value = self.attrs[attr][0] value = self.attrs[attr][0]
value = value.strip() value = value.strip()

View File

@@ -13,10 +13,6 @@ reader = None
def get_ip_city_by_geoip(ip): def get_ip_city_by_geoip(ip):
if not ip or '.' not in ip or not isinstance(ip, str):
return _("Invalid ip")
if ':' in ip:
return 'IPv6'
global reader global reader
if reader is None: if reader is None:
path = os.path.join(os.path.dirname(__file__), 'GeoLite2-City.mmdb') path = os.path.join(os.path.dirname(__file__), 'GeoLite2-City.mmdb')
@@ -32,7 +28,7 @@ def get_ip_city_by_geoip(ip):
try: try:
response = reader.city(ip) response = reader.city(ip)
except GeoIP2Error: except GeoIP2Error:
return {} return _("Unknown")
city_names = response.city.names or {} city_names = response.city.names or {}
lang = settings.LANGUAGE_CODE[:2] lang = settings.LANGUAGE_CODE[:2]

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import os import os
from django.utils.translation import ugettext as _
import ipdb import ipdb
@@ -11,13 +10,13 @@ ipip_db = None
def get_ip_city_by_ipip(ip): def get_ip_city_by_ipip(ip):
global ipip_db global ipip_db
if not ip or not isinstance(ip, str):
return _("Invalid ip")
if ':' in ip:
return 'IPv6'
if ipip_db is None: if ipip_db is None:
ipip_db_path = os.path.join(os.path.dirname(__file__), 'ipipfree.ipdb') ipip_db_path = os.path.join(os.path.dirname(__file__), 'ipipfree.ipdb')
ipip_db = ipdb.City(ipip_db_path) ipip_db = ipdb.City(ipip_db_path)
try:
info = ipip_db.find_info(ip, 'CN') info = ipip_db.find_info(ip, 'CN')
except ValueError:
return None
if not info:
raise None
return {'city': info.city_name, 'country': info.country_name} return {'city': info.city_name, 'country': info.country_name}

View File

@@ -74,13 +74,18 @@ def contains_ip(ip, ip_group):
def get_ip_city(ip): def get_ip_city(ip):
info = get_ip_city_by_ipip(ip) if not ip or not isinstance(ip, str):
city = info.get('city', _("Unknown")) return _("Invalid ip")
country = info.get('country') if ':' in ip:
return 'IPv6'
# 国内城市 并且 语言是中文就使用国内 info = get_ip_city_by_ipip(ip)
is_zh = settings.LANGUAGE_CODE.startswith('zh') if info:
if country == '中国' and is_zh: city = info.get('city', _("Unknown"))
return city country = info.get('country')
else:
return get_ip_city_by_geoip(ip) # 国内城市 并且 语言是中文就使用国内
is_zh = settings.LANGUAGE_CODE.startswith('zh')
if country == '中国' and is_zh:
return city
return get_ip_city_by_geoip(ip)

View File

@@ -126,6 +126,8 @@ class BuiltinRole:
org_user = PredefineRole( org_user = PredefineRole(
'7', ugettext_noop('OrgUser'), Scope.org, user_perms '7', ugettext_noop('OrgUser'), Scope.org, user_perms
) )
system_role_mapper = None
org_role_mapper = None
@classmethod @classmethod
def get_roles(cls): def get_roles(cls):
@@ -138,22 +140,24 @@ class BuiltinRole:
@classmethod @classmethod
def get_system_role_by_old_name(cls, name): def get_system_role_by_old_name(cls, name):
mapper = { if not cls.system_role_mapper:
'App': cls.system_component, cls.system_role_mapper = {
'Admin': cls.system_admin, 'App': cls.system_component.get_role(),
'User': cls.system_user, 'Admin': cls.system_admin.get_role(),
'Auditor': cls.system_auditor 'User': cls.system_user.get_role(),
} 'Auditor': cls.system_auditor.get_role()
return mapper[name].get_role() }
return cls.system_role_mapper[name]
@classmethod @classmethod
def get_org_role_by_old_name(cls, name): def get_org_role_by_old_name(cls, name):
mapper = { if not cls.org_role_mapper:
'Admin': cls.org_admin, cls.org_role_mapper = {
'User': cls.org_user, 'Admin': cls.org_admin.get_role(),
'Auditor': cls.org_auditor, 'User': cls.org_user.get_role(),
} 'Auditor': cls.org_auditor.get_role(),
return mapper[name].get_role() }
return cls.org_role_mapper[name]
@classmethod @classmethod
def sync_to_db(cls, show_msg=False): def sync_to_db(cls, show_msg=False):

View File

@@ -1,5 +1,6 @@
# Generated by Django 3.1.13 on 2021-12-01 11:01 # Generated by Django 3.1.13 on 2021-12-01 11:01
import time
from django.db import migrations from django.db import migrations
from rbac.builtin import BuiltinRole from rbac.builtin import BuiltinRole
@@ -9,33 +10,61 @@ def migrate_system_role_binding(apps, schema_editor):
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
user_model = apps.get_model('users', 'User') user_model = apps.get_model('users', 'User')
role_binding_model = apps.get_model('rbac', 'SystemRoleBinding') role_binding_model = apps.get_model('rbac', 'SystemRoleBinding')
users = user_model.objects.using(db_alias).all()
role_bindings = [] count = 0
for user in users: bulk_size = 1000
role = BuiltinRole.get_system_role_by_old_name(user.role) while True:
role_binding = role_binding_model(scope='system', user_id=user.id, role_id=role.id) users = user_model.objects.using(db_alias) \
role_bindings.append(role_binding) .only('role', 'id') \
role_binding_model.objects.bulk_create(role_bindings, ignore_conflicts=True) .all()[count:count+bulk_size]
if not users:
break
role_bindings = []
start = time.time()
for user in users:
role = BuiltinRole.get_system_role_by_old_name(user.role)
role_binding = role_binding_model(scope='system', user_id=user.id, role_id=role.id)
role_bindings.append(role_binding)
role_binding_model.objects.bulk_create(role_bindings, ignore_conflicts=True)
print("Create role binding: {}-{} using: {:.2f}s".format(
count, count + len(users), time.time()-start
))
count += len(users)
def migrate_org_role_binding(apps, schema_editor): def migrate_org_role_binding(apps, schema_editor):
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
org_member_model = apps.get_model('orgs', 'OrganizationMember') org_member_model = apps.get_model('orgs', 'OrganizationMember')
role_binding_model = apps.get_model('rbac', 'RoleBinding') role_binding_model = apps.get_model('rbac', 'RoleBinding')
members = org_member_model.objects.using(db_alias).all()
role_bindings = [] count = 0
for member in members: bulk_size = 1000
role = BuiltinRole.get_org_role_by_old_name(member.role)
role_binding = role_binding_model( while True:
scope='org', members = org_member_model.objects.using(db_alias)\
user_id=member.user.id, .only('role', 'user_id', 'org_id')\
role_id=role.id, .all()[count:count+bulk_size]
org_id=member.org.id if not members:
) break
role_bindings.append(role_binding) role_bindings = []
role_binding_model.objects.bulk_create(role_bindings) start = time.time()
for member in members:
role = BuiltinRole.get_org_role_by_old_name(member.role)
role_binding = role_binding_model(
scope='org',
user_id=member.user_id,
role_id=role.id,
org_id=member.org_id
)
role_bindings.append(role_binding)
role_binding_model.objects.bulk_create(role_bindings, ignore_conflicts=True)
print("Create role binding: {}-{} using: {:.2f}s".format(
count, count + len(members), time.time()-start
))
count += len(members)
class Migration(migrations.Migration): class Migration(migrations.Migration):

View File

@@ -40,6 +40,6 @@ class PrivateSettingSerializer(PublicSettingSerializer):
TERMINAL_KOKO_SSH_ENABLED = serializers.BooleanField() TERMINAL_KOKO_SSH_ENABLED = serializers.BooleanField()
ANNOUNCEMENT_ENABLED = serializers.BooleanField() ANNOUNCEMENT_ENABLED = serializers.BooleanField()
ANNOUNCEMENT = serializers.CharField() ANNOUNCEMENT = serializers.DictField()
TICKETS_ENABLED = serializers.BooleanField() TICKETS_ENABLED = serializers.BooleanField()

View File

@@ -143,7 +143,7 @@ class PasswordExpirationReminderMsg(UserMessage):
subject = _('Password is about expire') subject = _('Password is about expire')
date_password_expired_local = timezone.localtime(user.date_password_expired) date_password_expired_local = timezone.localtime(user.date_password_expired)
update_password_url = urljoin(settings.SITE_URL, '/ui/#/users/profile/?activeTab=PasswordUpdate') update_password_url = urljoin(settings.SITE_URL, '/ui/#/profile/setting/?activeTab=PasswordUpdate')
date_password_expired = date_password_expired_local.strftime('%Y-%m-%d %H:%M:%S') date_password_expired = date_password_expired_local.strftime('%Y-%m-%d %H:%M:%S')
context = { context = {
'name': user.name, 'name': user.name,

View File

@@ -0,0 +1,68 @@
# Generated by Django 3.1.13 on 2021-12-01 11:01
import os
import sys
import django
import time
app_path = '***** Change me *******'
sys.path.insert(0, app_path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings")
django.setup()
from django.apps import apps
from django.db import connection
# ========================== 添加到需要测试的 migrations 上方 ==========================
from django.db import migrations
from rbac.builtin import BuiltinRole
def migrate_system_role_binding(apps, schema_editor):
db_alias = schema_editor.connection.alias
user_model = apps.get_model('users', 'User')
role_binding_model = apps.get_model('rbac', 'SystemRoleBinding')
count = 0
bulk_size = 1000
while True:
users = user_model.objects.using(db_alias) \
.only('role', 'id') \
.all()[count:count+bulk_size]
if not users:
break
role_bindings = []
start = time.time()
for user in users:
role = BuiltinRole.get_system_role_by_old_name(user.role)
role_binding = role_binding_model(scope='system', user_id=user.id, role_id=role.id)
role_bindings.append(role_binding)
role_binding_model.objects.bulk_create(role_bindings, ignore_conflicts=True)
print("Create role binding: {}-{} using: {:.2f}s".format(
count, count + len(users), time.time()-start
))
count += len(users)
class Migration(migrations.Migration):
dependencies = [
('rbac', '0003_auto_20211130_1037'),
]
operations = [
migrations.RunPython(migrate_system_role_binding),
]
# ================== 添加到下方 ======================
def main():
schema_editor = connection.schema_editor()
migrate_system_role_binding(apps, schema_editor)
# main()