class FlinkJobSerializer(BaseModelSerializer): # https://www.django-rest-framework.org/api-guide/serializers/ # https://www.django-rest-framework.org/api-guide/relations/ # code_paragraphs = s.PrimaryKeyRelatedField(many=True,label=_("引用代码段落"),queryset=FlinkJob.code_paragraphs.field.related_model.objects.all() ) # author = s.RelatedField(label=_("作者"),queryset=FlinkJob.author.field.related_model.objects.all()) author_alias = s.CharField(required=False, read_only=True) project_alias = s.CharField(required=False, read_only=True) status_alias = s.CharField(source='get_status_display', required=False, read_only=True) mode_alias = s.CharField(source='get_mode_display', required=False, read_only=True) task_code_type_alias = s.CharField(source='get_task_code_type_display', required=False, read_only=True) status_info = FlinkJobStatusInfoSerializer(label=('任务状态信息'), required=False, read_only=True) source_list = RelationModelIdField(source='get_source', required=False, read_only=True) slink_list = RelationModelIdField(source='get_slink', required=False, read_only=True) udf_list = RelationModelIdField(source='get_udf', required=False, read_only=True) start_datetime = s.DateTimeField(label=_('创建时间'), format=DATETIMEFORMAT, required=False, read_only=False, allow_null=True) stop_datetime = s.DateTimeField(label=_('更新时间'), format=DATETIMEFORMAT, required=False, read_only=True, allow_null=True) class Meta: model = FlinkJob fields = [ 'id', 'project', 'author_alias', 'project_alias', 'author', 'name', 'alias', 'status', 'job_id', 'flink_job_id', 'flink_job_url', 'mode', 'cron', 'start_datetime', 'stop_datetime', 'remark', 'code_paragraphs', 'task_code_type', 'task_content', 'flink_config', 'flink_table_config', 'status_info', 'task_properties', 'last_execution_savepoint', 'create_datetime', 'update_datetime', 'status_alias', 'mode_alias', 'task_code_type_alias', 'execution_savepoint_path', 'source_list', 'slink_list', 'udf_list' ] or '__all__' # exclude = ['session_key'] read_only_fields = [ 'create_datetime', 'update_datetime', 'start_datetime', 'stop_datetime', 'status_info', 'status', 'flink_job_id', 'flink_job_url' ]
class AssociatedTaskResultSer(BaseModelSerializer): is_all_done = s.BooleanField(label=_('是否都完成'), required=True) task_result_id = ListStrField(label=_('Celery任务ID'), help_text=_('celery task id 列表')) class Meta: model = AssociatedTaskResult fields = [ 'id', 'a_id', 'a_type_name', 'is_all_done', 'create_datetime', 'task_result_id' ]
def test_connect(self, request): params = QueryServerSerializer(data=request.data, valid_exception=True).o errmsg, model = QueryServer.create_or_update_for_params(params) connect_name = model.alias or model.name conn = model.mysql_conn() if not conn: raise RspError(_(' %s 获取 Mysql 连接失败 %s') % (connect_name, errmsg)) cur = conn.cursor() cur.execute("SELECT 1") return Response(msg=_('%s 连接成功') % connect_name)
class CeleryTaskConfig(AppConfig): name = 'celery_task' verbose_name = _('Celery 任务管理') def ready(self): from celery_app import app app.autodiscover_tasks(force=True)
class SyncModel(BaseModel): name = models.CharField(_('名称'), max_length=100, default='', null=False, blank=False) url = models.CharField(_('同步后台的地址'), max_length=200, default='', null=False, blank=False) key = models.CharField(default='', max_length=20, null=False, blank=True) is_old = models.BooleanField(default=False, null=False, blank=True) class Meta: ordering = ('id', )
class DynamicSettingsConfig(AppConfig): name = 'dynamic_settings' verbose_name = _('动态配置') def ready(self): from .conf import settings_manager settings_manager.watch_config()
class UserModelResource(RelaRtionModelResource): name = 'user' label = _('管理的用户') model_class = User is_inner = True def get_resource_queryset(self, user_model): """ 这个角色能管理的用户1""" return user_model.get_manageable_user()
class MyadminConfig(AppConfig): #app_label = 'myadmin' name = 'myadmin' verbose_name = _('MyAdmin 管理系统') def ready(self): logging.info('myadmin ready') logging.info('register user resource') autodiscover_modules('admin_resource')
class MenuModelResource(ModelResource): label = _('管理的菜单权限') unique_filed_name = 'name' name = 'menu' model_class = Menu is_inner = True def members_handle(self, members): """菜单是返回 menu1,menu2,,menu3 的字符串列表""" return members
def delete(self, request): """FlinkJob 删除""" params = IdsSerializer(request.data).params_data if params.id: ids = params.id for model in self.get_queryset().filter(id__in=ids): model.delete() return self.response(data=params) return self.response(params, msg=_('ids empty'))
def process_view(self, request, view_func, view_args, view_kwargs): """静态文件及有"notauth" 属性view_func 免认证 """ # 获取原始代码的属性 check_view_func = self.get_check_view_func(request, view_func) # 视图类没有权限设置,则使用path找出function检查 if hasattr(check_view_func, 'as_view') and ( not is_notauth(check_view_func) or not is_notcheck(check_view_func) ): if 'path' in view_kwargs: check_view_func = getattr(check_view_func, view_kwargs['path'], None) or check_view_func # 不需要登陆 if is_notauth(check_view_func) or self.is_pass(view_func): # 不需处理的函数不管 is_allow = True if ((request.path_info.find('/login') == 0 or request.path_info.find( '/phone_login') == 0) and request.method == 'POST'): request.user = request.admin = User() request.user.id = 0 self.save_operate_log(request, '登录后台') else: user_id = request.session.get(SESSION_KEY, None) the_user = User.objects.filter(id=user_id, status__in=(User.Status.NORMAL, User.Status.NotActive)).first() request.user = request.admin = the_user if not request.user: if request.is_ajax() or request.is_json: return Response(request=request, code=-1, msg=_('请重新登录')) login_url = settings.LOGIN_URL return HttpResponseRedirect('%s?from_url=%s' % (login_url, request.get_full_path())) the_user.make_allow_map() request.allow = request.allow_menu = the_user.allow_menu is_allow = self.check_url_permsssion(request) if is_notcheck(check_view_func): is_allow = True if not is_allow: return Response(request=request, code=1, msg=_('没有权限'), template_name='myadmin/block.html')
class RspCodeStatus(Enum): """系统常用返回状态""" Success = 0, _('成功') Fail = 1, _('失败,查看具体消息') NotLoggedIn = -1, _('权限不足,请先登录') NotPermission = -2, _('权限不足') ParamsError = -4, _('参数格式错误') DuplicatePay = 99, _('给闸机重复支付限制使用')
class AccessDomainSerializer(BaseModelSerializer): # https://www.django-rest-framework.org/api-guide/serializers/ # https://www.django-rest-framework.org/api-guide/relations/ status_alias = s.CharField(source='get_status_display', required=False, read_only=True) basedn = s.CharField(label=_('basedn'), max_length=128, required=False, read_only=True) authdn = s.CharField(label=_('authdn'), max_length=128, required=False, read_only=True) class Meta: model = AccessDomain fields = [ 'id', 'name', 'alias', 'bindpw', 'access_address', 'status', 'role', 'create_datetime', 'update_datetime', 'status_alias', 'basedn', 'authdn' ] or '__all__' # exclude = ['session_key'] read_only_fields = ['create_datetime', 'update_datetime']
# -*- coding: utf-8 -*- # @Time : 2020-07-16 14:25 # @Author : xzr # @File : settings # @Software: PyCharm # @Contact : [email protected] # @Desc : from __future__ import absolute_import from framework.conf import SettingOptions from framework.translation import _ AUTH_USER_MODEL = 'myadmin.models.user.User' ALLOW_REGISTER = SettingOptions(False, _('是否允许注册'), 'ALLOW_REGISTER','System') ALLOW_REGISTER_ROLE_CHOICE = SettingOptions(False, _('注册时能否选择角色'), 'ALLOW_REGISTER_CHOICE','System') USE_LDAP_AUTH = SettingOptions(False, _('是否使用LDAP验证'), 'USE_LDAP_AUTH', 'ldap') LDAP_HOST = SettingOptions('ldaps://127.0.0.1:13891', 'LDAP 连接地址', 'LDAP_HOST', 'ldap') _LDAP_BASE_DN = 'dc=bigdata,dc=com' LDAP_BASE_DN = SettingOptions(_LDAP_BASE_DN, 'LDAP BASE_DN', 'LDAP_BASE_DN', 'ldap') LDAP_BIND_DN = SettingOptions("cn=bigdata,ou=people,%s" % _LDAP_BASE_DN, 'LDAP 绑定账号', 'LDAP_BIND_DN', 'ldap') LDAP_BIND_PASSWORD = SettingOptions("123", 'LDAP 绑定密码', 'LDAP_BIND_PASSWORD', 'ldap') LDAP_USER_BASE_DN = SettingOptions("ou=people,%s" % _LDAP_BASE_DN, 'LDAP 用户域名', 'LDAP_USER_BASE_DN', 'ldap') LDAP_USER_FILTER = SettingOptions('(objectClass=posixAccount)', 'LDAP 用户过滤条件', 'LDAP_USER_FILTER', 'ldap')
class AccessDomain(BaseNameModel): """访问域""" class Status(Enum): Enable = 0, _('开启') Disable = 1, _('禁用') bindpw = models.CharField(verbose_name=_('访问密钥'), max_length=30, default='', null=False) access_address = models.CharField(verbose_name=_('访问地址'), max_length=256, default='', null=False) status = models.IntegerField(verbose_name=_('状态'), choices=Status.member_list(), default=Status.Enable) role = models.ManyToManyField(Role, verbose_name=_('允许访问的角色')) @property def is_enable(self): return self.status == self.Status.Enable @property def basedn(self): return 'dc=%s,dc=com' % self.name @property def authdn(self): return 'cn=%s,ou=user,%s' % (self.name, self.basedn) def save(self, *args, **kwargs): self.create_ldap_access_user() if self.status == self.Status.Disable: self.remove_ldap_db_path() ret = super().save(*args, **kwargs) # self.generate_db() return ret def delete(self, *args, **kwargs): self.remove_ldap_db_path() super().delete(*args, **kwargs) def generate_db(self): """ 生成 ldap 数据库 :return: """ roles = self.role.prefetch_related('parent').prefetch_related( 'user_set').distinct() for user in User.get_normal_user_list().prefetch_related( 'userinfo_set').filter(role__in=roles).distinct(): self.create_user(user) for role in roles: self.create_role(role) def get_ldap_access_user(self): ldap_access_user = User() ldap_access_user.username = self.name ldap_access_user.alias = self.alias ldap_access_user.set_password(self.bindpw) _user_info = UserInfo() _user_info.email = '%s@%s.com' % (self.name, self.name) ldap_access_user.user_info = _user_info return ldap_access_user def remove_ldap_db_path(self): domain_db_path = self.get_domain_db_path() if os.path.isdir(domain_db_path): os.path.remove(domain_db_path) def create_ldap_access_user(self): return self.create_user(self.get_ldap_access_user()) def delete_ldap_access_user(self): return self.delete_user(self.get_ldap_access_user()) def get_domain_db_path(self): return os.path.join(DBPATH, 'dc=com.dir', 'dc=%s.dir' % self.name) def create_db_dir(self, *dir_name): db_dir = os.path.join(self.get_domain_db_path(), *dir_name) mkdirs(db_dir) return db_dir @CacheAttribute def user_db_path(self): return self.create_db_dir('ou=user.dir') @CacheAttribute def role_db_path(self): return self.create_db_dir('ou=role.dir') def create_user(self, user: User): file_name = 'cn=%s.ldif' % user.username user_info = user.user_info employee_id = email = '' if user_info: employee_id = user_info.employee_id email = user_info.email save_path = os.path.join(self.user_db_path, file_name) password_tuple = user.password.split('$', 1) secret = '{SSHA}%s' % (password_tuple[1] if len(password_tuple) > 1 else '') ldap_cn_str = '' with open(save_path, 'w') as f: ldap_cn_str = cn_tpl.format(cn=user.username, sn=user.alias[0], uid=user.username, alias=user.alias, uidNumber=user.id, userPassword=secret, email=email, employee_id=employee_id, status=user.status) # f.write(ldap_cn_str) return ldap_cn_str def delete_user(self, user): file_name = 'cn=%s.ldif' % user.username save_path = os.path.join(self.user_db_path, file_name) if os.path.exists(save_path): os.remove(save_path) def create_role(self, role: Role): file_name = 'cn=%s.ldif' % role.name ldap_cn_str = '' if role.type == Role.RoleType.GROUP: parent = '' # todo 改为域限制 if role.parent: parent = role.parent.name ou_role_dir = self.role_db_path save_path = os.path.join(ou_role_dir, file_name) memberuid_list = '\n'.join( ['memberUid: %s' % v.username for v in role.user_set.all()]) with open(save_path, 'w') as f: ldap_cn_str = ou_role_tpl.format(cn=role.name, parent=parent, gidnumber=role.id, alias=role.alias, desc=role.remark, memberuid=memberuid_list) # f.write(ldap_cn_str) return ldap_cn_str def delete_role(self, role: Role): file_name = 'cn=%s.ldif' % role.name save_path = os.path.join(self.role_db_path, file_name) if os.path.exists(save_path): os.remove(save_path) class Meta: pass
class SyncModelConfig(AppConfig): """同步django模型 """ name = 'sync_model' verbose_name = _('数据模型同步')
class FlinkProjectModelResource(ModelResource): label = _('Flink 项目') name = 'flink_project' model_class = Project template_context = {} template = ModelResource.default_template
class Permission(Enum): Read = 'r', _('只读') Write = 'w', _('只写') ReadWrite = 'rw', _('可读写') Empty = 'no', _('禁止访问')
class ParagraphsTreeParmas(ParamsSerializer): is_project_private = s.BooleanField(label=_('是否项目独有'), required=False, default=False)
class FlinkJobActionParams(IdsSerializer): force = s.BooleanField(label=_('是否强制执行'), required=False) use_last_savepoint = s.BooleanField( label=_('是否 使用最后一次 Savepoint Path'), required=False, default=True)
class RoleModelResource(ModelResource): name = 'role' label = _('管理的角色') model_class = Role is_inner = True
class PositionType(Enum): SERVER = 0, _('分服') CENTER = 1, _('中央服') KUAFU = 2, _('跨服')
class LogDefine(BaseModel, LogDefineMixin): """日志类定义 """ LogModel = Log class PositionType(Enum): SERVER = 0, _('分服') CENTER = 1, _('中央服') KUAFU = 2, _('跨服') Status = PositionType name = models.CharField(_('日志名'), max_length=50) key = models.CharField(_('日志表标识'), max_length=100, db_index=True, validators=[LetterValidator]) remark = models.CharField(_('备注'), max_length=1000) status = models.IntegerField(_('保存位置'), default=0, choices=PositionType.member_list()) _config = models.TextField(_('配置')) trigger = models.TextField(_('触发器sql'), default="", null=False, blank=True) # todo 这里未来兼容sql文件导入和mysqldb执行的sql 处理有点乱, 到时再改 def get_other_sqls(self, is_sql_file=False): """获取其他sql @is_sql_file:是否sql文件用的 """ sqls = [] sp = ';' the_cut_sp = '\\' if '//' in self.trigger: sp = '//' for sql in self.trigger.split(sp): if the_cut_sp in sql: if is_sql_file: sql = sql.replace(the_cut_sp, '') else: sql = '' elif not is_sql_file: sql = sql.replace('$$', '') if sql: sqls.append('%s' % sql) return sqls @property def config(self): _r = {} field_config = self.get_default_config() try: _r = json.loads(self._config) for k in sorted(_r.keys(), reverse=True): field_config[k].update(_r.get(k, {})) except: pass _r = field_config return _r @config.setter def config(self, obj_value): if isinstance(obj_value, dict): obj_value = json.dumps(obj_value) self._config = obj_value @CacheAttribute def json_config(self): return json_dumps(self.config) @property def table_name(self): return 'log_%s' % self.key.strip() def save(self, *args, **kwargs): return super(LogDefine, self).save(*args, **kwargs) def __unicode__(self): return '%s' % self.key class Meta: pass
class QueryServer(BaseModel): """查询服务器 """ class Status(myenum.Enum): Deleted = (-1, '已删除') Normal = (0, '正常') name = models.CharField(u'服务器名', max_length=20, blank=False, null=False, db_index=True, help_text='纯字母') alias = models.CharField(u'服务器别名', max_length=20, default='', blank=True, null=False) host = models.CharField(_('地址'), max_length=200, blank=False, null=False) user = models.CharField(_('用户'), max_length=100, default='root', blank=False, null=False) password = models.CharField(_('密码'), max_length=100, blank=False, null=False) port = models.IntegerField(_('端口'), default=3306, blank=False, null=False) db_name = models.CharField(_('数据库名'), max_length=100, blank=False, null=False) charset = models.CharField(_('数据字符集'), max_length=100, default='utf8', blank=False, null=False, help_text='默认 utf8') status = models.IntegerField(u'服务器状态', default=0, choices=Status.member_list()) remark = models.CharField(u'备注', max_length=200, default='', blank=True, null=False) order = models.IntegerField(u'排序', default=0) __conn = None @classmethod def get_conn(cls, server_id=0, databases='default', connect_timeout=10): try: if server_id: the_server = cls.objects.using(databases).get(id=server_id) the_conn = the_server.mysql_conn(True) the_conn.autocommit(1) else: the_conn = connections[databases] except Exception as e: raise e return the_conn def mysql_conn(self, select_db=True, connect_timeout=10, is_new=False): """mysql的连接 """ if not self.__conn or is_new: # try: the_conn = MySQLdb.connect(host=self.host, user=self.user, passwd=self.password, port=self.port, charset=self.charset, connect_timeout=connect_timeout) the_conn.autocommit(1) self.__conn = the_conn # except Exception as e: # print(trace_msg()) if self.__conn: if select_db: self.__conn.select_db(self.db_name) return self.__conn def get_json_data(self): try: json_data = self.json_data if self.json_data.find( '{') == 0 else '{%s}' % self.json_data server_config = json.loads(json_data) return server_config except: return {} def __unicode__(self): return '%s(%s)' % (self.name, self.id) def create_time_str(self): return datetime_to_str(self.create_datetime) if self.create_datetime else '' @classmethod def get_server_list(cls): return cls.objects.filter(~models.Q(status=cls.Status.DELETED)).order_by('-status') class Meta: ordering = ('order',)
class Statistic(BaseModel): """统计""" STATUS_CHOICES = ( (0, '结果数量数'), (1, '值求和'), (2, '求平均值'), (3, '求最大值'), (4, '求最小值'), ) DEFAULT_SAVE_TABLE_NAME = 'log_statistic_result' log_type = models.IntegerField() name = models.CharField(_('统计标识'), max_length=200, unique=True) remove_field = models.CharField(_('统计时间维护字段'), max_length=50, null=False, default="") # 统计时间维护字段 is_save_center = models.IntegerField('是否保存到中央库', default=1) save_table_name = models.CharField('保存到哪个表', max_length=50, default=DEFAULT_SAVE_TABLE_NAME) where = models.CharField('', max_length=50, null=True) sql = models.CharField(max_length=5000) exec_interval = models.IntegerField(default=0) last_exec_time = models.DateTimeField(null=True, blank=True) is_auto_execute = models.IntegerField(_('自动执行'), default=0) auto_exec_interval = models.IntegerField(_('自动执行间隔'), default=0, blank=True, null=False) # 自动执行间隔,单位秒天 remark = models.CharField(_('备注'), max_length=1000, blank=True) result_data = models.CharField(max_length=200, blank=True) @classmethod def get_servers(cls, server_ids): from .query_server import QueryServer return QueryServer.objects.filter(id__in=server_ids) @CacheAttribute def log_def(self): return LogDefine.objects.get(id=self.log_type) def is_center(self): return self.log_def.status == LogDefine.Status.CENTER def __unicode__(self): return '%s' % self.name def last_exec_time_str(self): return datetime_to_str(self.last_exec_time) def get_result_json(self): if self.result_data != '' and self.result_data != None: the_json = json.loads(self.result_data) the_date = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d') if the_date == the_json['date']: return the_json # 处理,昨天,前天,本周,上月同一天 today = datetime.date.today() last_day = today.day # 当前月份天数 current_month_days = calendar.monthrange(today.year, today.month)[1] if current_month_days < last_day: last_day = current_month_days now_date = datetime.datetime.now() list_date = [ (now_date - datetime.timedelta(days=1)).strftime('%Y-%m-%d'), (now_date - datetime.timedelta(days=2)).strftime('%Y-%m-%d'), (now_date - datetime.timedelta(weeks=1)).strftime('%Y-%m-%d'), (now_date - datetime.timedelta(days=current_month_days)).strftime('%Y-%m-%d') ] query_sql = 'select result_time,sum(result) from result where statistic_id=%d and result_time in("%s") group by result_time desc limit 10' % ( self.id, '","'.join(list_date)) cursor = connection.cursor() cursor.execute(query_sql) list_record = cursor.fetchall() # cursor.close() # list_record = Result.objects.filter(statistic__id=self.id,create_time__in=list_date).order_by('-create_time') new_json = {} new_json['date'] = list_date[0] the_value = 0.0 for item_record in list_record: item_date = item_record[0].strftime('%Y-%m-%d') tmp = 0 if float(item_record[1]) != 0: tmp = (the_value / float(item_record[1]) - 1) if item_date == list_date[0]: the_value = int(item_record[1]) new_json['default'] = '%d' % the_value elif item_date == list_date[1]: new_json['day'] = '%.2f' % (tmp * 100) elif item_date == list_date[2]: new_json['week'] = '%.2f' % (tmp * 100) elif item_date == list_date[3]: new_json['month'] = '%.2f' % (tmp * 100) self.result_data = str(new_json).replace('\'', '"') self.save(using='write') return new_json class Meta: app_label = AnalysisConfig.name ordering = ('-last_exec_time', )
class AnalysisConfig(AppConfig): """ 查询系统 """ name = 'analysis' verbose_name = _('查询分析系统')
class CodeParagraphsTreeItemSer(DataSerializer): title = s.CharField(label=_('标题')) key = s.CharField(label=_('值')) children = RecursiveField(label=_('子项目'))
class SvnPath(BaseModel): """ SVN 路径 """ class Status(Enum): Enable = 0, _('开启') Disable = 1, _('关闭') class Permission(Enum): Read = 'r', _('只读') Write = 'w', _('只写') ReadWrite = 'rw', _('可读写') Empty = 'no', _('禁止访问') project_name = models.CharField(max_length=100, verbose_name=_('项目名'), db_index=True, null=False, blank=False, validators=[LetterValidator]) alias = models.CharField(max_length=200, verbose_name=_('项目别称'), default='', null=False, blank=True) path = models.CharField(max_length=200, verbose_name=_('svn 路径'), db_index=True, null=False, blank=False) parent = models.ForeignKey(to='self', verbose_name=_('上级路径'), null=True, on_delete=models.DO_NOTHING, blank=True) status = models.IntegerField(verbose_name=_('状态'), choices=Status.member_list(), default=Status.Enable, null=True, blank=True) remark = models.CharField(max_length=500, verbose_name=_('备注'), default='', null=False, blank=True) read_member = JSONField(verbose_name=_('可读成员'), default='[]', blank=True, null=False) write_member = JSONField(verbose_name=_('可写成员'), default='[]', blank=True, null=False) other_permission = models.CharField(verbose_name=_('其他访问权限'), max_length=2, choices=Permission.member_list(), default=Permission.Empty, null=False, blank=True) class Meta: ordering = ['id'] unique_together = (('project_name', 'path')) def save(self, *args, **kwargs): if self.path != '/': self.parent = self.__class__.objects.get( project_name=self.project_name, parent=None, path='/') self.path = self.path.strip('/') r = super(SvnPath, self).save(*args, **kwargs) SvnPath.sync_svn_config_file() return r svn_root_conf_path = os.path.join(SVN_ROOT, 'conf') @classmethod def create_conf(cls): default_svnserve_conf_text = ''' ### Visit http://subversion.apache.org/ for more information. [general] anon-access = none auth-access = write password-db = {password_db} authz-db = {authz_db} groups-db = {groups_db} # realm = My First Repository # force-username-case = none # hooks-env = hooks-env [sasl] # use-sasl = true # min-encryption = 0 # max-encryption = 256 ''' mkdirs(cls.svn_root_conf_path) svnserve_conf_file = os.path.join(cls.svn_root_conf_path, 'svnserve.conf') if not os.path.isfile(svnserve_conf_file): open(svnserve_conf_file, 'w').write( default_svnserve_conf_text.format( password_db=SVN_PASSWORD_DB_FILE, authz_db=SVN_AUTH_DB_FILE, groups_db=SVN_GROUP_DB_FILE)) @classmethod def create_svnrepo(cls, svnrepo_name): cls.create_conf() svnrepo_path = os.path.join(SVN_ROOT, svnrepo_name) svnrepo_conf_path = os.path.join(svnrepo_path, 'conf') if not os.path.isdir(svnrepo_path): os.system('svnadmin create %s' % svnrepo_path) if not os.path.islink(svnrepo_conf_path): shutil.rmtree(svnrepo_conf_path) os.symlink(cls.svn_root_conf_path, svnrepo_conf_path) @property def section_name(self): return '{project_name}:{path}'.format(project_name=self.project_name, path=self.full_path) @property def full_path(self): return '/' + self.path.strip('/') @classmethod def get_password_db(self): password_db = configparser.ConfigParser() password_db.read(SVN_PASSWORD_DB_FILE) return password_db @classmethod def get_authz_db(self): authz_db = configparser.ConfigParser() authz_db.read(SVN_AUTH_DB_FILE) return authz_db @classmethod def get_groups_db(self): authz_db = configparser.ConfigParser() authz_db.read(SVN_GROUP_DB_FILE) return authz_db @classmethod def sync_svn_config_file(cls): cls.sync_user_to_password_db() cls.sync_group_menber_to_authz_db() cls.sync_svn_path_authz_db() USER_SECTION_NAME = 'users' GROUP_SECTION_NAME = 'groups' user_set = set() group_set = set() @classmethod def get_svn_project_list(cls): from .settings import SVN_ROOT dirs = os.listdir(SVN_ROOT) project_list = [] for d in dirs: if os.path.isfile(os.path.join(SVN_ROOT, d, 'format')): project_list.append(d) return project_list @classmethod def get_tree_list(cls, project_name, list_path='/'): project_path = os.path.join(SVN_ROOT, project_name) cmd = 'svnlook tree -N --full-paths {project_path} {list_path} '.format( project_path=project_path, list_path=list_path) result = {project_name: []} for path in os.popen(cmd).readlines(): path = path.strip() if path and path[-1] == '/' and path != list_path: result[project_name].append(path) return result @classmethod def init_svn_projects(cls): project_list = cls.get_svn_project_list() for project_name in project_list: svn_paht_model = cls.objects.get_or_create( project_name=project_name, parent=None, path='/') # svn_paht_model.parent = None # svn_paht_model.save() @classmethod def sync_user_to_password_db(cls): password_db = cls.get_password_db() password_db.clear() user_section_name = cls.USER_SECTION_NAME if not password_db.has_section(user_section_name): password_db.add_section(user_section_name) cls.user_set.clear() for svnuser in SvnUser.objects.select_related('user').all(): user = svnuser.user password_db.set(user_section_name, user.username, svnuser.get_raw_password()) cls.user_set.add(user.username) password_db.write(open(SVN_PASSWORD_DB_FILE, "w")) @classmethod def sync_group_menber_to_authz_db(cls): groups_db = cls.get_groups_db() group_section_name = cls.GROUP_SECTION_NAME if not groups_db.has_section(group_section_name): groups_db.add_section(group_section_name) cls.group_set.clear() for role in Role.objects.prefetch_related('user_set').filter( type=Role.RoleType.GROUP): user_name_list = role.user_set.values_list('username', flat=True) if user_name_list: cls.group_set.add('@%s' % role.name) groups_db.set(group_section_name, role.name, ','.join(user_name_list)) groups_db.write(open(SVN_GROUP_DB_FILE, "w")) @classmethod def sync_svn_path_authz_db(cls): authz_db = cls.get_authz_db() authz_db.clear() for svn_path_model in cls.objects.filter(status=cls.Status.Enable): svn_path_section_name = svn_path_model.section_name if authz_db.has_section(svn_path_section_name): authz_db.remove_section(svn_path_section_name) authz_db.add_section(svn_path_section_name) allow_menber = cls.user_set | cls.group_set read_member_set = set(json.loads( svn_path_model.read_member)) & allow_menber write_member_set = set(json.loads( svn_path_model.write_member)) & allow_menber rw_list = read_member_set & write_member_set for member in rw_list: authz_db.set(svn_path_section_name, member, 'rw') for member in read_member_set - rw_list: authz_db.set(svn_path_section_name, member, 'r') for member in write_member_set - rw_list: authz_db.set(svn_path_section_name, member, 'w') authz_db.set( svn_path_section_name, '*', '' if svn_path_model.other_permission == cls.Permission.Empty else svn_path_model.other_permission) authz_db.write(open(SVN_AUTH_DB_FILE, "w"))
class Status(Enum): Enable = 0, _('开启') Disable = 1, _('关闭')
class LdapAccountConfig(AppConfig): name = 'ldap_account' verbose_name = _('Ldap 账号系统')