# 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 django.core.paginator import Paginator from django.http import HttpResponse from django.conf import settings 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 import sys from io import BytesIO import xlwt 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 %H:%M') 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): print('sdf',sys.argv) 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 == 'login': return user_login(request) elif action == 'register': return user_register(request) elif action == 'logout': return user_logout(request) else: return 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') ALLOW_REGISTRATION = settings.ALLOW_REGISTRATION result = { 'code':0, 'msg':'' } if not ALLOW_REGISTRATION: result['msg'] = '当前未开放注册,请联系管理员!' return JsonResponse(result) 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) @login_required(login_url='/api/user_action?action=login') def user_logout(request): info = '' auth.logout(request) return HttpResponseRedirect('/api/user_action?action=login') 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} now = datetime.datetime.now() 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 %H:%M') peers[rid]['version'] = device.version peers[rid]['memory'] = device.memory peers[rid]['cpu'] = device.cpu peers[rid]['os'] = device.os peers[rid]['status'] = '在线' if (now-device.update_time).seconds <=120 else '离线' 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} now = datetime.datetime.now() 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 for k, v in devices.items(): devices[k]['status'] = '在线' if (now-datetime.datetime.strptime(v['update_time'], '%Y-%m-%d %H:%M')).seconds <=120 else '离线' 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) show_type = request.GET.get('show_type', '') show_all = True if show_type == 'admin' and u.is_admin else False paginator = Paginator(get_all_info(), 15) if show_type == 'admin' and u.is_admin else Paginator(get_single_info(u.id), 15) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return render(request, 'show_work.html', {'u':u, 'show_all':show_all, 'page_obj':page_obj}) @login_required(login_url='/api/user_action?action=login') def down_peers(request): username = request.user u = UserProfile.objects.get(username=username) if not u.is_admin: print(u.is_admin) return HttpResponseRedirect('/api/work') all_info = get_all_info() f = xlwt.Workbook(encoding='utf-8') sheet1 = f.add_sheet(u'设备信息表', cell_overwrite_ok=True) all_fields = [x.name for x in RustDesDevice._meta.get_fields()] all_fields.append('rust_user') for i, one in enumerate(all_info): for j, name in enumerate(all_fields): if i == 0: # 写入列名 sheet1.write(i, j, name) sheet1.write(i+1, j, one.get(name, '-')) sio = BytesIO() f.save(sio) sio.seek(0) response = HttpResponse(sio.getvalue(), content_type='application/vnd.ms-excel') response['Content-Disposition'] = 'attachment; filename=DeviceInfo.xls' response.write(sio.getvalue()) return response 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(Q(rid__in=peers) & Q(uid=sharelink.uid)) 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_f = RustDeskPeer.objects.filter(Q(rid=peer.rid) & Q(uid=sharelink.uid)) if not peer_f: msg += f"{peer.rid}已存在," continue if len(peer_f) > 1: msg += f'{peer.rid}存在多个,已经跳过。 ' continue peer = peer_f[0] 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})