# cython:language_level=3 from django.shortcuts import render from django.http import HttpResponseRedirect from django.contrib.auth.hashers import make_password from django.http import JsonResponse from django.db.models import Q from django.contrib.auth.decorators import login_required from django.contrib import auth from api.models import RustDeskPeer, RustDesDevice, UserProfile, ShareLink from django.forms.models import model_to_dict from itertools import chain from django.db.models.fields import DateTimeField, DateField, CharField, TextField import datetime from django.db.models import Model import json import time import hashlib salt = 'xiaomo' EFFECTIVE_SECONDS = 7200 def getStrMd5(s): if not isinstance(s, (str,)): s = str(s) myHash = hashlib.md5() myHash.update(s.encode()) return myHash.hexdigest() def model_to_dict2(instance, fields=None, exclude=None, replace=None, default=None): """ :params instance: 模型对象,不能是queryset数据集 :params fields: 指定要展示的字段数据,('字段1','字段2') :params exclude: 指定排除掉的字段数据,('字段1','字段2') :params replace: 将字段名字修改成需要的名字,{'数据库字段名':'前端展示名'} :params default: 新增不存在的字段数据,{'字段':'数据'} """ # 对传递进来的模型对象校验 if not isinstance(instance, Model): raise Exception('model_to_dict接收的参数必须是模型对象') # 对替换数据库字段名字校验 if replace and type(replace) == dict: for replace_field in replace.values(): if hasattr(instance, replace_field): raise Exception(f'model_to_dict,要替换成{replace_field}字段已经存在了') # 对要新增的默认值进行校验 if default and type(default) == dict: for default_key in default.keys(): if hasattr(instance, default_key): raise Exception(f'model_to_dict,要新增默认值,但字段{default_key}已经存在了') opts = instance._meta data = {} for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many): # 源码下:这块代码会将时间字段剔除掉,我加上一层判断,让其不再剔除时间字段 if not getattr(f, 'editable', False): if type(f) == DateField or type(f) == DateTimeField: pass else: continue # 如果fields参数传递了,要进行判断 if fields is not None and f.name not in fields: continue # 如果exclude 传递了,要进行判断 if exclude and f.name in exclude: continue key = f.name # 获取字段对应的数据 if type(f) == DateTimeField: # 字段类型是,DateTimeFiled 使用自己的方式操作 value = getattr(instance, key) value = datetime.datetime.strftime(value, '%Y-%m-%d') elif type(f) == DateField: # 字段类型是,DateFiled 使用自己的方式操作 value = getattr(instance, key) value = datetime.datetime.strftime(value, '%Y-%m-%d') elif type(f) == CharField or type(f) == TextField: # 字符串数据是否可以进行序列化,转成python结构数据 value = getattr(instance, key) try: value = json.loads(value) except Exception as _: value = value else:#其他类型的字段 # value = getattr(instance, key) key = f.name value = f.value_from_object(instance) # data[f.name] = f.value_from_object(instance) # 1、替换字段名字 if replace and key in replace.keys(): key = replace.get(key) data[key] = value #2、新增默认的字段数据 if default: data.update(default) return data def index(request): if request.user and request.user.username!='AnonymousUser': return HttpResponseRedirect('/api/work') return HttpResponseRedirect('/api/user_action?action=login') def user_action(request): action = request.GET.get('action', '') if action == '': return if action == 'login': return user_login(request) if action == 'register': return user_register(request) def user_login(request): if request.method == 'GET': return render(request, 'login.html') username = request.POST.get('account', '') password = request.POST.get('password', '') if not username or not password: return JsonResponse({'code':0, 'msg':'出了点问题。'}) user = auth.authenticate(username=username,password=password) if user: auth.login(request, user) return JsonResponse({'code':1, 'url':'/api/work'}) else: return JsonResponse({'code':0, 'msg':'帐号或密码错误!'}) def user_register(request): info = '' if request.method == 'GET': return render(request, 'reg.html') result = { 'code':0, 'msg':'' } username = request.POST.get('user', '') password1 = request.POST.get('pwd', '') if len(username) <= 3: info = '用户名不得小于3位' result['msg'] = info return JsonResponse(result) if len(password1)<8 or len(password1)>20: info = '密码长度不符合要求, 应在8~20位。' result['msg'] = info return JsonResponse(result) user = UserProfile.objects.filter(Q(username=username)).first() if user: info = '用户名已存在。' result['msg'] = info return JsonResponse(result) user = UserProfile( username=username, password=make_password(password1), is_admin = True if UserProfile.objects.count()==0 else False, is_superuser = True if UserProfile.objects.count()==0 else False, is_active = True ) user.save() result['msg'] = info result['code'] = 1 return JsonResponse(result) def get_single_info(uid): peers = RustDeskPeer.objects.filter(Q(uid=uid)) rids = [x.rid for x in peers] peers = {x.rid:model_to_dict(x) for x in peers} #print(peers) devices = RustDesDevice.objects.filter(rid__in=rids) devices = {x.rid:x for x in devices} for rid, device in devices.items(): peers[rid]['create_time'] = device.create_time.strftime('%Y-%m-%d') peers[rid]['update_time'] = device.update_time.strftime('%Y-%m-%d') peers[rid]['version'] = device.version peers[rid]['memory'] = device.memory peers[rid]['cpu'] = device.cpu peers[rid]['os'] = device.os for rid in peers.keys(): peers[rid]['has_rhash'] = '是' if len(peers[rid]['rhash'])>1 else '否' return [v for k,v in peers.items()] def get_all_info(): devices = RustDesDevice.objects.all() peers = RustDeskPeer.objects.all() devices = {x.rid:model_to_dict2(x) for x in devices} for peer in peers: user = UserProfile.objects.filter(Q(id=peer.uid)).first() device = devices.get(peer.rid, None) if device: devices[peer.rid]['rust_user'] = user.username return [v for k,v in devices.items()] @login_required(login_url='/api/user_action?action=login') def work(request): username = request.user u = UserProfile.objects.get(username=username) single_info = get_single_info(u.id) all_info = get_all_info() print(all_info) return render(request, 'show_work.html', {'single_info':single_info, 'all_info':all_info, 'u':u}) def check_sharelink_expired(sharelink): now = datetime.datetime.now() if sharelink.create_time > now: return False if (now - sharelink.create_time).seconds <15 * 60: return False else: sharelink.is_expired = True sharelink.save() return True @login_required(login_url='/api/user_action?action=login') def share(request): peers = RustDeskPeer.objects.filter(Q(uid=request.user.id)) sharelinks = ShareLink.objects.filter(Q(uid=request.user.id) & Q(is_used=False) & Q(is_expired=False)) # 省资源:处理已过期请求,不主动定时任务轮询请求,在任意地方请求时,检查是否过期,过期则保存。 now = datetime.datetime.now() for sl in sharelinks: check_sharelink_expired(sl) sharelinks = ShareLink.objects.filter(Q(uid=request.user.id) & Q(is_used=False) & Q(is_expired=False)) peers = [{'id':ix+1, 'name':f'{p.rid}|{p.alias}'} for ix, p in enumerate(peers)] sharelinks = [{'shash':s.shash, 'is_used':s.is_used, 'is_expired':s.is_expired, 'create_time':s.create_time, 'peers':s.peers} for ix, s in enumerate(sharelinks)] if request.method == 'GET': url = request.build_absolute_uri() if url.endswith('share'): return render(request, 'share.html', {'peers':peers, 'sharelinks':sharelinks}) else: shash = url.split('/')[-1] sharelink = ShareLink.objects.filter(Q(shash=shash)) msg = '' title = '成功' if not sharelink: title = '错误' msg = f'链接{url}:
分享链接不存在或已失效。' else: sharelink = sharelink[0] if str(request.user.id) == str(sharelink.uid): title = '错误' msg = f'链接{url}:

咱就说,你不能把链接分享给自己吧?!' else: sharelink.is_used = True sharelink.save() peers = sharelink.peers peers = peers.split(',') # 自己的peers若重叠,需要跳过 peers_self_ids = [x.rid for x in RustDeskPeer.objects.filter(Q(uid=request.user.id))] peers_share = RustDeskPeer.objects.filter(rid__in=peers) peers_share_ids = [x.rid for x in peers_share] for peer in peers_share: if peer.rid in peers_self_ids: continue peer = RustDeskPeer.objects.get(rid=peer.rid) peer.id = None peer.uid = request.user.id peer.save() msg += f"{peer.rid}," msg += '已被成功获取。' return render(request, 'msg.html', {'title':msg, 'msg':msg}) else: data = request.POST.get('data', '[]') data = json.loads(data) if not data: return JsonResponse({'code':0, 'msg':'数据为空。'}) rustdesk_ids = [x['title'].split('|')[0] for x in data] rustdesk_ids = ','.join(rustdesk_ids) sharelink = ShareLink( uid=request.user.id, shash = getStrMd5(str(time.time())+salt), peers=rustdesk_ids, ) sharelink.save() return JsonResponse({'code':1, 'shash':sharelink.shash})